diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct')
138 files changed, 12185 insertions, 7824 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/ArchivedSoftwareProductReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/ArchivedSoftwareProductReducer.js index b484f5e0a0..9faa6ffd68 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/ArchivedSoftwareProductReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/ArchivedSoftwareProductReducer.js @@ -13,13 +13,13 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductConstants.js'; +import { actionTypes } from './SoftwareProductConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED: - return [...action.response.results]; - default: - return state; - } + switch (action.type) { + case actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED: + return [...action.response.results]; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js index 396f65f5d7..f91c8f31e3 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js @@ -13,13 +13,13 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductConstants.js'; +import { actionTypes } from './SoftwareProductConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED: - return [...action.response.results]; - default: - return state; - } + switch (action.type) { + case actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED: + return [...action.response.results]; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js index e3ea7e1907..db3cc04f76 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js @@ -13,359 +13,668 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js'; import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx'; -import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js'; -import {onboardingMethod as onboardingMethodTypes, onboardingOriginTypes} from './SoftwareProductConstants.js'; +import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js'; +import { + onboardingMethod as onboardingMethodTypes, + onboardingOriginTypes +} from './SoftwareProductConstants.js'; import SoftwareProductActionHelper from './SoftwareProductActionHelper.js'; import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js'; import PermissionsActionHelper from './../permissions/PermissionsActionHelper.js'; import RevisionsActionHelper from './../revisions/RevisionsActionHelper.js'; import HeatSetupActionHelper from './attachments/setup/HeatSetupActionHelper.js'; import { actionsEnum as versionControllerActions } from 'nfvo-components/panel/versionController/VersionControllerConstants.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; -import {CommitModalType} from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx'; -import {onboardingMethod as onboardingMethodType} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; -import {SyncStates} from 'sdc-app/common/merge/MergeEditorConstants.js'; -import {catalogItemStatuses} from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; +import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx'; +import { onboardingMethod as onboardingMethodType } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { SyncStates } from 'sdc-app/common/merge/MergeEditorConstants.js'; +import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js'; function getActiveNavigationId(screen, componentId) { - let activeItemId = componentId ? screen + '|' + componentId : screen; - return activeItemId; + let activeItemId = componentId ? screen + '|' + componentId : screen; + return activeItemId; } -const buildComponentNavigationBarGroups = ({componentId, meta}) => { - const groups = ([ - { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL + '|' + componentId, - name: i18n('General'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE + '|' + componentId, - name: i18n('Compute'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING + '|' + componentId, - name: i18n('High Availability & Load Balancing'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK + '|' + componentId, - name: i18n('Networks'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE + '|' + componentId, - name: i18n('Storage'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES + '|' + componentId, - name: i18n('Images'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES + '|' + componentId, - name: i18n('Process Details'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING + '|' + componentId, - name: i18n('Monitoring'), - disabled: false, - meta - } - ]); +const buildComponentNavigationBarGroups = ({ componentId, meta }) => { + const groups = [ + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL + + '|' + + componentId, + name: i18n('General'), + disabled: false, + meta + }, + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE + + '|' + + componentId, + name: i18n('Compute'), + disabled: false, + meta + }, + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING + + '|' + + componentId, + name: i18n('High Availability & Load Balancing'), + disabled: false, + meta + }, + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK + + '|' + + componentId, + name: i18n('Networks'), + disabled: false, + meta + }, + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE + + '|' + + componentId, + name: i18n('Storage'), + disabled: false, + meta + }, + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES + + '|' + + componentId, + name: i18n('Images'), + disabled: false, + meta + }, + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES + + '|' + + componentId, + name: i18n('Process Details'), + disabled: false, + meta + }, + { + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING + + '|' + + componentId, + name: i18n('Monitoring'), + disabled: false, + meta + } + ]; - return groups; + return groups; }; -const buildNavigationBarProps = ({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds}) => { - const {softwareProductEditor: {data: currentSoftwareProduct = {}}} = softwareProduct; - const {id, name, onboardingMethod, candidateOnboardingOrigin, onboardingOrigin} = currentSoftwareProduct; - const groups = [{ - id: id, - name: name, - items: [ - { - id: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, - name: i18n('Overview'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, - name: i18n('General'), - disabled: false, - meta - }, - { - id: enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT, - name: i18n('Deployment Flavors'), - disabled: false, - hidden: onboardingMethod !== onboardingMethodTypes.MANUAL, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES, - name: i18n('Process Details'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS, - name: i18n('Networks'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS, - name: i18n('Attachments'), - disabled: false, - hidden: !candidateOnboardingOrigin && !onboardingOrigin, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG, - name: i18n('Activity Log'), - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES, - name: i18n('Component Dependencies'), - hidden: componentsList.length <= 1, - disabled: false, - meta - }, { - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS, - name: i18n('Components'), - hidden: componentsList.length <= 0, - meta, - expanded: mapOfExpandedIds[enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS] === true && screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, - items: [ - ...componentsList.map(({id, displayName}) => ({ - id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + '|' + id, - name: displayName, - meta, - expanded: mapOfExpandedIds[enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + '|' + id] === true && screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, - items: buildComponentNavigationBarGroups({componentId: id, meta}) - })) - ] - } - ] - }]; - let activeItemId = getActiveNavigationId(screen, componentId); - return { - activeItemId, groups, disabled: !!candidateOnboardingOrigin - }; +const buildNavigationBarProps = ({ + softwareProduct, + meta, + screen, + componentId, + componentsList, + mapOfExpandedIds +}) => { + const { + softwareProductEditor: { data: currentSoftwareProduct = {} } + } = softwareProduct; + const { + id, + name, + onboardingMethod, + candidateOnboardingOrigin, + onboardingOrigin + } = currentSoftwareProduct; + const groups = [ + { + id: id, + name: name, + items: [ + { + id: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + name: i18n('Overview'), + disabled: false, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, + name: i18n('General'), + disabled: false, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT, + name: i18n('Deployment Flavors'), + disabled: false, + hidden: onboardingMethod !== onboardingMethodTypes.MANUAL, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES, + name: i18n('Process Details'), + disabled: false, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS, + name: i18n('Networks'), + disabled: false, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS, + name: i18n('Attachments'), + disabled: false, + hidden: !candidateOnboardingOrigin && !onboardingOrigin, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG, + name: i18n('Activity Log'), + disabled: false, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES, + name: i18n('Component Dependencies'), + hidden: componentsList.length <= 1, + disabled: false, + meta + }, + { + id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS, + name: i18n('Components'), + hidden: componentsList.length <= 0, + meta, + expanded: + mapOfExpandedIds[ + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + ] === true && + screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + items: [ + ...componentsList.map(({ id, displayName }) => ({ + id: + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + + '|' + + id, + name: displayName, + meta, + expanded: + mapOfExpandedIds[ + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS + + '|' + + id + ] === true && + screen !== + enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + items: buildComponentNavigationBarGroups({ + componentId: id, + meta + }) + })) + ] + } + ] + } + ]; + let activeItemId = getActiveNavigationId(screen, componentId); + return { + activeItemId, + groups, + disabled: !!candidateOnboardingOrigin + }; }; -const buildVersionControllerProps = ({softwareProduct, versions, currentVersion, permissions, userInfo, isArchived, usersList, itemPermission, isReadOnlyMode}) => { - const {softwareProductEditor = {data: {}}} = softwareProduct; - const {isValidityData = true, data: {name, onboardingMethod, candidateOnboardingOrigin}} = softwareProductEditor; - - return { - version: currentVersion, - viewableVersions: versions, - isFormDataValid: isValidityData, - permissions, - itemName: name, - itemPermission, - isReadOnlyMode, - isArchived, - userInfo, - usersList, - isManual: onboardingMethod === onboardingMethodType.MANUAL, - candidateInProcess: !!candidateOnboardingOrigin - }; +const buildVersionControllerProps = ({ + softwareProduct, + versions, + currentVersion, + permissions, + userInfo, + isArchived, + usersList, + itemPermission, + isReadOnlyMode +}) => { + const { softwareProductEditor = { data: {} } } = softwareProduct; + const { + isValidityData = true, + data: { name, onboardingMethod, candidateOnboardingOrigin } + } = softwareProductEditor; + + return { + version: currentVersion, + viewableVersions: versions, + isFormDataValid: isValidityData, + permissions, + itemName: name, + itemPermission, + isReadOnlyMode, + isArchived, + userInfo, + usersList, + isManual: onboardingMethod === onboardingMethodType.MANUAL, + candidateInProcess: !!candidateOnboardingOrigin + }; }; -function buildMeta({softwareProduct, componentId, softwareProductDependencies, isReadOnlyMode}) { - const {softwareProductEditor, softwareProductComponents, softwareProductQuestionnaire, softwareProductAttachments} = softwareProduct; - const {data: currentSoftwareProduct = {}} = softwareProductEditor; - const {version, onboardingOrigin, candidateOnboardingOrigin} = currentSoftwareProduct; - const {qdata} = softwareProductQuestionnaire; - const {heatSetup, heatSetupCache} = softwareProductAttachments; - let currentComponentMeta = {}; - if(componentId) { - const {componentEditor: {data: componentData = {} , qdata: componentQdata}} = softwareProductComponents; - currentComponentMeta = {componentData, componentQdata}; - } - const meta = {softwareProduct: currentSoftwareProduct, qdata, version, onboardingOrigin, candidateOnboardingOrigin, heatSetup, heatSetupCache, - isReadOnlyMode, currentComponentMeta, softwareProductDependencies}; - return meta; +function buildMeta({ + softwareProduct, + componentId, + softwareProductDependencies, + isReadOnlyMode +}) { + const { + softwareProductEditor, + softwareProductComponents, + softwareProductQuestionnaire, + softwareProductAttachments + } = softwareProduct; + const { data: currentSoftwareProduct = {} } = softwareProductEditor; + const { + version, + onboardingOrigin, + candidateOnboardingOrigin + } = currentSoftwareProduct; + const { qdata } = softwareProductQuestionnaire; + const { heatSetup, heatSetupCache } = softwareProductAttachments; + let currentComponentMeta = {}; + if (componentId) { + const { + componentEditor: { data: componentData = {}, qdata: componentQdata } + } = softwareProductComponents; + currentComponentMeta = { componentData, componentQdata }; + } + const meta = { + softwareProduct: currentSoftwareProduct, + qdata, + version, + onboardingOrigin, + candidateOnboardingOrigin, + heatSetup, + heatSetupCache, + isReadOnlyMode, + currentComponentMeta, + softwareProductDependencies + }; + return meta; } const mapStateToProps = ( - { - softwareProduct, - users: {usersList, userInfo}, - versionsPage: {versionsList: {versions}, permissions} - }, - { - currentScreen: {screen, itemPermission, props: {version: currentVersion, componentId, isReadOnlyMode}} - } + { + softwareProduct, + users: { usersList, userInfo }, + versionsPage: { versionsList: { versions }, permissions } + }, + { + currentScreen: { + screen, + itemPermission, + props: { version: currentVersion, componentId, isReadOnlyMode } + } + } ) => { - const {softwareProductEditor, softwareProductComponents, softwareProductDependencies} = softwareProduct; - const {mapOfExpandedIds = []} = softwareProductEditor; - const {componentsList = []} = softwareProductComponents; + const { + softwareProductEditor, + softwareProductComponents, + softwareProductDependencies + } = softwareProduct; + const { mapOfExpandedIds = [] } = softwareProductEditor; + const { componentsList = [] } = softwareProductComponents; - const meta = buildMeta({softwareProduct, componentId, softwareProductDependencies, isReadOnlyMode}); - return { - versionControllerProps: buildVersionControllerProps({ - softwareProduct, - versions, - currentVersion, - userInfo, - usersList, - isArchived: itemPermission.isArchived, - permissions, - itemPermission: {...itemPermission, isDirty: true}, - isReadOnlyMode - }), - navigationBarProps: buildNavigationBarProps({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds}), - meta - }; + const meta = buildMeta({ + softwareProduct, + componentId, + softwareProductDependencies, + isReadOnlyMode + }); + return { + versionControllerProps: buildVersionControllerProps({ + softwareProduct, + versions, + currentVersion, + userInfo, + usersList, + isArchived: itemPermission.isArchived, + permissions, + itemPermission: { ...itemPermission, isDirty: true }, + isReadOnlyMode + }), + navigationBarProps: buildNavigationBarProps({ + softwareProduct, + meta, + screen, + componentId, + componentsList, + mapOfExpandedIds + }), + meta + }; }; -const autoSaveBeforeNavigate = ({dispatch, screen, softwareProductId, version, componentId, - meta: {isReadOnlyMode, softwareProduct, qdata, - currentComponentMeta: {componentData, componentQdata}}}) => { - let promise; - if (isReadOnlyMode) { - promise = Promise.resolve(); - } else { - switch(screen) { - case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS: - promise = SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, version, qdata}); - break; - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL: - promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch, - {softwareProductId, version, vspComponentId: componentId, componentData, qdata: componentQdata}); - break; - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE: - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE: - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK: - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES: - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING: - promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata: componentQdata}); - break; - default: - promise = Promise.resolve(); - break; - } - } - return promise; +const autoSaveBeforeNavigate = ({ + dispatch, + screen, + softwareProductId, + version, + componentId, + meta: { + isReadOnlyMode, + softwareProduct, + qdata, + currentComponentMeta: { componentData, componentQdata } + } +}) => { + let promise; + if (isReadOnlyMode) { + promise = Promise.resolve(); + } else { + switch (screen) { + case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS: + promise = SoftwareProductActionHelper.updateSoftwareProduct( + dispatch, + { softwareProduct, version, qdata } + ); + break; + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL: + promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponent( + dispatch, + { + softwareProductId, + version, + vspComponentId: componentId, + componentData, + qdata: componentQdata + } + ); + break; + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE: + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE: + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK: + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES: + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING: + promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire( + dispatch, + { + softwareProductId, + version, + vspComponentId: componentId, + qdata: componentQdata + } + ); + break; + default: + promise = Promise.resolve(); + break; + } + } + return promise; }; +const mapActionsToProps = ( + dispatch, + { + currentScreen: { + screen, + props: { + softwareProductId, + licenseModelId, + version, + componentId: currentComponentId + } + } + } +) => { + const props = { + onVersionSwitching: (versionToSwitch, meta) => { + ScreensHelper.loadScreen(dispatch, { + screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { + softwareProductId: meta.softwareProduct.id, + version: versionToSwitch + } + }); + }, + onOpenPermissions: ({ users }) => { + return PermissionsActionHelper.fetchItemUsers(dispatch, { + itemId: softwareProductId, + allUsers: users + }); + }, + onOpenRevisionsModal: () => { + return RevisionsActionHelper.openRevisionsView(dispatch, { + itemId: softwareProductId, + version: version, + itemType: screenTypes.SOFTWARE_PRODUCT + }); + }, + onOpenCommentCommitModal: ({ onCommit, title }) => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: modalContentMapper.COMMIT_COMMENT, + modalComponentProps: { + onCommit, + type: CommitModalType.COMMIT + }, + title + } + }), + onMoreVersionsClick: ({ itemName, users }) => { + ScreensHelper.loadScreen(dispatch, { + screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { + softwareProductId, + softwareProduct: { + name: itemName, + vendorId: licenseModelId + }, + usersList: users + } + }); + }, + onToggle: (groups, itemIdToExpand) => + groups.map(({ items }) => + SoftwareProductActionHelper.toggleNavigationItems(dispatch, { + items, + itemIdToExpand + }) + ), + onNavigate: ({ id, meta, newVersion }) => { + let navigationVersion = newVersion || version; + let { + onboardingOrigin, + candidateOnboardingOrigin, + heatSetup, + heatSetupCache + } = meta; + let heatSetupPopupPromise = + screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS + ? HeatSetupActionHelper.heatSetupLeaveConfirmation( + dispatch, + { softwareProductId, heatSetup, heatSetupCache } + ) + : Promise.resolve(); + let preNavigate = meta + ? autoSaveBeforeNavigate({ + dispatch, + screen, + meta, + version, + softwareProductId, + componentId: currentComponentId + }) + : Promise.resolve(); + version = version || (meta ? meta.version : undefined); + Promise.all([preNavigate, heatSetupPopupPromise]) + .then(() => { + let [nextScreen, nextComponentId] = id.split('|'); + if ( + nextScreen === + enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS && + nextComponentId && + nextComponentId === currentComponentId + ) { + ScreensHelper.loadScreen(dispatch, { + screen: nextScreen, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { + softwareProductId, + version: navigationVersion + } + }); + } else { + if ( + nextScreen === + enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS + ) { + if ( + onboardingOrigin === + onboardingOriginTypes.ZIP || + candidateOnboardingOrigin === + onboardingOriginTypes.ZIP + ) { + nextScreen = + enums.SCREEN + .SOFTWARE_PRODUCT_ATTACHMENTS_SETUP; + } else if ( + onboardingOrigin === onboardingOriginTypes.CSAR + ) { + nextScreen = + enums.SCREEN + .SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION; + } + } + ScreensHelper.loadScreen(dispatch, { + screen: nextScreen, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { + softwareProductId, + version: navigationVersion, + componentId: nextComponentId + } + }); + } + }) + .catch(e => { + console.error(e); + }); + } + }; -const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {softwareProductId, licenseModelId, version, componentId: currentComponentId}}}) => { - - const props = { - onVersionSwitching: (versionToSwitch, meta) => { - ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId: meta.softwareProduct.id, version: versionToSwitch}}); - }, - onOpenPermissions: ({users}) => { - return PermissionsActionHelper.fetchItemUsers(dispatch, {itemId: softwareProductId, allUsers: users}); - }, - onOpenRevisionsModal: () => { - return RevisionsActionHelper.openRevisionsView(dispatch, {itemId: softwareProductId, version: version, itemType: screenTypes.SOFTWARE_PRODUCT}); - }, - onOpenCommentCommitModal: ({onCommit, title}) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.COMMIT_COMMENT, - modalComponentProps: { - onCommit, - type: CommitModalType.COMMIT - }, - title - } - }), - onMoreVersionsClick: ({itemName, users}) => { - ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, softwareProduct: {name: itemName, vendorId: licenseModelId}, usersList: users}}); - - }, - onToggle: (groups, itemIdToExpand) => groups.map(({items}) => SoftwareProductActionHelper.toggleNavigationItems(dispatch, {items, itemIdToExpand})), - onNavigate: ({id, meta, newVersion}) => { - let navigationVersion = newVersion || version; - let {onboardingOrigin, candidateOnboardingOrigin, heatSetup, heatSetupCache} = meta; - let heatSetupPopupPromise = screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS ? - HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) : - Promise.resolve(); - let preNavigate = meta ? autoSaveBeforeNavigate({dispatch, screen, meta, version, softwareProductId, componentId: currentComponentId}) : Promise.resolve(); - version = version || (meta ? meta.version : undefined); - Promise.all([preNavigate, heatSetupPopupPromise]).then(() => { - let [nextScreen, nextComponentId] = id.split('|'); - if(nextScreen === enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS && nextComponentId && nextComponentId === currentComponentId) { - ScreensHelper.loadScreen(dispatch, { - screen: nextScreen, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version: navigationVersion} - }); - } - else { - if(nextScreen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS) { - if(onboardingOrigin === onboardingOriginTypes.ZIP || candidateOnboardingOrigin === onboardingOriginTypes.ZIP) { - nextScreen = enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP; - } - else if(onboardingOrigin === onboardingOriginTypes.CSAR) { - nextScreen = enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION; - } - } - ScreensHelper.loadScreen(dispatch, { - screen: nextScreen, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version: navigationVersion, componentId: nextComponentId} - }); - } - }).catch((e) => {console.error(e);}); - } - }; - - switch (screen) { - case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE: - case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS: - case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES: - case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS: - case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES: - case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG: - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS: - case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT: - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES: - case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING: - props.onSave = () => Promise.resolve(); - break; - default: - props.onSave = ({softwareProduct, qdata}) => SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, qdata, version}); - break; - } - + switch (screen) { + case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE: + case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS: + case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES: + case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS: + case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES: + case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG: + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS: + case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT: + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES: + case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING: + props.onSave = () => Promise.resolve(); + break; + default: + props.onSave = ({ softwareProduct, qdata }) => + SoftwareProductActionHelper.updateSoftwareProduct(dispatch, { + softwareProduct, + qdata, + version + }); + break; + } - props.onVersionControllerAction = (action, version, comment, meta) => { - let {heatSetup, heatSetupCache} = meta; - let autoSavePromise = meta ? autoSaveBeforeNavigate({dispatch, screen, meta, version, softwareProductId, componentId: currentComponentId}) : Promise.resolve(); - let heatSetupPopupPromise = screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS && action === versionControllerActions.COMMIT ? - HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) : - Promise.resolve(); - Promise.all([autoSavePromise, heatSetupPopupPromise]).then(() => { - return SoftwareProductActionHelper.performVCAction(dispatch, {softwareProductId, action, version, comment, meta}).then(updatedVersion => { - const inMerge = updatedVersion && updatedVersion.state && updatedVersion.state.synchronizationState === SyncStates.MERGE; - if((action === versionControllerActions.SYNC && !inMerge) || - ((action === versionControllerActions.COMMIT || action === versionControllerActions.SYNC) && updatedVersion.status === catalogItemStatuses.CERTIFIED)) { - ScreensHelper.loadLandingScreen(dispatch, {previousScreenName: screen, props: {softwareProductId, version: updatedVersion}}); - } else { - ScreensHelper.loadScreen(dispatch, {screen, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version: updatedVersion, componentId: currentComponentId}}); - } - }); - }).catch((e) => {console.error(e);}); - }; + props.onVersionControllerAction = (action, version, comment, meta) => { + let { heatSetup, heatSetupCache } = meta; + let autoSavePromise = meta + ? autoSaveBeforeNavigate({ + dispatch, + screen, + meta, + version, + softwareProductId, + componentId: currentComponentId + }) + : Promise.resolve(); + let heatSetupPopupPromise = + screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS && + action === versionControllerActions.COMMIT + ? HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, { + softwareProductId, + heatSetup, + heatSetupCache + }) + : Promise.resolve(); + Promise.all([autoSavePromise, heatSetupPopupPromise]) + .then(() => { + return SoftwareProductActionHelper.performVCAction(dispatch, { + softwareProductId, + action, + version, + comment, + meta + }).then(updatedVersion => { + const inMerge = + updatedVersion && + updatedVersion.state && + updatedVersion.state.synchronizationState === + SyncStates.MERGE; + if ( + (action === versionControllerActions.SYNC && + !inMerge) || + ((action === versionControllerActions.COMMIT || + action === versionControllerActions.SYNC) && + updatedVersion.status === + catalogItemStatuses.CERTIFIED) + ) { + ScreensHelper.loadLandingScreen(dispatch, { + previousScreenName: screen, + props: { + softwareProductId, + version: updatedVersion + } + }); + } else { + ScreensHelper.loadScreen(dispatch, { + screen, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { + softwareProductId, + version: updatedVersion, + componentId: currentComponentId + } + }); + } + }); + }) + .catch(e => { + console.error(e); + }); + }; - props.onManagePermissions = () => PermissionsActionHelper.openPermissonsManager(dispatch, {itemId: softwareProductId, askForRights: false}); - return props; + props.onManagePermissions = () => + PermissionsActionHelper.openPermissonsManager(dispatch, { + itemId: softwareProductId, + askForRights: false + }); + return props; }; export default connect(mapStateToProps, mapActionsToProps)(TabulatedEditor); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js index 42786bf752..4a2d7a2ece 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js @@ -21,553 +21,769 @@ import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseMod import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js'; import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js'; -import {actionTypes, onboardingOriginTypes, PRODUCT_QUESTIONNAIRE, forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { + actionTypes, + onboardingOriginTypes, + PRODUCT_QUESTIONNAIRE, + forms +} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js'; import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js'; -import {actionsEnum as VersionControllerActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js'; -import {actionTypes as HeatSetupActions} from 'sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js'; -import {actionTypes as featureGroupsActionConstants} from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js'; -import {actionTypes as licenseAgreementActionTypes} from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js'; -import {actionTypes as componentActionTypes} from './components/SoftwareProductComponentsConstants.js'; +import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js'; +import { actionTypes as HeatSetupActions } from 'sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js'; +import { actionTypes as featureGroupsActionConstants } from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js'; +import { actionTypes as licenseAgreementActionTypes } from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js'; +import { actionTypes as componentActionTypes } from './components/SoftwareProductComponentsConstants.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; -import {default as ItemsHelper} from 'sdc-app/common/helpers/ItemsHelper.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; +import { default as ItemsHelper } from 'sdc-app/common/helpers/ItemsHelper.js'; import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js'; -import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js'; +import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js'; import MergeEditorActionHelper from 'sdc-app/common/merge/MergeEditorActionHelper.js'; -import {CommitModalType} from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx'; -import {actionTypes as commonActionTypes} from 'sdc-app/common/reducers/PlainDataReducerConstants.js'; +import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx'; +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 { 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'; function getLicensingData(licensingData = {}) { - const {licenseAgreement, featureGroups} = licensingData; - const newlicenseAgreement = getValue(licenseAgreement); - const newfeatureGroups = getValue(featureGroups); - return newlicenseAgreement ? { - licenseAgreement: newlicenseAgreement, - featureGroups: newfeatureGroups - } : undefined; -}; + const { licenseAgreement, featureGroups } = licensingData; + const newlicenseAgreement = getValue(licenseAgreement); + const newfeatureGroups = getValue(featureGroups); + return newlicenseAgreement + ? { + licenseAgreement: newlicenseAgreement, + featureGroups: newfeatureGroups + } + : undefined; +} function baseUrl() { - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/`; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/`; } function softwareProductCategoriesUrl() { - const restCatalogPrefix = Configuration.get('restCatalogPrefix'); - return `${restCatalogPrefix}/v1/categories/resources/`; + const restCatalogPrefix = Configuration.get('restCatalogPrefix'); + return `${restCatalogPrefix}/v1/categories/resources/`; } function uploadFile(vspId, formData, version) { - return RestAPIUtil.post(`${baseUrl()}${vspId}/versions/${version.id}/orchestration-template-candidate`, formData); - + return RestAPIUtil.post( + `${baseUrl()}${vspId}/versions/${ + version.id + }/orchestration-template-candidate`, + formData + ); } -function putSoftwareProduct({softwareProduct, version}) { - return RestAPIUtil.put(`${baseUrl()}${softwareProduct.id}/versions/${version.id}`, { - name: softwareProduct.name, - description: softwareProduct.description, - category: softwareProduct.category, - subCategory: softwareProduct.subCategory, - vendorId: softwareProduct.vendorId, - vendorName: softwareProduct.vendorName, - licensingVersion: softwareProduct.licensingVersion ? softwareProduct.licensingVersion : undefined, - icon: softwareProduct.icon, - licensingData: getLicensingData(softwareProduct.licensingData) - }); +function putSoftwareProduct({ softwareProduct, version }) { + return RestAPIUtil.put( + `${baseUrl()}${softwareProduct.id}/versions/${version.id}`, + { + name: softwareProduct.name, + description: softwareProduct.description, + category: softwareProduct.category, + subCategory: softwareProduct.subCategory, + vendorId: softwareProduct.vendorId, + vendorName: softwareProduct.vendorName, + licensingVersion: softwareProduct.licensingVersion + ? softwareProduct.licensingVersion + : undefined, + icon: softwareProduct.icon, + licensingData: getLicensingData(softwareProduct.licensingData) + } + ); } function putSoftwareProductQuestionnaire(vspId, qdata, version) { - return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/questionnaire`, qdata); + return RestAPIUtil.put( + `${baseUrl()}${vspId}/versions/${version.id}/questionnaire`, + qdata + ); } function putSoftwareProductAction(id, action, version) { - return RestAPIUtil.put(`${baseUrl()}${id}/versions/${version.id}/actions`, {action: action}); + return RestAPIUtil.put(`${baseUrl()}${id}/versions/${version.id}/actions`, { + action: action + }); } function fetchSoftwareProductList() { - return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}`); + return RestAPIUtil.fetch( + `${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}` + ); } function fetchArchivedSoftwareProductList() { - return RestAPIUtil.fetch(`${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}`); + return RestAPIUtil.fetch( + `${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}` + ); } function fetchFinalizedSoftwareProductList() { - return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}`); + return RestAPIUtil.fetch( + `${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}` + ); } function fetchSoftwareProduct(vspId, version) { - return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}`); + return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}`); } function fetchSoftwareProductQuestionnaire(vspId, version) { - return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}/questionnaire`); + return RestAPIUtil.fetch( + `${baseUrl()}${vspId}/versions/${version.id}/questionnaire` + ); } -function updateSoftwareProductHeatCandidate(softwareProductId, heatCandidate, version) { - return RestAPIUtil.put(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/manifest`, heatCandidate); +function updateSoftwareProductHeatCandidate( + softwareProductId, + heatCandidate, + version +) { + return RestAPIUtil.put( + `${baseUrl()}${softwareProductId}/versions/${ + version.id + }/orchestration-template-candidate/manifest`, + heatCandidate + ); } function validateHeatCandidate(softwareProductId, version) { - return RestAPIUtil.put(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/process`); + return RestAPIUtil.put( + `${baseUrl()}${softwareProductId}/versions/${ + version.id + }/orchestration-template-candidate/process` + ); } -function fetchOrchestrationTemplateCandidate(softwareProductId, version, ) { - return RestAPIUtil.fetch(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate`, {dataType: 'binary'}); +function fetchOrchestrationTemplateCandidate(softwareProductId, version) { + return RestAPIUtil.fetch( + `${baseUrl()}${softwareProductId}/versions/${ + version.id + }/orchestration-template-candidate`, + { dataType: 'binary' } + ); } function abortValidationProcess(softwareProductId, version) { - return RestAPIUtil.destroy(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate`); + return RestAPIUtil.destroy( + `${baseUrl()}${softwareProductId}/versions/${ + version.id + }/orchestration-template-candidate` + ); } function objToString(obj) { - let str = ''; - if (obj instanceof Array) { - obj.forEach((item) => { - str += objToString(item) + '\n'; - }); - } - else { - for (let p in obj) { - if (obj.hasOwnProperty(p)) { - str += obj[p] + '\n'; - } - } - } - return str.replace(/\n$/, ''); + let str = ''; + if (obj instanceof Array) { + obj.forEach(item => { + str += objToString(item) + '\n'; + }); + } else { + for (let p in obj) { + if (obj.hasOwnProperty(p)) { + str += obj[p] + '\n'; + } + } + } + return str.replace(/\n$/, ''); } function parseUploadErrorMsg(error) { - let message = ''; - for (let key in error) { - if (error.hasOwnProperty(key)) { - message += objToString(error[key]) + '\n'; - } - } - return message.replace(/\n$/, ''); + let message = ''; + for (let key in error) { + if (error.hasOwnProperty(key)) { + message += objToString(error[key]) + '\n'; + } + } + return message.replace(/\n$/, ''); } function fetchSoftwareProductCategories(dispatch) { - let handleResponse = response => dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED, - softwareProductCategories: response - }); - return RestAPIUtil.fetch(softwareProductCategoriesUrl()) - .then(handleResponse) - .catch(() => handleResponse(null)); + let handleResponse = response => + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED, + softwareProductCategories: response + }); + return RestAPIUtil.fetch(softwareProductCategoriesUrl()) + .then(handleResponse) + .catch(() => handleResponse(null)); } -function loadLicensingData(dispatch, {licenseModelId, licensingVersion}) { - return ItemsHelper.fetchVersion({itemId: licenseModelId, versionId: licensingVersion}).then(() => { - return Promise.all([ - LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: {id: licensingVersion}}), - FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version: {id: licensingVersion}}) - ]); - }); +function loadLicensingData(dispatch, { licenseModelId, licensingVersion }) { + return ItemsHelper.fetchVersion({ + itemId: licenseModelId, + versionId: licensingVersion + }).then(() => { + return Promise.all([ + LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, { + licenseModelId, + version: { id: licensingVersion } + }), + FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, { + licenseModelId, + version: { id: licensingVersion } + }) + ]); + }); } function getExpandedItemsId(items, itemIdToToggle) { - for (let i = 0; i < items.length; i++) { - if (items[i].id === itemIdToToggle) { - if (items[i].expanded) { - return {}; - } - else { - return {[itemIdToToggle]: true}; - } - } - else if (items[i].items && items[i].items.length > 0) { - let mapOfExpandedIds = getExpandedItemsId(items[i].items, itemIdToToggle); - if (mapOfExpandedIds !== false) { - mapOfExpandedIds[items[i].id] = true; - return mapOfExpandedIds; - } - } - } - return false; + for (let i = 0; i < items.length; i++) { + if (items[i].id === itemIdToToggle) { + if (items[i].expanded) { + return {}; + } else { + return { [itemIdToToggle]: true }; + } + } else if (items[i].items && items[i].items.length > 0) { + let mapOfExpandedIds = getExpandedItemsId( + items[i].items, + itemIdToToggle + ); + if (mapOfExpandedIds !== false) { + mapOfExpandedIds[items[i].id] = true; + return mapOfExpandedIds; + } + } + } + return false; } function migrateSoftwareProduct(vspId, version) { - return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/heal`); + return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/heal`); } - - const SoftwareProductActionHelper = { - - fetchFinalizedSoftwareProductList(dispatch) { - return fetchFinalizedSoftwareProductList().then(response => dispatch({ - type: actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED, - response - })); - }, - - fetchArchivedSoftwareProductList(dispatch) { - return fetchArchivedSoftwareProductList().then(response => dispatch({ - type: actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED, - response - })); - }, - - loadSoftwareProductAssociatedData(dispatch) { - fetchSoftwareProductCategories(dispatch); - LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch); - }, - - loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion}) { - SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch); - if (licensingVersion) { - return loadLicensingData(dispatch, {licenseModelId, licensingVersion}); - } - return Promise.resolve(); - }, - - fetchSoftwareProductList(dispatch) { - return fetchSoftwareProductList().then(response => dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_LIST_LOADED, - response - })); - }, - - loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version}){ - return RestAPIUtil.fetch(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/manifest`).then(response => dispatch({ - type: HeatSetupActions.MANIFEST_LOADED, - response - })); - }, - - loadLicensingVersionsList(dispatch, {licenseModelId}){ - return ItemsHelper.fetchVersions({itemId: licenseModelId}).then(response => { - dispatch({ - type: actionTypes.LOAD_LICENSING_VERSIONS_LIST, - licensingVersionsList: response.results - }); - }); - }, - updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version}){ - return updateSoftwareProductHeatCandidate(softwareProductId, heatCandidate, version); - }, - - processAndValidateHeatCandidate(dispatch, {softwareProductId, version}){ - return validateHeatCandidate(softwareProductId, version).then(response => { - if (response.status === 'Success') { - SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version}); - SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version}); - } else { - SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version}); - } - }); - }, - - uploadFile(dispatch, {softwareProductId, formData, failedNotificationTitle, version}) { - dispatch({ - type: HeatSetupActions.FILL_HEAT_SETUP_CACHE, - payload: {} - }); - - Promise.resolve() - .then(() => uploadFile(softwareProductId, formData, version)) - .then(response => { - if (response.status === 'Success') { - dispatch({ - type: commonActionTypes.DATA_CHANGED, - deltaData: {onboardingOrigin: response.onboardingOrigin}, - formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS - }); - switch(response.onboardingOrigin){ - case onboardingOriginTypes.ZIP: - ScreensHelper.loadScreen(dispatch, { - screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version} - }); - dispatch({ - type: actionTypes.CANDIDATE_IN_PROCESS, - inProcess: true - }); - break; - case onboardingOriginTypes.CSAR: - ScreensHelper.loadScreen(dispatch, { - screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version} - }); - break; - } - } - else { - throw new Error(parseUploadErrorMsg(response.errors)); - } - }) - .catch(error => { - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_ERROR, - data: { - title: failedNotificationTitle, - msg: error.message || (error.responseJSON && error.responseJSON.message) - } - }); - }); - }, - - downloadHeatFile(dispatch, {softwareProductId, heatCandidate, isReadOnlyMode, version}){ - let p = isReadOnlyMode ? Promise.resolve() : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, { - softwareProductId, - heatCandidate, - version}); - p.then(() => { - fetchOrchestrationTemplateCandidate(softwareProductId, version) - .then((response) => { - showFileSaveDialog({ - blob: response.blob, - headers: response.headers, - defaultFilename: 'HEAT_file.zip', - addTimestamp: true - }); - }); - }, null/* do not download if data was not saved correctly*/); - }, - - hideUploadConfirm (dispatch) { - dispatch({ - type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION - }); - }, - updateSoftwareProduct(dispatch, {softwareProduct, version, qdata}) { - return Promise.all([ - SoftwareProductActionHelper.updateSoftwareProductData(dispatch, {softwareProduct, version}).then( - () => dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_LIST_EDIT, - payload: {softwareProduct} - }) - ), - SoftwareProductActionHelper.updateSoftwareProductQuestionnaire(dispatch, { - softwareProductId: softwareProduct.id, - qdata, - version - }) - ]); - }, - - updateSoftwareProductData(dispatch, {softwareProduct, version}) { - return putSoftwareProduct({softwareProduct, version}); - }, - - updateSoftwareProductQuestionnaire(dispatch, {softwareProductId, qdata, version}) { - return putSoftwareProductQuestionnaire(softwareProductId, qdata, version); - }, - - softwareProductEditorDataChanged(dispatch, {deltaData}) { - dispatch({ - type: actionTypes.softwareProductEditor.DATA_CHANGED, - deltaData - }); - }, - - softwareProductQuestionnaireUpdate(dispatch, {data}) { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE, - payload: {qdata: data} - }); - }, - - softwareProductEditorVendorChanged(dispatch, {deltaData, formName}) { - if (deltaData.licensingVersion){ - return loadLicensingData(dispatch, {licenseModelId: deltaData.vendorId, licensingVersion: deltaData.licensingVersion}).then(() => { - ValidationHelper.dataChanged(dispatch, {deltaData, formName}); - return Promise.resolve(); - }); - } else if (deltaData.vendorId) { - ValidationHelper.dataChanged(dispatch, {deltaData, formName}); - return SoftwareProductActionHelper.loadLicensingVersionsList(dispatch, { - licenseModelId: deltaData.vendorId - }).then( () => - OnboardingActionHelper.forceBreadCrumbsUpdate(dispatch) - ); - } else { - ValidationHelper.dataChanged(dispatch, {deltaData, formName}); - - dispatch({ - type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED, - response: {results: []} - }); - - dispatch({ - type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED, - response: {results: []} - }); - } - - }, - - setIsValidityData(dispatch, {isValidityData}) { - dispatch({ - type: actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED, - isValidityData - }); - }, - - fetchSoftwareProduct(dispatch, {softwareProductId, version}) { - return Promise.all([ - fetchSoftwareProduct(softwareProductId, version).then(response => { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_LOADED, - response - }); - return response; - }), - fetchSoftwareProductQuestionnaire(softwareProductId, version).then(response => { - ValidationHelper.qDataLoaded(dispatch, {response: {qdata: response.data ? JSON.parse(response.data) : {}, - qschema: JSON.parse(response.schema)}, qName: PRODUCT_QUESTIONNAIRE}); - }) - ]); - }, - - manageSubmitAction(dispatch, {softwareProductId, version, isDirty}) { - if (isDirty) { - const onCommit = comment => { - return this.performVCAction(dispatch, {softwareProductId, action: VersionControllerActionsEnum.COMMIT, version, comment}).then(() => { - return this.performSubmitAction(dispatch, {softwareProductId, version}); - }); - }; - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.COMMIT_COMMENT, - modalComponentProps: { - onCommit, - type: CommitModalType.COMMIT_SUBMIT - }, - title: i18n('Commit & Submit') - } - }); - return Promise.resolve(version); - } - return this.performSubmitAction(dispatch, {softwareProductId, version}); - }, - - performSubmitAction(dispatch, {softwareProductId, version}) { - return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.SUBMIT, version).then(() => { - return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.CREATE_PACKAGE, version).then(() => { - return ItemsHelper.checkItemStatus(dispatch, {itemId: softwareProductId, versionId: version.id}).then(updatedVersion => { - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SUCCESS, - data: { - title: i18n('Submit Succeeded'), - msg: i18n('This software product successfully submitted'), - cancelButtonText: i18n('OK'), - timeout: 2000 - } - }); - versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.SOFTWARE_PRODUCT, itemId: softwareProductId}); - return Promise.resolve(updatedVersion); - }); - }); - }, error => - { - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_ERROR, - data: { - modalComponentName: modalContentMapper.SUMBIT_ERROR_RESPONSE, - title: i18n('Submit Failed'), - modalComponentProps: { - validationResponse: error.responseJSON - }, - cancelButtonText: i18n('OK') - } - }); - return Promise.reject(error.responseJSON); - }); - }, - - performVCAction(dispatch, {softwareProductId, action, version, comment}) { - return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: softwareProductId, version}).then(({inMerge, isDirty, updatedVersion}) => { - if ((updatedVersion.status === catalogItemStatuses.CERTIFIED || updatedVersion.archivedStatus === catalogItemStatuses.ARCHIVED) && - (action === VersionControllerActionsEnum.COMMIT || action === VersionControllerActionsEnum.SYNC)) { - versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.SOFTWARE_PRODUCT, itemId: softwareProductId}); - const msg = updatedVersion.archivedStatus === catalogItemStatuses.ARCHIVED ? i18n('Item was Archived') : i18n('Item version already Certified'); - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data: { - title: i18n('Commit error'), - msg, - cancelButtonText: i18n('Cancel') - } - }); - return Promise.resolve(updatedVersion); - } - if (!inMerge) { - if (action === VersionControllerActionsEnum.SUBMIT) { - return this.manageSubmitAction(dispatch, {softwareProductId, version, isDirty}); - } - else { - let isCallActionValid = action !== VersionControllerActionsEnum.COMMIT || isDirty; - if(isCallActionValid) { - return ItemsHelper.performVCAction({itemId: softwareProductId, action, version, comment}).then(() => { - versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: softwareProductId}); - if (action === VersionControllerActionsEnum.SYNC) { - return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: softwareProductId, version}).then(({updatedVersion}) => { - return Promise.resolve(updatedVersion); - }); - } else { - return ItemsHelper.checkItemStatus(dispatch, {itemId: softwareProductId, versionId: version.id}); - } - }); - } - else { - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_ERROR, - data: { - title: i18n('Commit Failed'), - msg: i18n('There is nothing to commit') - } - }); - } - } - } - }); - }, - - toggleNavigationItems(dispatch, {items, itemIdToExpand}) { - let mapOfExpandedIds = getExpandedItemsId(items, itemIdToExpand); - dispatch({ - type: actionTypes.TOGGLE_NAVIGATION_ITEM, - mapOfExpandedIds - }); - }, - - /** for the next verision */ - addComponent(dispatch, {softwareProductId, modalClassName, version}) { - SoftwareProductComponentsActionHelper.clearComponentCreationData(dispatch); - dispatch({ - type: componentActionTypes.COMPONENT_CREATE_OPEN - }); - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.COMPONENT_CREATION, - modalComponentProps: {softwareProductId, version}, - modalClassName, - title: 'Create Virtual Function Component' - } - }); - }, - - migrateSoftwareProduct(dispatch, {softwareProduct}) { - let {id: softwareProductId, version} = softwareProduct; - const newVer = version.id; - migrateSoftwareProduct(softwareProductId, version).then(() => ScreensHelper.loadScreen(dispatch, { - screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version: {id: newVer, label: newVer}} - })); - }, - - abortCandidateValidation(dispatch, {softwareProductId, version}) { - return abortValidationProcess(softwareProductId, version); - } - + fetchFinalizedSoftwareProductList(dispatch) { + return fetchFinalizedSoftwareProductList().then(response => + dispatch({ + type: actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED, + response + }) + ); + }, + + fetchArchivedSoftwareProductList(dispatch) { + return fetchArchivedSoftwareProductList().then(response => + dispatch({ + type: actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED, + response + }) + ); + }, + + loadSoftwareProductAssociatedData(dispatch) { + fetchSoftwareProductCategories(dispatch); + LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch); + }, + + loadSoftwareProductDetailsData( + dispatch, + { licenseModelId, licensingVersion } + ) { + SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch); + if (licensingVersion) { + return loadLicensingData(dispatch, { + licenseModelId, + licensingVersion + }); + } + return Promise.resolve(); + }, + + fetchSoftwareProductList(dispatch) { + return fetchSoftwareProductList().then(response => + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_LIST_LOADED, + response + }) + ); + }, + + loadSoftwareProductHeatCandidate(dispatch, { softwareProductId, version }) { + return RestAPIUtil.fetch( + `${baseUrl()}${softwareProductId}/versions/${ + version.id + }/orchestration-template-candidate/manifest` + ).then(response => + dispatch({ + type: HeatSetupActions.MANIFEST_LOADED, + response + }) + ); + }, + + loadLicensingVersionsList(dispatch, { licenseModelId }) { + return ItemsHelper.fetchVersions({ itemId: licenseModelId }).then( + response => { + dispatch({ + type: actionTypes.LOAD_LICENSING_VERSIONS_LIST, + licensingVersionsList: response.results + }); + } + ); + }, + updateSoftwareProductHeatCandidate( + dispatch, + { softwareProductId, heatCandidate, version } + ) { + return updateSoftwareProductHeatCandidate( + softwareProductId, + heatCandidate, + version + ); + }, + + processAndValidateHeatCandidate(dispatch, { softwareProductId, version }) { + return validateHeatCandidate(softwareProductId, version).then( + response => { + if (response.status === 'Success') { + SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents( + dispatch, + { softwareProductId, version } + ); + SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, { + softwareProductId, + version + }); + } else { + SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, { + softwareProductId, + version + }); + } + } + ); + }, + + uploadFile( + dispatch, + { softwareProductId, formData, failedNotificationTitle, version } + ) { + dispatch({ + type: HeatSetupActions.FILL_HEAT_SETUP_CACHE, + payload: {} + }); + + Promise.resolve() + .then(() => uploadFile(softwareProductId, formData, version)) + .then(response => { + if (response.status === 'Success') { + dispatch({ + type: commonActionTypes.DATA_CHANGED, + deltaData: { + onboardingOrigin: response.onboardingOrigin + }, + formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + }); + switch (response.onboardingOrigin) { + case onboardingOriginTypes.ZIP: + ScreensHelper.loadScreen(dispatch, { + screen: + enums.SCREEN + .SOFTWARE_PRODUCT_ATTACHMENTS_SETUP, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version } + }); + dispatch({ + type: actionTypes.CANDIDATE_IN_PROCESS, + inProcess: true + }); + break; + case onboardingOriginTypes.CSAR: + ScreensHelper.loadScreen(dispatch, { + screen: + enums.SCREEN + .SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version } + }); + break; + } + } else { + throw new Error(parseUploadErrorMsg(response.errors)); + } + }) + .catch(error => { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + title: failedNotificationTitle, + msg: + error.message || + (error.responseJSON && error.responseJSON.message) + } + }); + }); + }, + + downloadHeatFile( + dispatch, + { softwareProductId, heatCandidate, isReadOnlyMode, version } + ) { + let p = isReadOnlyMode + ? Promise.resolve() + : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate( + dispatch, + { + softwareProductId, + heatCandidate, + version + } + ); + p.then(() => { + fetchOrchestrationTemplateCandidate( + softwareProductId, + version + ).then(response => { + showFileSaveDialog({ + blob: response.blob, + headers: response.headers, + defaultFilename: 'HEAT_file.zip', + addTimestamp: true + }); + }); + }, null /* do not download if data was not saved correctly*/); + }, + + hideUploadConfirm(dispatch) { + dispatch({ + type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION + }); + }, + updateSoftwareProduct(dispatch, { softwareProduct, version, qdata }) { + return Promise.all([ + SoftwareProductActionHelper.updateSoftwareProductData(dispatch, { + softwareProduct, + version + }).then(() => + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_LIST_EDIT, + payload: { softwareProduct } + }) + ), + SoftwareProductActionHelper.updateSoftwareProductQuestionnaire( + dispatch, + { + softwareProductId: softwareProduct.id, + qdata, + version + } + ) + ]); + }, + + updateSoftwareProductData(dispatch, { softwareProduct, version }) { + return putSoftwareProduct({ softwareProduct, version }); + }, + + updateSoftwareProductQuestionnaire( + dispatch, + { softwareProductId, qdata, version } + ) { + return putSoftwareProductQuestionnaire( + softwareProductId, + qdata, + version + ); + }, + + softwareProductEditorDataChanged(dispatch, { deltaData }) { + dispatch({ + type: actionTypes.softwareProductEditor.DATA_CHANGED, + deltaData + }); + }, + + softwareProductQuestionnaireUpdate(dispatch, { data }) { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE, + payload: { qdata: data } + }); + }, + + softwareProductEditorVendorChanged(dispatch, { deltaData, formName }) { + if (deltaData.licensingVersion) { + return loadLicensingData(dispatch, { + licenseModelId: deltaData.vendorId, + licensingVersion: deltaData.licensingVersion + }).then(() => { + ValidationHelper.dataChanged(dispatch, { deltaData, formName }); + return Promise.resolve(); + }); + } else if (deltaData.vendorId) { + ValidationHelper.dataChanged(dispatch, { deltaData, formName }); + return SoftwareProductActionHelper.loadLicensingVersionsList( + dispatch, + { + licenseModelId: deltaData.vendorId + } + ).then(() => + OnboardingActionHelper.forceBreadCrumbsUpdate(dispatch) + ); + } else { + ValidationHelper.dataChanged(dispatch, { deltaData, formName }); + + dispatch({ + type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED, + response: { results: [] } + }); + + dispatch({ + type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED, + response: { results: [] } + }); + } + }, + + setIsValidityData(dispatch, { isValidityData }) { + dispatch({ + type: actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED, + isValidityData + }); + }, + + fetchSoftwareProduct(dispatch, { softwareProductId, version }) { + return Promise.all([ + fetchSoftwareProduct(softwareProductId, version).then(response => { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_LOADED, + response + }); + return response; + }), + fetchSoftwareProductQuestionnaire(softwareProductId, version).then( + response => { + ValidationHelper.qDataLoaded(dispatch, { + response: { + qdata: response.data + ? JSON.parse(response.data) + : {}, + qschema: JSON.parse(response.schema) + }, + qName: PRODUCT_QUESTIONNAIRE + }); + } + ) + ]); + }, + + manageSubmitAction(dispatch, { softwareProductId, version, isDirty }) { + if (isDirty) { + const onCommit = comment => { + return this.performVCAction(dispatch, { + softwareProductId, + action: VersionControllerActionsEnum.COMMIT, + version, + comment + }).then(() => { + return this.performSubmitAction(dispatch, { + softwareProductId, + version + }); + }); + }; + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: modalContentMapper.COMMIT_COMMENT, + modalComponentProps: { + onCommit, + type: CommitModalType.COMMIT_SUBMIT + }, + title: i18n('Commit & Submit') + } + }); + return Promise.resolve(version); + } + return this.performSubmitAction(dispatch, { + softwareProductId, + version + }); + }, + + performSubmitAction(dispatch, { softwareProductId, version }) { + return putSoftwareProductAction( + softwareProductId, + VersionControllerActionsEnum.SUBMIT, + version + ).then( + () => { + return putSoftwareProductAction( + softwareProductId, + VersionControllerActionsEnum.CREATE_PACKAGE, + version + ).then(() => { + return ItemsHelper.checkItemStatus(dispatch, { + itemId: softwareProductId, + versionId: version.id + }).then(updatedVersion => { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SUCCESS, + data: { + title: i18n('Submit Succeeded'), + msg: i18n( + 'This software product successfully submitted' + ), + cancelButtonText: i18n('OK'), + timeout: 2000 + } + }); + versionPageActionHelper.fetchVersions(dispatch, { + itemType: itemTypes.SOFTWARE_PRODUCT, + itemId: softwareProductId + }); + return Promise.resolve(updatedVersion); + }); + }); + }, + error => { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + modalComponentName: + modalContentMapper.SUMBIT_ERROR_RESPONSE, + title: i18n('Submit Failed'), + modalComponentProps: { + validationResponse: error.responseJSON + }, + cancelButtonText: i18n('OK') + } + }); + return Promise.reject(error.responseJSON); + } + ); + }, + + performVCAction(dispatch, { softwareProductId, action, version, comment }) { + return MergeEditorActionHelper.analyzeSyncResult(dispatch, { + itemId: softwareProductId, + version + }).then(({ inMerge, isDirty, updatedVersion }) => { + if ( + (updatedVersion.status === catalogItemStatuses.CERTIFIED || + updatedVersion.archivedStatus === + catalogItemStatuses.ARCHIVED) && + (action === VersionControllerActionsEnum.COMMIT || + action === VersionControllerActionsEnum.SYNC) + ) { + versionPageActionHelper.fetchVersions(dispatch, { + itemType: itemTypes.SOFTWARE_PRODUCT, + itemId: softwareProductId + }); + const msg = + updatedVersion.archivedStatus === + catalogItemStatuses.ARCHIVED + ? i18n('Item was Archived') + : i18n('Item version already Certified'); + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + title: i18n('Commit error'), + msg, + cancelButtonText: i18n('Cancel') + } + }); + return Promise.resolve(updatedVersion); + } + if (!inMerge) { + if (action === VersionControllerActionsEnum.SUBMIT) { + return this.manageSubmitAction(dispatch, { + softwareProductId, + version, + isDirty + }); + } else { + let isCallActionValid = + action !== VersionControllerActionsEnum.COMMIT || + isDirty; + if (isCallActionValid) { + return ItemsHelper.performVCAction({ + itemId: softwareProductId, + action, + version, + comment + }).then(() => { + versionPageActionHelper.fetchVersions(dispatch, { + itemType: itemTypes.LICENSE_MODEL, + itemId: softwareProductId + }); + if (action === VersionControllerActionsEnum.SYNC) { + return MergeEditorActionHelper.analyzeSyncResult( + dispatch, + { itemId: softwareProductId, version } + ).then(({ updatedVersion }) => { + return Promise.resolve(updatedVersion); + }); + } else { + return ItemsHelper.checkItemStatus(dispatch, { + itemId: softwareProductId, + versionId: version.id + }); + } + }); + } else { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + title: i18n('Commit Failed'), + msg: i18n('There is nothing to commit') + } + }); + } + } + } + }); + }, + + toggleNavigationItems(dispatch, { items, itemIdToExpand }) { + let mapOfExpandedIds = getExpandedItemsId(items, itemIdToExpand); + dispatch({ + type: actionTypes.TOGGLE_NAVIGATION_ITEM, + mapOfExpandedIds + }); + }, + + /** for the next verision */ + addComponent(dispatch, { softwareProductId, modalClassName, version }) { + SoftwareProductComponentsActionHelper.clearComponentCreationData( + dispatch + ); + dispatch({ + type: componentActionTypes.COMPONENT_CREATE_OPEN + }); + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: modalContentMapper.COMPONENT_CREATION, + modalComponentProps: { softwareProductId, version }, + modalClassName, + title: 'Create Virtual Function Component' + } + }); + }, + + migrateSoftwareProduct(dispatch, { softwareProduct }) { + let { id: softwareProductId, version } = softwareProduct; + const newVer = version.id; + migrateSoftwareProduct(softwareProductId, version).then(() => + ScreensHelper.loadScreen(dispatch, { + screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { + softwareProductId, + version: { id: newVer, label: newVer } + } + }) + ); + }, + + abortCandidateValidation(dispatch, { softwareProductId, version }) { + return abortValidationProcess(softwareProductId, version); + } }; export default SoftwareProductActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js index 9b147415f9..d1ba947f81 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js @@ -14,17 +14,21 @@ * permissions and limitations under the License. */ export default { - - getCurrentCategoryOfSubCategory(selectedSubCategory, softwareProductCategories) { - let category, subCategory; - for (var i = 0; i < softwareProductCategories.length; i++) { - let {subcategories = []} = softwareProductCategories[i]; - subCategory = subcategories.find(sub => sub.uniqueId === selectedSubCategory); - if (subCategory) { - category = softwareProductCategories[i].uniqueId; - break; - } - } - return category; - } + getCurrentCategoryOfSubCategory( + selectedSubCategory, + softwareProductCategories + ) { + let category, subCategory; + for (var i = 0; i < softwareProductCategories.length; i++) { + let { subcategories = [] } = softwareProductCategories[i]; + subCategory = subcategories.find( + sub => sub.uniqueId === selectedSubCategory + ); + if (subCategory) { + category = softwareProductCategories[i].uniqueId; + break; + } + } + return category; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js index d33eb822cf..711bbf8db8 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js @@ -16,41 +16,38 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - SOFTWARE_PRODUCT_LOADED: null, - SOFTWARE_PRODUCT_LIST_LOADED: null, - ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED: null, - FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED: null, - SOFTWARE_PRODUCT_LIST_EDIT: null, - SOFTWARE_PRODUCT_CATEGORIES_LOADED: null, - SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE: null, - LOAD_LICENSING_VERSIONS_LIST: null, - TOGGLE_NAVIGATION_ITEM: null, - CANDIDATE_IN_PROCESS: null, - - softwareProductEditor: { - OPEN: null, - CLOSE: null, - DATA_CHANGED: null, - IS_VALIDITY_DATA_CHANGED: null - } + SOFTWARE_PRODUCT_LOADED: null, + SOFTWARE_PRODUCT_LIST_LOADED: null, + ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED: null, + FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED: null, + SOFTWARE_PRODUCT_LIST_EDIT: null, + SOFTWARE_PRODUCT_CATEGORIES_LOADED: null, + SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE: null, + LOAD_LICENSING_VERSIONS_LIST: null, + TOGGLE_NAVIGATION_ITEM: null, + CANDIDATE_IN_PROCESS: null, + + softwareProductEditor: { + OPEN: null, + CLOSE: null, + DATA_CHANGED: null, + IS_VALIDITY_DATA_CHANGED: null + } }); - - export const onboardingMethod = { - MANUAL: 'Manual', - NETWORK_PACKAGE: 'NetworkPackage' + MANUAL: 'Manual', + NETWORK_PACKAGE: 'NetworkPackage' }; export const onboardingOriginTypes = { - NONE: 'none', - ZIP: 'zip', - CSAR: 'csar' + NONE: 'none', + ZIP: 'zip', + CSAR: 'csar' }; export const forms = keyMirror({ - VENDOR_SOFTWARE_PRODUCT_DETAILS: 'vendor-software-product-details', + VENDOR_SOFTWARE_PRODUCT_DETAILS: 'vendor-software-product-details' }); export const PRODUCT_QUESTIONNAIRE = 'product'; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js index 31be338ff5..f52153a29f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js @@ -13,16 +13,22 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductConstants.js'; +import { actionTypes } from './SoftwareProductConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.SOFTWARE_PRODUCT_LIST_LOADED: - return [...action.response.results]; - case actionTypes.SOFTWARE_PRODUCT_LIST_EDIT: - const indexForEdit = state.findIndex(vsp => vsp.id === action.payload.softwareProduct.id); - return [...state.slice(0, indexForEdit), action.payload.softwareProduct, ...state.slice(indexForEdit + 1)]; - default: - return state; - } + switch (action.type) { + case actionTypes.SOFTWARE_PRODUCT_LIST_LOADED: + return [...action.response.results]; + case actionTypes.SOFTWARE_PRODUCT_LIST_EDIT: + const indexForEdit = state.findIndex( + vsp => vsp.id === action.payload.softwareProduct.id + ); + return [ + ...state.slice(0, indexForEdit), + action.payload.softwareProduct, + ...state.slice(indexForEdit + 1) + ]; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js index d7a6c2ef5c..f3de517a1c 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js @@ -13,12 +13,15 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {combineReducers} from 'redux'; -import {actionTypes, PRODUCT_QUESTIONNAIRE} from './SoftwareProductConstants.js'; +import { combineReducers } from 'redux'; +import { + actionTypes, + PRODUCT_QUESTIONNAIRE +} from './SoftwareProductConstants.js'; import SoftwareProductAttachmentsReducer from './attachments/SoftwareProductAttachmentsReducer.js'; import HeatValidationReducer from './attachments/validation/HeatValidationReducer.js'; import HeatSetupReducer from './attachments/setup/HeatSetupReducer.js'; -import {actionTypes as heatSetupActionTypes} from './attachments/setup/HeatSetupConstants.js'; +import { actionTypes as heatSetupActionTypes } from './attachments/setup/HeatSetupConstants.js'; import SoftwareProductCreationReducer from './creation/SoftwareProductCreationReducer.js'; import SoftwareProductDetailsReducer from './details/SoftwareProductDetailsReducer.js'; import SoftwareProductProcessesListReducer from './processes/SoftwareProductProcessesListReducer.js'; @@ -28,10 +31,10 @@ import SoftwareProductDeploymentEditorReducer from './deployment/editor/Software import SoftwareProductNetworksListReducer from './networks/SoftwareProductNetworksListReducer.js'; import SoftwareProductComponentsListReducer from './components/SoftwareProductComponentsListReducer.js'; import SoftwareProductComponentEditorReducer from './components/SoftwareProductComponentEditorReducer.js'; -import {actionTypes as processesActionTypes} from './processes/SoftwareProductProcessesConstants.js'; -import SoftwareProductComponentProcessesListReducer from './components/processes/SoftwareProductComponentProcessesListReducer.js'; +import { actionTypes as processesActionTypes } from './processes/SoftwareProductProcessesConstants.js'; +import SoftwareProductComponentProcessesListReducer from './components/processes/SoftwareProductComponentProcessesListReducer.js'; import SoftwareProductComponentProcessesEditorReducer from './components/processes/SoftwareProductComponentProcessesEditorReducer.js'; -import {actionTypes as componentProcessesActionTypes} from './components/processes/SoftwareProductComponentProcessesConstants.js'; +import { actionTypes as componentProcessesActionTypes } from './components/processes/SoftwareProductComponentProcessesConstants.js'; import SoftwareProductComponentsNICListReducer from './components/network/SoftwareProductComponentsNICListReducer.js'; import SoftwareProductComponentsNICEditorReducer from './components/network/SoftwareProductComponentsNICEditorReducer.js'; import SoftwareProductComponentsImageListReducer from './components/images/SoftwareProductComponentsImageListReducer.js'; @@ -40,63 +43,112 @@ import SoftwareProductComponentsNICCreationReducer from './components/network/NI import SoftwareProductComponentsMonitoringReducer from './components/monitoring/SoftwareProductComponentsMonitoringReducer.js'; import SoftwareProductComponentsComputeFlavorListReducer from './components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js'; import SoftwareProductComponentsComputeFlavorReducer from './components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js'; -import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js'; +import { createPlainDataReducer } from 'sdc-app/common/reducers/PlainDataReducer.js'; import SoftwareProductDependenciesReducer from './dependencies/SoftwareProductDependenciesReducer.js'; -import {createJSONSchemaReducer, createComposedJSONSchemaReducer} from 'sdc-app/common/reducers/JSONSchemaReducer.js'; -import {COMPONENTS_QUESTIONNAIRE, COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; -import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js'; -import {IMAGE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js'; +import { + createJSONSchemaReducer, + createComposedJSONSchemaReducer +} from 'sdc-app/common/reducers/JSONSchemaReducer.js'; +import { + COMPONENTS_QUESTIONNAIRE, + COMPONENTS_COMPUTE_QUESTIONNAIRE +} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { NIC_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js'; +import { IMAGE_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js'; export default combineReducers({ - softwareProductAttachments: combineReducers({ - attachmentsDetails: SoftwareProductAttachmentsReducer, - heatValidation: HeatValidationReducer, - heatSetup: HeatSetupReducer, - heatSetupCache: (state = {}, action) => action.type === heatSetupActionTypes.FILL_HEAT_SETUP_CACHE ? action.payload : state - }), - softwareProductCreation: createPlainDataReducer(SoftwareProductCreationReducer), - softwareProductEditor: createPlainDataReducer(SoftwareProductDetailsReducer), - softwareProductProcesses: combineReducers({ - processesList: SoftwareProductProcessesListReducer, - processesEditor: createPlainDataReducer(SoftwareProductProcessesEditorReducer), - processToDelete: (state = false, action) => action.type === processesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM ? action.processToDelete : state - }), - softwareProductDeployment: combineReducers({ - deploymentFlavors: SoftwareProductDeploymentListReducer, - deploymentFlavorEditor: createPlainDataReducer(SoftwareProductDeploymentEditorReducer) - }), - softwareProductNetworks: combineReducers({ - networksList: SoftwareProductNetworksListReducer - }), - softwareProductDependencies: SoftwareProductDependenciesReducer, - softwareProductComponents: combineReducers({ - componentsList: SoftwareProductComponentsListReducer, - componentEditor: createPlainDataReducer(createComposedJSONSchemaReducer(COMPONENTS_QUESTIONNAIRE, SoftwareProductComponentEditorReducer)), - componentProcesses: combineReducers({ - processesList: SoftwareProductComponentProcessesListReducer, - processesEditor: createPlainDataReducer(SoftwareProductComponentProcessesEditorReducer), - processToDelete: (state = false, action) => action.type === componentProcessesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM ? action.processToDelete : state, - }), - network: combineReducers({ - nicList: SoftwareProductComponentsNICListReducer, - nicEditor: createPlainDataReducer(createComposedJSONSchemaReducer(NIC_QUESTIONNAIRE, SoftwareProductComponentsNICEditorReducer)), - nicCreation: createPlainDataReducer(SoftwareProductComponentsNICCreationReducer) - }), - images: combineReducers({ - imagesList: SoftwareProductComponentsImageListReducer, - imageEditor: createPlainDataReducer(createComposedJSONSchemaReducer(IMAGE_QUESTIONNAIRE, SoftwareProductComponentsImageEditorReducer)) - }), - computeFlavor: combineReducers({ - computesList: SoftwareProductComponentsComputeFlavorListReducer, - computeEditor: createPlainDataReducer(createComposedJSONSchemaReducer(COMPONENTS_COMPUTE_QUESTIONNAIRE, SoftwareProductComponentsComputeFlavorReducer)), - }), - monitoring: SoftwareProductComponentsMonitoringReducer - }), - softwareProductCategories: (state = [], action) => { - if (action.type === actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED) { - return action.softwareProductCategories; - } - return state; - }, - softwareProductQuestionnaire: createJSONSchemaReducer(PRODUCT_QUESTIONNAIRE) + softwareProductAttachments: combineReducers({ + attachmentsDetails: SoftwareProductAttachmentsReducer, + heatValidation: HeatValidationReducer, + heatSetup: HeatSetupReducer, + heatSetupCache: (state = {}, action) => + action.type === heatSetupActionTypes.FILL_HEAT_SETUP_CACHE + ? action.payload + : state + }), + softwareProductCreation: createPlainDataReducer( + SoftwareProductCreationReducer + ), + softwareProductEditor: createPlainDataReducer( + SoftwareProductDetailsReducer + ), + softwareProductProcesses: combineReducers({ + processesList: SoftwareProductProcessesListReducer, + processesEditor: createPlainDataReducer( + SoftwareProductProcessesEditorReducer + ), + processToDelete: (state = false, action) => + action.type === + processesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM + ? action.processToDelete + : state + }), + softwareProductDeployment: combineReducers({ + deploymentFlavors: SoftwareProductDeploymentListReducer, + deploymentFlavorEditor: createPlainDataReducer( + SoftwareProductDeploymentEditorReducer + ) + }), + softwareProductNetworks: combineReducers({ + networksList: SoftwareProductNetworksListReducer + }), + softwareProductDependencies: SoftwareProductDependenciesReducer, + softwareProductComponents: combineReducers({ + componentsList: SoftwareProductComponentsListReducer, + componentEditor: createPlainDataReducer( + createComposedJSONSchemaReducer( + COMPONENTS_QUESTIONNAIRE, + SoftwareProductComponentEditorReducer + ) + ), + componentProcesses: combineReducers({ + processesList: SoftwareProductComponentProcessesListReducer, + processesEditor: createPlainDataReducer( + SoftwareProductComponentProcessesEditorReducer + ), + processToDelete: (state = false, action) => + action.type === + componentProcessesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM + ? action.processToDelete + : state + }), + network: combineReducers({ + nicList: SoftwareProductComponentsNICListReducer, + nicEditor: createPlainDataReducer( + createComposedJSONSchemaReducer( + NIC_QUESTIONNAIRE, + SoftwareProductComponentsNICEditorReducer + ) + ), + nicCreation: createPlainDataReducer( + SoftwareProductComponentsNICCreationReducer + ) + }), + images: combineReducers({ + imagesList: SoftwareProductComponentsImageListReducer, + imageEditor: createPlainDataReducer( + createComposedJSONSchemaReducer( + IMAGE_QUESTIONNAIRE, + SoftwareProductComponentsImageEditorReducer + ) + ) + }), + computeFlavor: combineReducers({ + computesList: SoftwareProductComponentsComputeFlavorListReducer, + computeEditor: createPlainDataReducer( + createComposedJSONSchemaReducer( + COMPONENTS_COMPUTE_QUESTIONNAIRE, + SoftwareProductComponentsComputeFlavorReducer + ) + ) + }), + monitoring: SoftwareProductComponentsMonitoringReducer + }), + softwareProductCategories: (state = [], action) => { + if (action.type === actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED) { + return action.softwareProductCategories; + } + return state; + }, + softwareProductQuestionnaire: createJSONSchemaReducer(PRODUCT_QUESTIONNAIRE) }); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js index d942172973..4d5887be6f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js @@ -13,100 +13,142 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; import HeatSetupActionHelper from './setup/HeatSetupActionHelper.js'; import SoftwareProductAttachmentsView from './SoftwareProductAttachmentsView.jsx'; -import {errorLevels} from 'sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js'; +import { errorLevels } from 'sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js'; import HeatSetup from './setup/HeatSetup.js'; -import {doesHeatDataExist} from './SoftwareProductAttachmentsUtils.js'; +import { doesHeatDataExist } from './SoftwareProductAttachmentsUtils.js'; import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js'; -import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js'; +import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js'; import SoftwareProductAttachmentsActionHelper from './SoftwareProductAttachmentsActionHelper.js'; -export const mapStateToProps = (state) => { - let { - softwareProduct: { - softwareProductEditor:{data: currentSoftwareProduct = {}}, - softwareProductAttachments: {attachmentsDetails: {activeTab}, heatSetup, heatSetupCache, heatValidation : {errorList}} - } - } = state; +export const mapStateToProps = state => { + let { + softwareProduct: { + softwareProductEditor: { data: currentSoftwareProduct = {} }, + softwareProductAttachments: { + attachmentsDetails: { activeTab }, + heatSetup, + heatSetupCache, + heatValidation: { errorList } + } + } + } = state; - let {unassigned = [], modules = []} = heatSetup; - let goToOverview = true; - if (errorList) { - for (let i = 0 ; i < errorList.length ; i++) { - if (errorList[i].level === errorLevels.ERROR) { - goToOverview = false; - } - } - } - let heatDataExist = doesHeatDataExist(heatSetup); + let { unassigned = [], modules = [] } = heatSetup; + let goToOverview = true; + if (errorList) { + for (let i = 0; i < errorList.length; i++) { + if (errorList[i].level === errorLevels.ERROR) { + goToOverview = false; + } + } + } + let heatDataExist = doesHeatDataExist(heatSetup); - let {version, onboardingOrigin} = currentSoftwareProduct; - return { - isValidationAvailable: unassigned.length === 0 && modules.length > 0, - heatSetup, - heatSetupCache, - heatDataExist, - goToOverview, - HeatSetupComponent: HeatSetup, - version, - onboardingOrigin, - activeTab, - candidateInProcess: !!currentSoftwareProduct.candidateOnboardingOrigin - }; + let { version, onboardingOrigin } = currentSoftwareProduct; + return { + isValidationAvailable: unassigned.length === 0 && modules.length > 0, + heatSetup, + heatSetupCache, + heatDataExist, + goToOverview, + HeatSetupComponent: HeatSetup, + version, + onboardingOrigin, + activeTab, + candidateInProcess: !!currentSoftwareProduct.candidateOnboardingOrigin + }; }; -export const mapActionsToProps = (dispatch, {softwareProductId, version}) => { - return { - onDownload: ({heatCandidate, isReadOnlyMode}) => SoftwareProductActionHelper.downloadHeatFile(dispatch, {softwareProductId, heatCandidate, isReadOnlyMode, version}), - onUpload: (formData) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data:{ - msg: i18n('Upload will erase existing data. Do you want to continue?'), - confirmationButtonText: i18n('Continue'), - title: i18n('WARNING'), +export const mapActionsToProps = (dispatch, { softwareProductId, version }) => { + return { + onDownload: ({ heatCandidate, isReadOnlyMode }) => + SoftwareProductActionHelper.downloadHeatFile(dispatch, { + softwareProductId, + heatCandidate, + isReadOnlyMode, + version + }), + onUpload: formData => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + msg: i18n( + 'Upload will erase existing data. Do you want to continue?' + ), + confirmationButtonText: i18n('Continue'), + title: i18n('WARNING'), - onConfirmed: ()=>SoftwareProductActionHelper.uploadFile(dispatch, { - softwareProductId, - formData, - failedNotificationTitle: i18n('Upload validation failed'), - version - }) - } - }), - onUploadAbort: () => { - SoftwareProductActionHelper.abortCandidateValidation(dispatch, {softwareProductId, version}) - .then(()=>{ - ScreensHelper.loadScreen(dispatch, { - screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version} - }); - }); - }, - onInvalidFileUpload: () => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_ERROR, - data: { - title: i18n('Upload Failed'), - confirmationButtonText: i18n('Continue'), - msg: i18n('no zip or csar file was uploaded or expected file doesn\'t exist') - } - }), - onSave: (heatCandidate) => SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version}), - onGoToOverview: () => ScreensHelper.loadScreen(dispatch, { - screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version} - }), - onProcessAndValidate: ({heatData, heatDataCache, isReadOnlyMode}) => { - return HeatSetupActionHelper.processAndValidateHeat(dispatch, - {softwareProductId, heatData, heatDataCache, isReadOnlyMode, version}); - }, - setActiveTab: ({activeTab}) => SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, {activeTab}) - - }; + onConfirmed: () => + SoftwareProductActionHelper.uploadFile(dispatch, { + softwareProductId, + formData, + failedNotificationTitle: i18n( + 'Upload validation failed' + ), + version + }) + } + }), + onUploadAbort: () => { + SoftwareProductActionHelper.abortCandidateValidation(dispatch, { + softwareProductId, + version + }).then(() => { + ScreensHelper.loadScreen(dispatch, { + screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version } + }); + }); + }, + onInvalidFileUpload: () => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + title: i18n('Upload Failed'), + confirmationButtonText: i18n('Continue'), + msg: i18n( + "no zip or csar file was uploaded or expected file doesn't exist" + ) + } + }), + onSave: heatCandidate => + SoftwareProductActionHelper.updateSoftwareProductHeatCandidate( + dispatch, + { + softwareProductId, + heatCandidate, + version + } + ), + onGoToOverview: () => + ScreensHelper.loadScreen(dispatch, { + screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version } + }), + onProcessAndValidate: ({ heatData, heatDataCache, isReadOnlyMode }) => { + return HeatSetupActionHelper.processAndValidateHeat(dispatch, { + softwareProductId, + heatData, + heatDataCache, + isReadOnlyMode, + version + }); + }, + setActiveTab: ({ activeTab }) => + SoftwareProductAttachmentsActionHelper.setActiveTab(dispatch, { + activeTab + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductAttachmentsView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductAttachmentsView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js index ae4a615a40..2d35bc27ee 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js @@ -14,13 +14,13 @@ * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductAttachmentsConstants'; +import { actionTypes } from './SoftwareProductAttachmentsConstants'; export default { - setActiveTab(dispatch, {activeTab}) { - dispatch({ - type: actionTypes.SET_ACTIVE_TAB, - activeTab - }); - } + setActiveTab(dispatch, { activeTab }) { + dispatch({ + type: actionTypes.SET_ACTIVE_TAB, + activeTab + }); + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js index 67265909d7..aff0a3dbdf 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js @@ -16,10 +16,10 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const tabsMapping = { - SETUP: 1, - VALIDATION: 2 + SETUP: 1, + VALIDATION: 2 }; export const actionTypes = keyMirror({ - SET_ACTIVE_TAB: null + SET_ACTIVE_TAB: null }); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js index 5f6538ab7e..5d9a37f98a 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js @@ -13,13 +13,13 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductAttachmentsConstants.js'; +import { actionTypes } from './SoftwareProductAttachmentsConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.SET_ACTIVE_TAB: - return {activeTab: action.activeTab}; - default: - return state; - } + switch (action.type) { + case actionTypes.SET_ACTIVE_TAB: + return { activeTab: action.activeTab }; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsUtils.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsUtils.js index 2e76b11630..f4e77229e9 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsUtils.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsUtils.js @@ -15,11 +15,11 @@ */ export function doesHeatDataExist(heatData) { - let result = false; - for (let key of Object.keys(heatData)) { - if(heatData[key].length > 0) { - result = true; - } - } - return result; + let result = false; + for (let key of Object.keys(heatData)) { + if (heatData[key].length > 0) { + result = true; + } + } + return result; } diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx index 2a849f376e..2007493d48 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx @@ -13,140 +13,208 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import accept from 'attr-accept'; -import {SVGIcon, Tab, Tabs} from 'sdc-ui/lib/react'; -import {tabsMapping} from './SoftwareProductAttachmentsConstants.js'; +import { SVGIcon, Tab, Tabs } from 'sdc-ui/lib/react'; +import { tabsMapping } from './SoftwareProductAttachmentsConstants.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; import HeatValidation from './validation/HeatValidation.js'; -import {onboardingOriginTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { onboardingOriginTypes } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; import Button from 'sdc-ui/lib/react/Button.js'; class HeatScreenView extends Component { + static propTypes = { + isValidationAvailable: PropTypes.bool, + goToOverview: PropTypes.bool, + setActiveTab: PropTypes.func + }; - static propTypes = { - isValidationAvailable: PropTypes.bool, - goToOverview: PropTypes.bool, - setActiveTab: PropTypes.func - }; + componentDidMount() { + if (!this.props.goToOverview && this.props.candidateInProcess) { + this.props.setActiveTab({ activeTab: tabsMapping.VALIDATION }); + } + } - componentDidMount() { - if (!this.props.goToOverview && this.props.candidateInProcess) { - this.props.setActiveTab({activeTab: tabsMapping.VALIDATION}); - } - } + render() { + let { + isValidationAvailable, + isReadOnlyMode, + heatDataExist, + onDownload, + softwareProductId, + onProcessAndValidate, + onUploadAbort, + candidateInProcess, + heatSetup, + HeatSetupComponent, + onGoToOverview, + version, + onboardingOrigin, + activeTab, + setActiveTab, + ...other + } = this.props; - render() { - let {isValidationAvailable, isReadOnlyMode, heatDataExist, onDownload, softwareProductId, onProcessAndValidate, onUploadAbort, - candidateInProcess, heatSetup, HeatSetupComponent, onGoToOverview, version, onboardingOrigin, activeTab, setActiveTab, ...other} = this.props; + return ( + <div className="vsp-attachments-view"> + <div className="attachments-view-controllers"> + {activeTab === tabsMapping.SETUP && + candidateInProcess && ( + <Button + data-test-id="proceed-to-validation-btn" + disabled={!isValidationAvailable} + className="proceed-to-validation-btn" + onClick={() => this.validate()}> + {i18n('PROCEED TO VALIDATION')} + </Button> + )} + {candidateInProcess && ( + <SVGIcon + onClick={onUploadAbort} + name="close" + className="icon-component abort-btn" + label={i18n('ABORT')} + labelPosition="right" + color="secondary" + data-test-id="abort-btn" + /> + )} + {activeTab === tabsMapping.VALIDATION && + softwareProductId && ( + <Button + btnType="outline" + data-test-id="go-to-overview" + disabled={this.props.goToOverview !== true} + className="go-to-overview-btn" + onClick={ + this.props.goToOverview + ? () => onGoToOverview({ version }) + : undefined + }> + {i18n('GO TO OVERVIEW')} + </Button> + )} + <div className="separator" /> + <SVGIcon + disabled={heatDataExist ? false : true} + name="download" + className="icon-component" + color="dark-gray" + onClick={ + heatDataExist + ? () => + onDownload({ + heatCandidate: heatSetup, + isReadOnlyMode: + isReadOnlyMode || + !candidateInProcess, + version + }) + : undefined + } + data-test-id="download-heat" + /> + <SVGIcon + name="upload" + className="icon-component" + color="dark-gray" + disabled={isReadOnlyMode || candidateInProcess} + onClick={ + isReadOnlyMode + ? undefined + : evt => + this.refs.hiddenImportFileInput.click(evt) + } + data-test-id="upload-heat" + /> + <input + ref="hiddenImportFileInput" + type="file" + name="fileInput" + accept=".zip, .csar" + onChange={evt => this.handleImport(evt)} + /> + </div> + <Tabs + className="attachments-tabs" + type="header" + activeTab={activeTab} + onTabClick={key => this.handleTabPress(key)}> + <Tab + tabId={tabsMapping.SETUP} + title="Setup" + disabled={ + onboardingOrigin === onboardingOriginTypes.CSAR + }> + <HeatSetupComponent + heatDataExist={heatDataExist} + changeAttachmentsTab={tab => + setActiveTab({ activeTab: tab }) + } + onProcessAndValidate={onProcessAndValidate} + softwareProductId={softwareProductId} + isReadOnlyMode={isReadOnlyMode} + version={version} + /> + </Tab> + <Tab + tabId={tabsMapping.VALIDATION} + title="Validation" + disabled={!isValidationAvailable || candidateInProcess}> + <HeatValidation {...other} /> + </Tab> + </Tabs> + </div> + ); + } - return ( - <div className='vsp-attachments-view'> - <div className='attachments-view-controllers'> - {(activeTab === tabsMapping.SETUP) && candidateInProcess && - <Button - data-test-id='proceed-to-validation-btn' - disabled={!isValidationAvailable} - className='proceed-to-validation-btn' - onClick={()=>this.validate()}>{i18n('PROCEED TO VALIDATION')}</Button> - } - {candidateInProcess && <SVGIcon - onClick={onUploadAbort} - name='close' - className='icon-component abort-btn' - label={i18n('ABORT')} - labelPosition='right' - color='secondary' - data-test-id='abort-btn'/> - } - {(activeTab === tabsMapping.VALIDATION && softwareProductId) && - <Button btnType='outline' - data-test-id='go-to-overview' - disabled={this.props.goToOverview !== true} - className='go-to-overview-btn' - onClick={this.props.goToOverview ? () => onGoToOverview({version}) : undefined}>{i18n('GO TO OVERVIEW')}</Button>} - <div className='separator'></div> - <SVGIcon - disabled={heatDataExist ? false : true} - name='download' - className='icon-component' - color='dark-gray' - onClick={heatDataExist ? () => onDownload({heatCandidate: heatSetup, isReadOnlyMode: isReadOnlyMode || !candidateInProcess, version}) : undefined} - data-test-id='download-heat'/> - <SVGIcon - name='upload' - className='icon-component' - color='dark-gray' - disabled={isReadOnlyMode || candidateInProcess} - onClick={isReadOnlyMode ? undefined : evt => this.refs.hiddenImportFileInput.click(evt)} - data-test-id='upload-heat'/> - <input - ref='hiddenImportFileInput' - type='file' - name='fileInput' - accept='.zip, .csar' - onChange={evt => this.handleImport(evt)}/> - </div> - <Tabs - className='attachments-tabs' - type='header' - activeTab={activeTab} - onTabClick={key => this.handleTabPress(key)}> - <Tab tabId={tabsMapping.SETUP} title='Setup' disabled={onboardingOrigin === onboardingOriginTypes.CSAR}> - <HeatSetupComponent - heatDataExist={heatDataExist} - changeAttachmentsTab={tab => setActiveTab({activeTab: tab})} - onProcessAndValidate={onProcessAndValidate} - softwareProductId={softwareProductId} - isReadOnlyMode={isReadOnlyMode} - version={version}/> - </Tab> - <Tab tabId={tabsMapping.VALIDATION} title='Validation' disabled={!isValidationAvailable || candidateInProcess}> - <HeatValidation {...other}/> - </Tab> - </Tabs> - </div> - ); - } - - handleTabPress(key) { - let {setActiveTab} = this.props; - switch (key) { - case tabsMapping.VALIDATION: - setActiveTab({activeTab: tabsMapping.VALIDATION}); - return; - case tabsMapping.SETUP: - setActiveTab({activeTab: tabsMapping.SETUP}); - return; - } - } - - handleImport(evt) { - evt.preventDefault(); - let file = this.refs.hiddenImportFileInput.files[0]; - if(! (file && file.size && accept(file, ['.zip', '.csar'])) ) { - this.props.onInvalidFileUpload(); - return; - } - let {version} = this.props; - let formData = new FormData(); - formData.append('upload', file); - this.refs.hiddenImportFileInput.value = ''; - this.props.onUpload(formData, version); - } - validate() { - let {heatSetup, heatSetupCache, onProcessAndValidate, isReadOnlyMode, version, setActiveTab} = this.props; - onProcessAndValidate({heatData: heatSetup, heatDataCache: heatSetupCache, isReadOnlyMode, version}).then( - () => setActiveTab({activeTab: tabsMapping.VALIDATION}) - ); - } - save() { - return this.props.onboardingOrigin === onboardingOriginTypes.ZIP ? - this.props.onSave(this.props.heatSetup, this.props.version) : - Promise.resolve(); - } + handleTabPress(key) { + let { setActiveTab } = this.props; + switch (key) { + case tabsMapping.VALIDATION: + setActiveTab({ activeTab: tabsMapping.VALIDATION }); + return; + case tabsMapping.SETUP: + setActiveTab({ activeTab: tabsMapping.SETUP }); + return; + } + } + handleImport(evt) { + evt.preventDefault(); + let file = this.refs.hiddenImportFileInput.files[0]; + if (!(file && file.size && accept(file, ['.zip', '.csar']))) { + this.props.onInvalidFileUpload(); + return; + } + let { version } = this.props; + let formData = new FormData(); + formData.append('upload', file); + this.refs.hiddenImportFileInput.value = ''; + this.props.onUpload(formData, version); + } + validate() { + let { + heatSetup, + heatSetupCache, + onProcessAndValidate, + isReadOnlyMode, + version, + setActiveTab + } = this.props; + onProcessAndValidate({ + heatData: heatSetup, + heatDataCache: heatSetupCache, + isReadOnlyMode, + version + }).then(() => setActiveTab({ activeTab: tabsMapping.VALIDATION })); + } + save() { + return this.props.onboardingOrigin === onboardingOriginTypes.ZIP + ? this.props.onSave(this.props.heatSetup, this.props.version) + : Promise.resolve(); + } } export default HeatScreenView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js index 4c3adc6a7d..d75d464f9e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js @@ -13,50 +13,65 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import HeatSetupView from './HeatSetupView.jsx'; import HeatSetupActionHelper from './HeatSetupActionHelper.js'; - const BASE = true; function baseExists(modules) { - for (let i in modules) { - if (modules[i].isBase) { - return true; - } - } - return false; + for (let i in modules) { + if (modules[i].isBase) { + return true; + } + } + return false; } -export const mapStateToProps = ({softwareProduct: {softwareProductAttachments: {heatSetup, heatSetupCache}}}) => { - let {modules = [], unassigned = [], artifacts = [], nested = []} = heatSetup; - let isBaseExist = baseExists(modules); +export const mapStateToProps = ({ + softwareProduct: { + softwareProductAttachments: { heatSetup, heatSetupCache } + } +}) => { + let { + modules = [], + unassigned = [], + artifacts = [], + nested = [] + } = heatSetup; + let isBaseExist = baseExists(modules); - return { - heatSetupCache, - modules, - unassigned, - artifacts, - nested, - isBaseExist - }; + return { + heatSetupCache, + modules, + unassigned, + artifacts, + nested, + isBaseExist + }; }; export const mapActionsToProps = (dispatch, {}) => { - return { - onModuleRename: (oldName, newName) => HeatSetupActionHelper.renameModule(dispatch, {oldName, newName}), - onModuleAdd: () => HeatSetupActionHelper.addModule(dispatch, !BASE), - onBaseAdd: () => HeatSetupActionHelper.addModule(dispatch, BASE), - onModuleDelete: moduleName => HeatSetupActionHelper.deleteModule(dispatch, moduleName), - onModuleFileTypeChange: ({module, value, type}) => HeatSetupActionHelper.changeModuleFileType(dispatch, { - module, - value, - type - }), - onArtifactListChange: artifacts => HeatSetupActionHelper.changeArtifactList(dispatch, artifacts), - onAddAllUnassigned: () => HeatSetupActionHelper.addAllUnassignedFilesToArtifacts(dispatch) - }; + return { + onModuleRename: (oldName, newName) => + HeatSetupActionHelper.renameModule(dispatch, { oldName, newName }), + onModuleAdd: () => HeatSetupActionHelper.addModule(dispatch, !BASE), + onBaseAdd: () => HeatSetupActionHelper.addModule(dispatch, BASE), + onModuleDelete: moduleName => + HeatSetupActionHelper.deleteModule(dispatch, moduleName), + onModuleFileTypeChange: ({ module, value, type }) => + HeatSetupActionHelper.changeModuleFileType(dispatch, { + module, + value, + type + }), + onArtifactListChange: artifacts => + HeatSetupActionHelper.changeArtifactList(dispatch, artifacts), + onAddAllUnassigned: () => + HeatSetupActionHelper.addAllUnassignedFilesToArtifacts(dispatch) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(HeatSetupView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(HeatSetupView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js index 87953bb8aa..05ac408fbb 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js @@ -13,7 +13,7 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './HeatSetupConstants.js'; +import { actionTypes } from './HeatSetupConstants.js'; import isEqual from 'lodash/isEqual.js'; import cloneDeep from 'lodash/cloneDeep.js'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; @@ -21,46 +21,72 @@ import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/Soft // import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; export default { + addModule(dispatch, isBase) { + dispatch({ type: actionTypes.ADD_MODULE, data: { isBase } }); + }, - addModule(dispatch, isBase){ - dispatch({type: actionTypes.ADD_MODULE, data: {isBase}}); - }, + deleteModule(dispatch, moduleName) { + dispatch({ type: actionTypes.REMOVE_MODULE, data: { moduleName } }); + }, - deleteModule(dispatch, moduleName){ - dispatch({type: actionTypes.REMOVE_MODULE, data: {moduleName}}); - }, + renameModule(dispatch, { oldName, newName }) { + dispatch({ + type: actionTypes.RENAME_MODULE, + data: { oldName, newName } + }); + }, - renameModule(dispatch, {oldName, newName}){ - dispatch({type: actionTypes.RENAME_MODULE, data: {oldName, newName}}); - }, + changeModuleFileType(dispatch, { module, value, type }) { + if (!value) { + value = { value: '' }; + } + dispatch({ + type: actionTypes.FILE_ASSIGN_CHANGED, + data: { module, value, type } + }); + }, - changeModuleFileType(dispatch, {module, value, type}){ - if (!value) { - value = {value: ''}; - } - dispatch({type: actionTypes.FILE_ASSIGN_CHANGED, data: {module, value, type}}); - }, + changeArtifactList(dispatch, artifacts) { + dispatch({ + type: actionTypes.ARTIFACT_LIST_CHANGE, + data: { artifacts: artifacts.map(artifact => artifact.value) } + }); + }, - changeArtifactList(dispatch, artifacts){ - dispatch({type: actionTypes.ARTIFACT_LIST_CHANGE, data: {artifacts: artifacts.map(artifact => artifact.value)}}); - }, + processAndValidateHeat( + dispatch, + { softwareProductId, heatData, heatDataCache, isReadOnlyMode, version } + ) { + return isEqual({ ...heatData, softwareProductId }, heatDataCache) || + isReadOnlyMode + ? Promise.resolve() + : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate( + dispatch, + { softwareProductId, heatCandidate: heatData, version } + ) + .then(() => + SoftwareProductActionHelper.processAndValidateHeatCandidate( + dispatch, + { softwareProductId, version } + ) + ) + .then(() => + dispatch({ + type: actionTypes.FILL_HEAT_SETUP_CACHE, + payload: { ...cloneDeep(heatData), softwareProductId } + }) + ); + }, - processAndValidateHeat(dispatch, {softwareProductId, heatData, heatDataCache, isReadOnlyMode, version}){ - return (isEqual({...heatData, softwareProductId}, heatDataCache) || isReadOnlyMode) ? Promise.resolve() : - SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate: heatData, version}) - .then(() => SoftwareProductActionHelper.processAndValidateHeatCandidate(dispatch, {softwareProductId, version})) - .then(() => dispatch({type: actionTypes.FILL_HEAT_SETUP_CACHE, payload: {...cloneDeep(heatData), softwareProductId}})); - }, + addAllUnassignedFilesToArtifacts(dispatch) { + dispatch({ type: actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS }); + }, - addAllUnassignedFilesToArtifacts(dispatch){ - dispatch({type: actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS}); - }, + heatSetupLeaveConfirmation() { + return Promise.resolve(); + } - heatSetupLeaveConfirmation() { - return Promise.resolve(); - } - - /*heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) { + /*heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) { return new Promise((resolve, reject) => { if (isEqual({...heatSetup, softwareProductId}, heatSetupCache)) { resolve(); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js index 2d6bd574a7..ff53fad27f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js @@ -16,27 +16,25 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ + ARTIFACT_LIST_CHANGE: null, + ADD_ALL_UNASSIGNED_TO_ARTIFACTS: null, + ADD_ALL_ARTIFACTS_TO_UNASSIGNED: null, - ARTIFACT_LIST_CHANGE: null, - ADD_ALL_UNASSIGNED_TO_ARTIFACTS: null, - ADD_ALL_ARTIFACTS_TO_UNASSIGNED: null, + ADD_MODULE: null, + REMOVE_MODULE: null, + RENAME_MODULE: null, + FILL_HEAT_SETUP_CACHE: null, + FILE_ASSIGN_CHANGED: null, - ADD_MODULE: null, - REMOVE_MODULE: null, - RENAME_MODULE: null, - FILL_HEAT_SETUP_CACHE: null, - FILE_ASSIGN_CHANGED: null, - - MANIFEST_LOADED: null, - - GO_TO_VALIDATION: null, - IN_VALIDATION: null + MANIFEST_LOADED: null, + GO_TO_VALIDATION: null, + IN_VALIDATION: null }); export const fileTypes = { - YAML: {label: 'yaml', regex: /(yaml|yml)/g}, - ENV: {label: 'env', regex: /env/g}, - VOL: {label: 'vol', regex: /(yaml|yml)/g}, - VOL_ENV: {label: 'volEnv', regex: /env/g} + YAML: { label: 'yaml', regex: /(yaml|yml)/g }, + ENV: { label: 'env', regex: /env/g }, + VOL: { label: 'vol', regex: /(yaml|yml)/g }, + VOL_ENV: { label: 'volEnv', regex: /env/g } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js index f49339ce35..8840a11c3e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js @@ -13,112 +13,163 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './HeatSetupConstants.js'; +import { actionTypes } from './HeatSetupConstants.js'; import differenceWith from 'lodash/differenceWith.js'; - const emptyModule = (isBase, currentLength) => ({ - name: `${isBase ? 'base_' : 'module_'}${currentLength + 1}`, - isBase: isBase + name: `${isBase ? 'base_' : 'module_'}${currentLength + 1}`, + isBase: isBase }); -function syncUnassignedFilesWithArtifactsChanges(unassigned, artifacts, oldArtifacts) { - if (artifacts.length > oldArtifacts.length) { - return differenceWith(unassigned, artifacts, (unassignedFile, artifact) => unassignedFile === artifact); - } - else { - const removedArtifact = differenceWith(oldArtifacts, artifacts, (oldArtifact, artifact) => artifact === oldArtifact); - return [...unassigned, removedArtifact[0]]; - } +function syncUnassignedFilesWithArtifactsChanges( + unassigned, + artifacts, + oldArtifacts +) { + if (artifacts.length > oldArtifacts.length) { + return differenceWith( + unassigned, + artifacts, + (unassignedFile, artifact) => unassignedFile === artifact + ); + } else { + const removedArtifact = differenceWith( + oldArtifacts, + artifacts, + (oldArtifact, artifact) => artifact === oldArtifact + ); + return [...unassigned, removedArtifact[0]]; + } } function findModuleIndexByName(modules, name) { - return modules.findIndex(module => module.name === name); + return modules.findIndex(module => module.name === name); } -function addDeletedModuleFilesToUnassigned(unassigned, deletedModule){ - let files = []; - for(let i in deletedModule){ - if (deletedModule.hasOwnProperty(i)) { - if (typeof deletedModule[i] === 'string' && deletedModule[i] && i !== 'name') { - files.push(deletedModule[i]); - } - } - } +function addDeletedModuleFilesToUnassigned(unassigned, deletedModule) { + let files = []; + for (let i in deletedModule) { + if (deletedModule.hasOwnProperty(i)) { + if ( + typeof deletedModule[i] === 'string' && + deletedModule[i] && + i !== 'name' + ) { + files.push(deletedModule[i]); + } + } + } - return unassigned.concat(files); + return unassigned.concat(files); } export default (state = {}, action) => { - switch (action.type) { - case actionTypes.MANIFEST_LOADED: - return { - ...state, - ...action.response, - modules: action.response.modules.map(module => ({...module, name: module.name || module.yaml.substring(0, module.yaml.lastIndexOf('.'))})) - }; - case actionTypes.ARTIFACT_LIST_CHANGE: - return { - ...state, - artifacts: action.data.artifacts, - unassigned: syncUnassignedFilesWithArtifactsChanges(state.unassigned, action.data.artifacts, state.artifacts) - }; - case actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS: - return { - ...state, - artifacts: [...state.artifacts,...state.unassigned], - unassigned: [] - }; - case actionTypes.ADD_ALL_ARTIFACTS_TO_UNASSIGNED: - return { - ...state, - artifacts: [], - unassigned: [...state.unassigned, ...state.artifacts] - }; - case actionTypes.ADD_MODULE: - return { - ...state, - modules: state.modules.concat({...emptyModule(action.data.isBase, state.modules.length)}) - }; - case actionTypes.REMOVE_MODULE: - const moduleIndexToDelete = findModuleIndexByName(state.modules, action.data.moduleName); - let unassigned = addDeletedModuleFilesToUnassigned(state.unassigned, state.modules[moduleIndexToDelete]); - return { - ...state, - unassigned, - modules: [...state.modules.slice(0, moduleIndexToDelete), ...state.modules.slice(moduleIndexToDelete + 1)] - }; - case actionTypes.RENAME_MODULE: - const indexToRename = findModuleIndexByName(state.modules, action.data.oldName); - let moduleToRename = state.modules[indexToRename]; - moduleToRename.name = action.data.newName; - return { - ...state, - modules: [...state.modules.slice(0, indexToRename), moduleToRename, ...state.modules.slice(indexToRename + 1)] - }; - case actionTypes.FILE_ASSIGN_CHANGED: - let {module, value:{value}, type} = action.data; - const moduleIndexToModify = findModuleIndexByName(state.modules, module.name); - let moduleToModify = state.modules[moduleIndexToModify]; - let dumpedFile = moduleToModify[type]; - if (dumpedFile !== value) { - if(value) { - moduleToModify[type] = value; - } - else { - delete moduleToModify[type]; - } - const newUnassignedList = dumpedFile ? [...state.unassigned.filter(file => file !== value), dumpedFile] : state.unassigned.filter(file => file !== value); - return { - ...state, - modules: [...state.modules.slice(0, moduleIndexToModify), moduleToModify, ...state.modules.slice(moduleIndexToModify + 1)], - unassigned: newUnassignedList - }; - } - else { - return state; - } - default: - return state; - } + switch (action.type) { + case actionTypes.MANIFEST_LOADED: + return { + ...state, + ...action.response, + modules: action.response.modules.map(module => ({ + ...module, + name: + module.name || + module.yaml.substring(0, module.yaml.lastIndexOf('.')) + })) + }; + case actionTypes.ARTIFACT_LIST_CHANGE: + return { + ...state, + artifacts: action.data.artifacts, + unassigned: syncUnassignedFilesWithArtifactsChanges( + state.unassigned, + action.data.artifacts, + state.artifacts + ) + }; + case actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS: + return { + ...state, + artifacts: [...state.artifacts, ...state.unassigned], + unassigned: [] + }; + case actionTypes.ADD_ALL_ARTIFACTS_TO_UNASSIGNED: + return { + ...state, + artifacts: [], + unassigned: [...state.unassigned, ...state.artifacts] + }; + case actionTypes.ADD_MODULE: + return { + ...state, + modules: state.modules.concat({ + ...emptyModule(action.data.isBase, state.modules.length) + }) + }; + case actionTypes.REMOVE_MODULE: + const moduleIndexToDelete = findModuleIndexByName( + state.modules, + action.data.moduleName + ); + let unassigned = addDeletedModuleFilesToUnassigned( + state.unassigned, + state.modules[moduleIndexToDelete] + ); + return { + ...state, + unassigned, + modules: [ + ...state.modules.slice(0, moduleIndexToDelete), + ...state.modules.slice(moduleIndexToDelete + 1) + ] + }; + case actionTypes.RENAME_MODULE: + const indexToRename = findModuleIndexByName( + state.modules, + action.data.oldName + ); + let moduleToRename = state.modules[indexToRename]; + moduleToRename.name = action.data.newName; + return { + ...state, + modules: [ + ...state.modules.slice(0, indexToRename), + moduleToRename, + ...state.modules.slice(indexToRename + 1) + ] + }; + case actionTypes.FILE_ASSIGN_CHANGED: + let { module, value: { value }, type } = action.data; + const moduleIndexToModify = findModuleIndexByName( + state.modules, + module.name + ); + let moduleToModify = state.modules[moduleIndexToModify]; + let dumpedFile = moduleToModify[type]; + if (dumpedFile !== value) { + if (value) { + moduleToModify[type] = value; + } else { + delete moduleToModify[type]; + } + const newUnassignedList = dumpedFile + ? [ + ...state.unassigned.filter(file => file !== value), + dumpedFile + ] + : state.unassigned.filter(file => file !== value); + return { + ...state, + modules: [ + ...state.modules.slice(0, moduleIndexToModify), + moduleToModify, + ...state.modules.slice(moduleIndexToModify + 1) + ], + unassigned: newUnassignedList + }; + } else { + return state; + } + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx index ce6d5260d7..1d4efd9104 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx @@ -13,7 +13,7 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import Button from 'sdc-ui/lib/react/Button.js'; import Tooltip from 'react-bootstrap/lib/Tooltip.js'; import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js'; @@ -21,307 +21,476 @@ import FormControl from 'react-bootstrap/lib/FormControl.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; import SelectInput from 'nfvo-components/input/SelectInput.jsx'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; -import {fileTypes} from './HeatSetupConstants.js'; -import {tabsMapping} from '../SoftwareProductAttachmentsConstants.js'; -import {sortable} from 'react-sortable'; +import { fileTypes } from './HeatSetupConstants.js'; +import { tabsMapping } from '../SoftwareProductAttachmentsConstants.js'; +import { sortable } from 'react-sortable'; class ListItem extends Component { - - render() { - return ( - <li {...this.props}>{this.props.children}</li> - ); - } + render() { + return <li {...this.props}>{this.props.children}</li>; + } } - const SortableListItem = sortable(ListItem); class SortableModuleFileList extends Component { - - state = { - draggingIndex: null, - data: this.props.modules - }; - - - componentWillReceiveProps(nextProps) { - this.setState({data: nextProps.modules}); - } - - render() { - - let {unassigned, onModuleRename, onModuleDelete, onModuleAdd, onBaseAdd, onModuleFileTypeChange, isBaseExist, isReadOnlyMode} = this.props; - const childProps = module => ({ - module, - onModuleRename, - onModuleDelete, - onModuleFileTypeChange: (value, type) => onModuleFileTypeChange({module, value, type}), - files: unassigned - }); - let listItems = this.state.data.map(function (item, i) { - return ( - <SortableListItem - key={i} - updateState={data => this.setState(data)} - items={this.state.data} - draggingIndex={this.state.draggingIndex} - sortId={i} - outline='list'><ModuleFile {...childProps(item)} isReadOnlyMode={this.props.isReadOnlyMode} /></SortableListItem> - ); - }, this); - - return ( - <div className={`modules-list-wrapper ${(listItems.length > 0) ? 'modules-list-wrapper-divider' : ''}`}> - <div className='modules-list-header'> - {!isBaseExist && <div><Button btnType='link' onClick={onBaseAdd} disabled={isReadOnlyMode || unassigned.length === 0}>{i18n('Add Base')}</Button></div>} - <div><Button btnType='link' onClick={onModuleAdd} disabled={isReadOnlyMode || unassigned.length === 0}>{i18n('Add Module')}</Button></div> - </div> - {(listItems.length > 0) && <ul>{listItems}</ul>} - </div> - ); - } + state = { + draggingIndex: null, + data: this.props.modules + }; + + componentWillReceiveProps(nextProps) { + this.setState({ data: nextProps.modules }); + } + + render() { + let { + unassigned, + onModuleRename, + onModuleDelete, + onModuleAdd, + onBaseAdd, + onModuleFileTypeChange, + isBaseExist, + isReadOnlyMode + } = this.props; + const childProps = module => ({ + module, + onModuleRename, + onModuleDelete, + onModuleFileTypeChange: (value, type) => + onModuleFileTypeChange({ module, value, type }), + files: unassigned + }); + let listItems = this.state.data.map(function(item, i) { + return ( + <SortableListItem + key={i} + updateState={data => this.setState(data)} + items={this.state.data} + draggingIndex={this.state.draggingIndex} + sortId={i} + outline="list"> + <ModuleFile + {...childProps(item)} + isReadOnlyMode={this.props.isReadOnlyMode} + /> + </SortableListItem> + ); + }, this); + + return ( + <div + className={`modules-list-wrapper ${ + listItems.length > 0 ? 'modules-list-wrapper-divider' : '' + }`}> + <div className="modules-list-header"> + {!isBaseExist && ( + <div> + <Button + btnType="link" + onClick={onBaseAdd} + disabled={ + isReadOnlyMode || unassigned.length === 0 + }> + {i18n('Add Base')} + </Button> + </div> + )} + <div> + <Button + btnType="link" + onClick={onModuleAdd} + disabled={ + isReadOnlyMode || unassigned.length === 0 + }> + {i18n('Add Module')} + </Button> + </div> + </div> + {listItems.length > 0 && <ul>{listItems}</ul>} + </div> + ); + } } -const tooltip = (name) => <Tooltip id='tooltip-bottom'>{name}</Tooltip>; -const UnassignedFileList = (props) => { - return ( - <div> - <div className='modules-list-header'/> - <div className='unassigned-files'> - <div className='unassigned-files-title'>{i18n('UNASSIGNED FILES')}</div> - <div className='unassigned-files-list'>{props.children}</div> - </div> - </div> - ); +const tooltip = name => <Tooltip id="tooltip-bottom">{name}</Tooltip>; +const UnassignedFileList = props => { + return ( + <div> + <div className="modules-list-header" /> + <div className="unassigned-files"> + <div className="unassigned-files-title"> + {i18n('UNASSIGNED FILES')} + </div> + <div className="unassigned-files-list">{props.children}</div> + </div> + </div> + ); }; const EmptyListContent = props => { - let {heatDataExist} = props; - let displayText = heatDataExist ? 'All Files Are Assigned' : ''; - return ( - <div className='go-to-validation-button-wrapper'> - <div className='all-files-assigned'>{i18n(displayText)}</div> - </div> - ); + let { heatDataExist } = props; + let displayText = heatDataExist ? 'All Files Are Assigned' : ''; + return ( + <div className="go-to-validation-button-wrapper"> + <div className="all-files-assigned">{i18n(displayText)}</div> + </div> + ); }; -const UnassignedFile = (props) => ( - <OverlayTrigger placement='bottom' overlay={tooltip(props.name)} delayShow={1000}> - <li data-test-id='unassigned-files' className='unassigned-files-list-item'>{props.name}</li> - </OverlayTrigger> +const UnassignedFile = props => ( + <OverlayTrigger + placement="bottom" + overlay={tooltip(props.name)} + delayShow={1000}> + <li + data-test-id="unassigned-files" + className="unassigned-files-list-item"> + {props.name} + </li> + </OverlayTrigger> ); -const AddOrDeleteVolumeFiles = ({add = true, onAdd, onDelete, isReadOnlyMode}) => { - const displayText = add ? 'Add Volume Files' : 'Delete Volume Files'; - const action = add ? onAdd : onDelete; - return ( - <Button disabled={isReadOnlyMode} onClick={action} btnType='link' className='add-or-delete-volumes' iconName={add ? 'plus' : 'close'}>{i18n(displayText)}</Button> - ); +const AddOrDeleteVolumeFiles = ({ + add = true, + onAdd, + onDelete, + isReadOnlyMode +}) => { + const displayText = add ? 'Add Volume Files' : 'Delete Volume Files'; + const action = add ? onAdd : onDelete; + return ( + <Button + disabled={isReadOnlyMode} + onClick={action} + btnType="link" + className="add-or-delete-volumes" + iconName={add ? 'plus' : 'close'}> + {i18n(displayText)} + </Button> + ); }; -const SelectWithFileType = ({type, selected, files, onChange}) => { - - let filteredFiledAccordingToType = files.filter(file => file.label.search(type.regex) > -1); - if (selected) { - filteredFiledAccordingToType = filteredFiledAccordingToType.concat({label: selected, value: selected}); - } - - return ( - <SelectInput - data-test-id={`${type.label}-list`} - label={type.label} - value={selected} - onChange={value => value !== selected && onChange(value, type.label)} - disabled={filteredFiledAccordingToType.length === 0} - placeholder={filteredFiledAccordingToType.length === 0 ? '' : undefined} - clearable={true} - options={filteredFiledAccordingToType} /> - ); +const SelectWithFileType = ({ type, selected, files, onChange }) => { + let filteredFiledAccordingToType = files.filter( + file => file.label.search(type.regex) > -1 + ); + if (selected) { + filteredFiledAccordingToType = filteredFiledAccordingToType.concat({ + label: selected, + value: selected + }); + } + + return ( + <SelectInput + data-test-id={`${type.label}-list`} + label={type.label} + value={selected} + onChange={value => + value !== selected && onChange(value, type.label) + } + disabled={filteredFiledAccordingToType.length === 0} + placeholder={ + filteredFiledAccordingToType.length === 0 ? '' : undefined + } + clearable={true} + options={filteredFiledAccordingToType} + /> + ); }; class NameEditInput extends Component { - componentDidMount() { - this.input.focus(); - } - - render() { - return ( - <FormControl {...this.props} className='name-edit' inputRef={input => this.input = input}/> - ); - } + componentDidMount() { + this.input.focus(); + } + + render() { + return ( + <FormControl + {...this.props} + className="name-edit" + inputRef={input => (this.input = input)} + /> + ); + } } class ModuleFile extends Component { - constructor(props) { - super(props); - this.state = { - isInNameEdit: false, - displayVolumes: Boolean(props.module.vol || props.module.volEnv) - }; - } - - handleSubmit(event, name) { - if (event.keyCode === 13) { - this.handleModuleRename(event, name); - } - } - - componentWillReceiveProps(nextProps) { - this.setState({displayVolumes: Boolean(nextProps.module.vol || nextProps.module.volEnv)}); - } - - handleModuleRename(event, name) { - this.setState({isInNameEdit: false}); - this.props.onModuleRename(name, event.target.value); - } - - deleteVolumeFiles() { - const { onModuleFileTypeChange} = this.props; - onModuleFileTypeChange(null, fileTypes.VOL.label); - onModuleFileTypeChange(null, fileTypes.VOL_ENV.label); - this.setState({displayVolumes: false}); - } - - renderNameAccordingToEditState() { - const {module: {name}} = this.props; - if (this.state.isInNameEdit) { - return (<NameEditInput defaultValue={name} onBlur={evt => this.handleModuleRename(evt, name)} onKeyDown={evt => this.handleSubmit(evt, name)}/>); - } - return (<span className='filename-text'>{name}</span>); - } - - render() { - const {module: {name, isBase, yaml, env, vol, volEnv}, onModuleDelete, files, onModuleFileTypeChange, isReadOnlyMode} = this.props; - const {displayVolumes} = this.state; - const moduleType = isBase ? 'BASE' : 'MODULE'; - return ( - <div className='modules-list-item' data-test-id='module-item'> - <div className='modules-list-item-controllers'> - <div className='modules-list-item-filename'> - <SVGIcon name={isBase ? 'base' : 'module'} color='primary' iconClassName='heat-setup-module-icon' /> - <span className='module-title-by-type'>{`${moduleType}: `}</span> - <div className={`text-and-icon ${this.state.isInNameEdit ? 'in-edit' : ''}`}> - {this.renderNameAccordingToEditState()} - {!this.state.isInNameEdit && <SVGIcon - name='pencil' - onClick={() => this.setState({isInNameEdit: true})} - data-test-id={isBase ? 'base-name' : 'module-name'}/>} - </div> - </div> - <SVGIcon name='trashO' onClick={() => onModuleDelete(name)} data-test-id='module-delete'/> - </div> - <div className='modules-list-item-selectors'> - <SelectWithFileType - type={fileTypes.YAML} - files={files} - selected={yaml} - onChange={onModuleFileTypeChange}/> - <SelectWithFileType - type={fileTypes.ENV} - files={files} - selected={env} - onChange={onModuleFileTypeChange}/> - {displayVolumes && <SelectWithFileType - type={fileTypes.VOL} - files={files} - selected={vol} - onChange={onModuleFileTypeChange}/>} - {displayVolumes && <SelectWithFileType - type={fileTypes.VOL_ENV} - files={files} - selected={volEnv} - onChange={onModuleFileTypeChange}/>} - <AddOrDeleteVolumeFiles isReadOnlyMode={isReadOnlyMode} onAdd={() => this.setState({displayVolumes: true})} onDelete={() => this.deleteVolumeFiles()} add={!displayVolumes}/> - </div> - </div> - ); - } + constructor(props) { + super(props); + this.state = { + isInNameEdit: false, + displayVolumes: Boolean(props.module.vol || props.module.volEnv) + }; + } + + handleSubmit(event, name) { + if (event.keyCode === 13) { + this.handleModuleRename(event, name); + } + } + + componentWillReceiveProps(nextProps) { + this.setState({ + displayVolumes: Boolean( + nextProps.module.vol || nextProps.module.volEnv + ) + }); + } + + handleModuleRename(event, name) { + this.setState({ isInNameEdit: false }); + this.props.onModuleRename(name, event.target.value); + } + + deleteVolumeFiles() { + const { onModuleFileTypeChange } = this.props; + onModuleFileTypeChange(null, fileTypes.VOL.label); + onModuleFileTypeChange(null, fileTypes.VOL_ENV.label); + this.setState({ displayVolumes: false }); + } + + renderNameAccordingToEditState() { + const { module: { name } } = this.props; + if (this.state.isInNameEdit) { + return ( + <NameEditInput + defaultValue={name} + onBlur={evt => this.handleModuleRename(evt, name)} + onKeyDown={evt => this.handleSubmit(evt, name)} + /> + ); + } + return <span className="filename-text">{name}</span>; + } + + render() { + const { + module: { name, isBase, yaml, env, vol, volEnv }, + onModuleDelete, + files, + onModuleFileTypeChange, + isReadOnlyMode + } = this.props; + const { displayVolumes } = this.state; + const moduleType = isBase ? 'BASE' : 'MODULE'; + return ( + <div className="modules-list-item" data-test-id="module-item"> + <div className="modules-list-item-controllers"> + <div className="modules-list-item-filename"> + <SVGIcon + name={isBase ? 'base' : 'module'} + color="primary" + iconClassName="heat-setup-module-icon" + /> + <span className="module-title-by-type">{`${moduleType}: `}</span> + <div + className={`text-and-icon ${ + this.state.isInNameEdit ? 'in-edit' : '' + }`}> + {this.renderNameAccordingToEditState()} + {!this.state.isInNameEdit && ( + <SVGIcon + name="pencil" + onClick={() => + this.setState({ isInNameEdit: true }) + } + data-test-id={ + isBase ? 'base-name' : 'module-name' + } + /> + )} + </div> + </div> + <SVGIcon + name="trashO" + onClick={() => onModuleDelete(name)} + data-test-id="module-delete" + /> + </div> + <div className="modules-list-item-selectors"> + <SelectWithFileType + type={fileTypes.YAML} + files={files} + selected={yaml} + onChange={onModuleFileTypeChange} + /> + <SelectWithFileType + type={fileTypes.ENV} + files={files} + selected={env} + onChange={onModuleFileTypeChange} + /> + {displayVolumes && ( + <SelectWithFileType + type={fileTypes.VOL} + files={files} + selected={vol} + onChange={onModuleFileTypeChange} + /> + )} + {displayVolumes && ( + <SelectWithFileType + type={fileTypes.VOL_ENV} + files={files} + selected={volEnv} + onChange={onModuleFileTypeChange} + /> + )} + <AddOrDeleteVolumeFiles + isReadOnlyMode={isReadOnlyMode} + onAdd={() => this.setState({ displayVolumes: true })} + onDelete={() => this.deleteVolumeFiles()} + add={!displayVolumes} + /> + </div> + </div> + ); + } } class ArtifactOrNestedFileList extends Component { - - render() { - let {type, title, selected, options, onSelectChanged, onAddAllUnassigned, isReadOnlyMode, headerClassName} = this.props; - return ( - <div className={`artifact-files ${type === 'nested' ? 'nested' : ''} ${headerClassName} `}> - <div className='artifact-files-header'> - <span> - {type === 'artifact' && (<SVGIcon color='primary' name='artifacts' iconClassName='heat-setup-module-icon' />)} - {`${title}`} - </span> - {type === 'artifact' && <Button disabled={isReadOnlyMode} btnType='link' className='add-all-unassigned' onClick={onAddAllUnassigned}>{i18n('Add All Unassigned Files')}</Button>} - </div> - {type === 'nested' ? ( - <ul className='nested-list'>{selected.map(nested => - <li key={nested} className='nested-list-item'>{nested}</li> - )}</ul>) : - (<SelectInput - options={options} - onMultiSelectChanged={onSelectChanged || (() => { - })} - value={selected} - clearable={false} - placeholder={i18n('Add Artifact')} - multi/>) - } - </div> - ); - } + render() { + let { + type, + title, + selected, + options, + onSelectChanged, + onAddAllUnassigned, + isReadOnlyMode, + headerClassName + } = this.props; + return ( + <div + className={`artifact-files ${ + type === 'nested' ? 'nested' : '' + } ${headerClassName} `}> + <div className="artifact-files-header"> + <span> + {type === 'artifact' && ( + <SVGIcon + color="primary" + name="artifacts" + iconClassName="heat-setup-module-icon" + /> + )} + {`${title}`} + </span> + {type === 'artifact' && ( + <Button + disabled={isReadOnlyMode} + btnType="link" + className="add-all-unassigned" + onClick={onAddAllUnassigned}> + {i18n('Add All Unassigned Files')} + </Button> + )} + </div> + {type === 'nested' ? ( + <ul className="nested-list"> + {selected.map(nested => ( + <li key={nested} className="nested-list-item"> + {nested} + </li> + ))} + </ul> + ) : ( + <SelectInput + options={options} + onMultiSelectChanged={onSelectChanged || (() => {})} + value={selected} + clearable={false} + placeholder={i18n('Add Artifact')} + multi + /> + )} + </div> + ); + } } -const buildLabelValueObject = str => (typeof str === 'string' ? {value: str, label: str} : str); +const buildLabelValueObject = str => + typeof str === 'string' ? { value: str, label: str } : str; class SoftwareProductHeatSetupView extends Component { - - processAndValidateHeat(heatData, heatDataCache){ - let {onProcessAndValidate, changeAttachmentsTab, version} = this.props; - onProcessAndValidate({heatData, heatDataCache, version}).then( - () => changeAttachmentsTab(tabsMapping.VALIDATION) - ); - } - - render() { - let {modules, isReadOnlyMode, heatDataExist, unassigned, artifacts, nested, onArtifactListChange, onAddAllUnassigned} = this.props; - - const formattedUnassigned = unassigned.map(buildLabelValueObject); - const formattedArtifacts = artifacts.map(buildLabelValueObject); - return ( - <div className={`heat-setup-view ${isReadOnlyMode ? 'disabled' : ''}`}> - <div className='heat-setup-view-modules-and-artifacts'> - <SortableModuleFileList - {...this.props} - isReadOnlyMode={this.props.isReadOnlyMode} - artifacts={formattedArtifacts} - unassigned={formattedUnassigned}/> - <ArtifactOrNestedFileList - type={'artifact'} - title={i18n('ARTIFACTS')} - options={formattedUnassigned} - selected={formattedArtifacts} - onSelectChanged={onArtifactListChange} - isReadOnlyMode={this.props.isReadOnlyMode} - headerClassName={(modules && modules.length > 0) ? 'with-list-items' : ''} - onAddAllUnassigned={onAddAllUnassigned}/> - <ArtifactOrNestedFileList - type={'nested'} - title={i18n('NESTED HEAT FILES')} - options={[]} - isReadOnlyMode={this.props.isReadOnlyMode} - selected={nested}/> - </div> - <UnassignedFileList> - { - formattedUnassigned.length > 0 ? - (<ul>{formattedUnassigned.map(file => <UnassignedFile key={file.label} name={file.label}/>)}</ul>) - : - (<EmptyListContent - heatDataExist={heatDataExist}/>) - } - </UnassignedFileList> - </div> - ); - } - + processAndValidateHeat(heatData, heatDataCache) { + let { + onProcessAndValidate, + changeAttachmentsTab, + version + } = this.props; + onProcessAndValidate({ heatData, heatDataCache, version }).then(() => + changeAttachmentsTab(tabsMapping.VALIDATION) + ); + } + + render() { + let { + modules, + isReadOnlyMode, + heatDataExist, + unassigned, + artifacts, + nested, + onArtifactListChange, + onAddAllUnassigned + } = this.props; + + const formattedUnassigned = unassigned.map(buildLabelValueObject); + const formattedArtifacts = artifacts.map(buildLabelValueObject); + return ( + <div + className={`heat-setup-view ${ + isReadOnlyMode ? 'disabled' : '' + }`}> + <div className="heat-setup-view-modules-and-artifacts"> + <SortableModuleFileList + {...this.props} + isReadOnlyMode={this.props.isReadOnlyMode} + artifacts={formattedArtifacts} + unassigned={formattedUnassigned} + /> + <ArtifactOrNestedFileList + type={'artifact'} + title={i18n('ARTIFACTS')} + options={formattedUnassigned} + selected={formattedArtifacts} + onSelectChanged={onArtifactListChange} + isReadOnlyMode={this.props.isReadOnlyMode} + headerClassName={ + modules && modules.length > 0 + ? 'with-list-items' + : '' + } + onAddAllUnassigned={onAddAllUnassigned} + /> + <ArtifactOrNestedFileList + type={'nested'} + title={i18n('NESTED HEAT FILES')} + options={[]} + isReadOnlyMode={this.props.isReadOnlyMode} + selected={nested} + /> + </div> + <UnassignedFileList> + {formattedUnassigned.length > 0 ? ( + <ul> + {formattedUnassigned.map(file => ( + <UnassignedFile + key={file.label} + name={file.label} + /> + ))} + </ul> + ) : ( + <EmptyListContent heatDataExist={heatDataExist} /> + )} + </UnassignedFileList> + </div> + ); + } } export default SoftwareProductHeatSetupView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidation.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidation.js index 21f6e6c77f..00130e4bc7 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidation.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidation.js @@ -13,39 +13,55 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import HeatValidationView from './HeatValidationView.jsx'; import HeatValidationActionHelper from './HeatValidationActionHelper.js'; -import {errorLevels, nodeFilters} from './HeatValidationConstants.js'; +import { errorLevels, nodeFilters } from './HeatValidationConstants.js'; -export const mapStateToProps = ({softwareProduct: {softwareProductAttachments: {heatValidation}}}) => { - let {attachmentsTree, selectedNode, errorList} = heatValidation; - let currentErrors = [], currentWarnings = []; - if (errorList) { - for (let i = 0 ; i < errorList.length ; i++) { - if (errorList[i].level === errorLevels.ERROR && (errorList[i].name === selectedNode || selectedNode === nodeFilters.ALL)) { - currentErrors[currentErrors.length] = errorList[i]; - } - if (errorList[i].level === errorLevels.WARNING && (errorList[i].name === selectedNode || selectedNode === nodeFilters.ALL)) { - currentWarnings[currentWarnings.length] = errorList[i]; - } - } - } - return { - attachmentsTree, - selectedNode, - errorList, - currentErrors, - currentWarnings - }; +export const mapStateToProps = ({ + softwareProduct: { softwareProductAttachments: { heatValidation } } +}) => { + let { attachmentsTree, selectedNode, errorList } = heatValidation; + let currentErrors = [], + currentWarnings = []; + if (errorList) { + for (let i = 0; i < errorList.length; i++) { + if ( + errorList[i].level === errorLevels.ERROR && + (errorList[i].name === selectedNode || + selectedNode === nodeFilters.ALL) + ) { + currentErrors[currentErrors.length] = errorList[i]; + } + if ( + errorList[i].level === errorLevels.WARNING && + (errorList[i].name === selectedNode || + selectedNode === nodeFilters.ALL) + ) { + currentWarnings[currentWarnings.length] = errorList[i]; + } + } + } + return { + attachmentsTree, + selectedNode, + errorList, + currentErrors, + currentWarnings + }; }; -const mapActionsToProps = (dispatch) => { - return { - toggleExpanded: (path) => HeatValidationActionHelper.toggleExpanded(dispatch, {path}), - onSelectNode: (nodeName) => HeatValidationActionHelper.onSelectNode(dispatch, {nodeName}), - onDeselectNode: () => HeatValidationActionHelper.onDeselectNode(dispatch) - }; +const mapActionsToProps = dispatch => { + return { + toggleExpanded: path => + HeatValidationActionHelper.toggleExpanded(dispatch, { path }), + onSelectNode: nodeName => + HeatValidationActionHelper.onSelectNode(dispatch, { nodeName }), + onDeselectNode: () => + HeatValidationActionHelper.onDeselectNode(dispatch) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(HeatValidationView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(HeatValidationView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js index 73366c20cc..5e8e49cf8a 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js @@ -13,27 +13,26 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './HeatValidationConstants.js'; +import { actionTypes } from './HeatValidationConstants.js'; export default { + toggleExpanded(dispatch, { path }) { + dispatch({ + type: actionTypes.TOGGLE_EXPANDED, + path + }); + }, - toggleExpanded(dispatch, {path}) { - dispatch({ - type: actionTypes.TOGGLE_EXPANDED, - path - }); - }, + onSelectNode(dispatch, { nodeName }) { + dispatch({ + type: actionTypes.SELECTED_NODE, + nodeName + }); + }, - onSelectNode(dispatch, {nodeName}) { - dispatch({ - type: actionTypes.SELECTED_NODE, - nodeName - }); - }, - - onDeselectNode(dispatch) { - dispatch({ - type: actionTypes.UNSELECTED_NODE - }); - } + onDeselectNode(dispatch) { + dispatch({ + type: actionTypes.UNSELECTED_NODE + }); + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js index f783fe6482..8c9f54b5ba 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js @@ -17,41 +17,48 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; export const actionTypes = keyMirror({ - TOGGLE_EXPANDED: null, - SELECTED_NODE: null, - UNSELECTED_NODE: null + TOGGLE_EXPANDED: null, + SELECTED_NODE: null, + UNSELECTED_NODE: null }); export const errorTypes = keyMirror({ - MISSING_FILE_IN_ZIP: i18n('missing file in zip'), - MISSING_FILE_IN_MANIFEST: i18n('missing file in manifest'), - MISSING_OR_ILLEGAL_FILE_TYPE_IN_MANIFEST: i18n('missing or illegal file type in manifest'), - FILE_IS_YML_WITHOUT_YML_EXTENSION: i18n('file is defined as a heat file but it doesn\'t have .yml or .yaml extension'), - FILE_IS_ENV_WITHOUT_ENV_EXTENSION: i18n('file is defined as an env file but it doesn\'t have .env extension'), - ILLEGAL_YAML_FILE_CONTENT: i18n('illegal yaml file content'), - ILLEGAL_HEAT_YAML_FILE_CONTENT: i18n('illegal HEAT yaml file content'), - MISSING_FILE_NAME_IN_MANIFEST: i18n('a file is written in manifest without file name'), - MISSING_ENV_FILE_IN_ZIP: i18n('missing env file in zip'), - ARTIFACT_NOT_IN_USE: i18n('artifact not in use') + MISSING_FILE_IN_ZIP: i18n('missing file in zip'), + MISSING_FILE_IN_MANIFEST: i18n('missing file in manifest'), + MISSING_OR_ILLEGAL_FILE_TYPE_IN_MANIFEST: i18n( + 'missing or illegal file type in manifest' + ), + FILE_IS_YML_WITHOUT_YML_EXTENSION: i18n( + "file is defined as a heat file but it doesn't have .yml or .yaml extension" + ), + FILE_IS_ENV_WITHOUT_ENV_EXTENSION: i18n( + "file is defined as an env file but it doesn't have .env extension" + ), + ILLEGAL_YAML_FILE_CONTENT: i18n('illegal yaml file content'), + ILLEGAL_HEAT_YAML_FILE_CONTENT: i18n('illegal HEAT yaml file content'), + MISSING_FILE_NAME_IN_MANIFEST: i18n( + 'a file is written in manifest without file name' + ), + MISSING_ENV_FILE_IN_ZIP: i18n('missing env file in zip'), + ARTIFACT_NOT_IN_USE: i18n('artifact not in use') }); export const errorLevels = keyMirror({ - WARNING: 'WARNING', - ERROR: 'ERROR' + WARNING: 'WARNING', + ERROR: 'ERROR' }); export const nodeFilters = keyMirror({ - ALL: 'All' + ALL: 'All' }); export const nodeTypes = keyMirror({ - heat: i18n('Heat'), - volume: i18n('Volume'), - network: i18n('Network'), - artifact: i18n('Artifact'), - env: i18n('Environment'), - other: i18n('') + heat: i18n('Heat'), + volume: i18n('Volume'), + network: i18n('Network'), + artifact: i18n('Artifact'), + env: i18n('Environment'), + other: i18n('') }); export const mouseActions = keyMirror({ - MOUSE_BUTTON_CLICK: 0 + MOUSE_BUTTON_CLICK: 0 }); - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js index 1d11bdd6b7..67e36ca040 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js @@ -13,185 +13,242 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes as softwareProductsActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; -import {actionTypes, nodeFilters} from './HeatValidationConstants.js'; +import { actionTypes as softwareProductsActionTypes } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { actionTypes, nodeFilters } from './HeatValidationConstants.js'; -const mapVolumeData = ({fileName, env, errors}) => ({ - name: fileName, - expanded: true, - type: 'volume', - children: env && [{ - name: env.fileName, - errors: env.errors, - type: 'env' - }], - errors +const mapVolumeData = ({ fileName, env, errors }) => ({ + name: fileName, + expanded: true, + type: 'volume', + children: env && [ + { + name: env.fileName, + errors: env.errors, + type: 'env' + } + ], + errors }); -const mapNetworkData = ({fileName, env, errors}) => ({ - name: fileName, - expanded: true, - type: 'network', - children: env && [{ - name: env.fileName, - errors: env.errors, - type: 'env' - }], - errors +const mapNetworkData = ({ fileName, env, errors }) => ({ + name: fileName, + expanded: true, + type: 'network', + children: env && [ + { + name: env.fileName, + errors: env.errors, + type: 'env' + } + ], + errors }); -const mapArtifactsData = ({fileName, errors}) => ({ - name: fileName, - type: 'artifact', - errors +const mapArtifactsData = ({ fileName, errors }) => ({ + name: fileName, + type: 'artifact', + errors }); -const mapOtherData = ({fileName, errors}) => ({ - name: fileName, - type: 'other', - errors +const mapOtherData = ({ fileName, errors }) => ({ + name: fileName, + type: 'other', + errors }); - -const mapHeatData = ({fileName, env, nested, volume, network, artifacts, errors, other}) => ({ - name: fileName, - expanded: true, - type: 'heat', - errors, - children: [ - ...(volume ? volume.map(mapVolumeData) : []), - ...(network ? network.map(mapNetworkData) : []), - ...(env ? [{ - name: env.fileName, - errors: env.errors, - type: 'env' - }] : []), - ...(artifacts ? artifacts.map(mapArtifactsData) : []), - ...(other ? other.map(mapOtherData) : []), - ...(nested ? nested.map(mapHeatData) : []) - ] +const mapHeatData = ({ + fileName, + env, + nested, + volume, + network, + artifacts, + errors, + other +}) => ({ + name: fileName, + expanded: true, + type: 'heat', + errors, + children: [ + ...(volume ? volume.map(mapVolumeData) : []), + ...(network ? network.map(mapNetworkData) : []), + ...(env + ? [ + { + name: env.fileName, + errors: env.errors, + type: 'env' + } + ] + : []), + ...(artifacts ? artifacts.map(mapArtifactsData) : []), + ...(other ? other.map(mapOtherData) : []), + ...(nested ? nested.map(mapHeatData) : []) + ] }); function createErrorList(node, parent, deep = 0, errorList = []) { - if (node.errors) { - errorList.push(...node.errors.map((error) => ({ - level: error.level, - errorMessage: error.message, - name: node.name, - hasParent: deep > 2, - parentName: parent.name, - type: node.type, - }))); - } - if (node.children && node.children.length) { - node.children.map((child) => createErrorList(child, node, deep + 1, errorList)); - } - return errorList; + if (node.errors) { + errorList.push( + ...node.errors.map(error => ({ + level: error.level, + errorMessage: error.message, + name: node.name, + hasParent: deep > 2, + parentName: parent.name, + type: node.type + })) + ); + } + if (node.children && node.children.length) { + node.children.map(child => + createErrorList(child, node, deep + 1, errorList) + ); + } + return errorList; } const mapValidationDataToTree = (validationData, packageName) => { - let {heat, nested, volume, network, artifacts, other} = validationData.importStructure || {}; - return { - children: [ - { - name: packageName, - expanded: true, - type: 'heat', - header: true, - children: (heat ? heat.map(mapHeatData) : nested ? nested.map(mapHeatData) : []) - }, - ...(artifacts ? [{ - name: 'artifacts', - expanded: true, - type: 'artifact', - children: (artifacts ? artifacts.map(mapArtifactsData) : []) - }] : []), - ...(network ? [{ - name: 'networks', - expanded: true, - type: 'network', - children: (network ? network.map(mapNetworkData) : []), - }] : []), - ...(volume ? [{ - name: 'volume', - expanded: true, - type: 'volume', - children: (volume ? volume.map(mapVolumeData) : []), - }] : []), - ...(other ? [{ - name: 'other', - expanded: true, - type: 'other', - children: (other ? other.map(mapOtherData) : []), - }] : []) - ] - }; + let { heat, nested, volume, network, artifacts, other } = + validationData.importStructure || {}; + return { + children: [ + { + name: packageName, + expanded: true, + type: 'heat', + header: true, + children: heat + ? heat.map(mapHeatData) + : nested ? nested.map(mapHeatData) : [] + }, + ...(artifacts + ? [ + { + name: 'artifacts', + expanded: true, + type: 'artifact', + children: artifacts + ? artifacts.map(mapArtifactsData) + : [] + } + ] + : []), + ...(network + ? [ + { + name: 'networks', + expanded: true, + type: 'network', + children: network ? network.map(mapNetworkData) : [] + } + ] + : []), + ...(volume + ? [ + { + name: 'volume', + expanded: true, + type: 'volume', + children: volume ? volume.map(mapVolumeData) : [] + } + ] + : []), + ...(other + ? [ + { + name: 'other', + expanded: true, + type: 'other', + children: other ? other.map(mapOtherData) : [] + } + ] + : []) + ] + }; }; const toggleExpanded = (node, path) => { - let newNode = {...node}; - if (path.length === 0) { - newNode.expanded = !node.expanded; - } else { - let index = path[0]; - newNode.children = [ - ...node.children.slice(0, index), - toggleExpanded(node.children[index], path.slice(1)), - ...node.children.slice(index + 1) - ]; - } - return newNode; + let newNode = { ...node }; + if (path.length === 0) { + newNode.expanded = !node.expanded; + } else { + let index = path[0]; + newNode.children = [ + ...node.children.slice(0, index), + toggleExpanded(node.children[index], path.slice(1)), + ...node.children.slice(index + 1) + ]; + } + return newNode; }; const expandSelected = (node, selectedNode) => { - let shouldExpand = node.name === selectedNode; - let children = node.children && node.children.map(child => { - let {shouldExpand: shouldExpandChild, node: newChild} = expandSelected(child, selectedNode); - shouldExpand = shouldExpand || shouldExpandChild; - return newChild; - }); + let shouldExpand = node.name === selectedNode; + let children = + node.children && + node.children.map(child => { + let { + shouldExpand: shouldExpandChild, + node: newChild + } = expandSelected(child, selectedNode); + shouldExpand = shouldExpand || shouldExpandChild; + return newChild; + }); - return { - node: { - ...node, - expanded: node.expanded || shouldExpand, - children - }, - shouldExpand - }; + return { + node: { + ...node, + expanded: node.expanded || shouldExpand, + children + }, + shouldExpand + }; }; -export default (state = {attachmentsTree: {}}, action) => { - switch (action.type) { - case softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED: - let currentSoftwareProduct = action.response; - const packageName = currentSoftwareProduct.networkPackageName; - let attachmentsTree = currentSoftwareProduct.validationData ? mapValidationDataToTree(currentSoftwareProduct.validationData, packageName) : {}; - let errorList = createErrorList(attachmentsTree); - return { - ...state, - attachmentsTree, - errorList, - selectedNode: nodeFilters.ALL - }; - case actionTypes.TOGGLE_EXPANDED: - return { - ...state, - attachmentsTree: toggleExpanded(state.attachmentsTree, action.path) - }; - case actionTypes.SELECTED_NODE: - let selectedNode = action.nodeName; - return { - ...state, - attachmentsTree: expandSelected(state.attachmentsTree, selectedNode).node, - selectedNode - }; - case actionTypes.UNSELECTED_NODE: - return { - ...state, - selectedNode: nodeFilters.ALL - }; - default: - return state; - } +export default (state = { attachmentsTree: {} }, action) => { + switch (action.type) { + case softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED: + let currentSoftwareProduct = action.response; + const packageName = currentSoftwareProduct.networkPackageName; + let attachmentsTree = currentSoftwareProduct.validationData + ? mapValidationDataToTree( + currentSoftwareProduct.validationData, + packageName + ) + : {}; + let errorList = createErrorList(attachmentsTree); + return { + ...state, + attachmentsTree, + errorList, + selectedNode: nodeFilters.ALL + }; + case actionTypes.TOGGLE_EXPANDED: + return { + ...state, + attachmentsTree: toggleExpanded( + state.attachmentsTree, + action.path + ) + }; + case actionTypes.SELECTED_NODE: + let selectedNode = action.nodeName; + return { + ...state, + attachmentsTree: expandSelected( + state.attachmentsTree, + selectedNode + ).node, + selectedNode + }; + case actionTypes.UNSELECTED_NODE: + return { + ...state, + selectedNode: nodeFilters.ALL + }; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationView.jsx index 3fdaa9c591..c6ee5efd36 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationView.jsx @@ -13,254 +13,352 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import Collapse from 'react-bootstrap/lib/Collapse.js'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {mouseActions, errorLevels, nodeFilters} from './HeatValidationConstants.js'; +import { + mouseActions, + errorLevels, + nodeFilters +} from './HeatValidationConstants.js'; const leftPanelWidth = 250; const typeToIcon = Object.freeze({ - heat: 'nestedHeat', - volume: 'base', - network: 'network', - artifact: 'artifacts', - env: 'env', - other: 'other' + heat: 'nestedHeat', + volume: 'base', + network: 'network', + artifact: 'artifacts', + env: 'env', + other: 'other' }); - class HeatValidationView extends Component { + static propTypes = { + attachmentsTree: PropTypes.object.isRequired, + errorList: PropTypes.array.isRequired, + currentErrors: PropTypes.array.isRequired, + currentWarnings: PropTypes.array.isRequired, + onSelectNode: PropTypes.func.isRequired, + onDeselectNode: PropTypes.func.isRequired, + toggleExpanded: PropTypes.func.isRequired, + selectedNode: PropTypes.string + }; - static propTypes = { - attachmentsTree: PropTypes.object.isRequired, - errorList: PropTypes.array.isRequired, - currentErrors: PropTypes.array.isRequired, - currentWarnings: PropTypes.array.isRequired, - onSelectNode: PropTypes.func.isRequired, - onDeselectNode: PropTypes.func.isRequired, - toggleExpanded: PropTypes.func.isRequired, - selectedNode: PropTypes.string - }; - - render() { - return (<div className='vsp-attachments-heat-validation' data-test-id='heat-validation-editor'> - <HeatFileTree errorList={this.props.errorList} attachmentsTree={this.props.attachmentsTree} - onSelectNode={this.props.onSelectNode} toggleExpanded={this.props.toggleExpanded} - selectedNode={this.props.selectedNode} onDeselectNode={this.props.onDeselectNode} /> - <HeatMessageBoard errors={this.props.currentErrors} warnings={this.props.currentWarnings} selectedNode={this.props.selectedNode} /> - </div> ); - } + render() { + return ( + <div + className="vsp-attachments-heat-validation" + data-test-id="heat-validation-editor"> + <HeatFileTree + errorList={this.props.errorList} + attachmentsTree={this.props.attachmentsTree} + onSelectNode={this.props.onSelectNode} + toggleExpanded={this.props.toggleExpanded} + selectedNode={this.props.selectedNode} + onDeselectNode={this.props.onDeselectNode} + /> + <HeatMessageBoard + errors={this.props.currentErrors} + warnings={this.props.currentWarnings} + selectedNode={this.props.selectedNode} + /> + </div> + ); + } } function HeatFileTreeRow(props) { - let {node, path, toggleExpanded, selectedNode, selectNode} = props; - let isFolder = node.children && node.children.length > 0; - return ( - <div onDoubleClick={() => toggleExpanded(path)} className={classNames({ - 'tree-node-row': true, - 'tree-node-clicked': node.name === props.selectedNode - })} data-test-id='validation-tree-node'> - <div className='name-section'> - { - isFolder && - <div onClick={() => toggleExpanded(path)} - className='tree-node-expander'> - <SVGIcon name={!node.expanded ? 'chevronUp' : 'chevronDown'} data-test-id='validation-tree-block-toggle'/> - </div> - } - { - - <span className='tree-node-icon'> - <SVGIcon name={typeToIcon[node.type]} color={selectedNode === node.name ? 'primary' : 'secondary'}/> - </span> - } - { - - <span className='tree-node-name' onClick={() => selectNode(node.name)} data-test-id='validation-tree-node-name'> - {node.name ? node.name : 'UNKNOWN'} - </span> - } - </div> - <ErrorsAndWarningsCount errorList={node.errors} onClick={() => selectNode(node.name)} /> - </div>); + let { node, path, toggleExpanded, selectedNode, selectNode } = props; + let isFolder = node.children && node.children.length > 0; + return ( + <div + onDoubleClick={() => toggleExpanded(path)} + className={classNames({ + 'tree-node-row': true, + 'tree-node-clicked': node.name === props.selectedNode + })} + data-test-id="validation-tree-node"> + <div className="name-section"> + {isFolder && ( + <div + onClick={() => toggleExpanded(path)} + className="tree-node-expander"> + <SVGIcon + name={!node.expanded ? 'chevronUp' : 'chevronDown'} + data-test-id="validation-tree-block-toggle" + /> + </div> + )} + { + <span className="tree-node-icon"> + <SVGIcon + name={typeToIcon[node.type]} + color={ + selectedNode === node.name + ? 'primary' + : 'secondary' + } + /> + </span> + } + { + <span + className="tree-node-name" + onClick={() => selectNode(node.name)} + data-test-id="validation-tree-node-name"> + {node.name ? node.name : 'UNKNOWN'} + </span> + } + </div> + <ErrorsAndWarningsCount + errorList={node.errors} + onClick={() => selectNode(node.name)} + /> + </div> + ); } function HeatFileTreeHeader(props) { - let hasErrors = props.errorList.filter(error => error.level === errorLevels.ERROR).length > 0; - return ( - <div onClick={() => props.selectNode(nodeFilters.ALL)} className={classNames({'attachments-tree-header': true, - 'header-selected' : props.selectedNode === nodeFilters.ALL})} data-test-id='validation-tree-header'> - <div className='tree-header-title' > - {/*<SVGIcon name='zip' color={props.selectedNode === nodeFilters.ALL ? 'primary' : ''} iconClassName='header-icon' />*/} - <span className={classNames({'tree-header-title-text' : true, - 'tree-header-title-selected' : props.selectedNode === nodeFilters.ALL})}>{i18n('{title} {hasErrors}', {title: props.headerTitle, hasErrors: hasErrors ? '(Draft)' : ''})}</span> - </div> - <ErrorsAndWarningsCount errorList={props.errorList} size='large' /> - </div>); + let hasErrors = + props.errorList.filter(error => error.level === errorLevels.ERROR) + .length > 0; + return ( + <div + onClick={() => props.selectNode(nodeFilters.ALL)} + className={classNames({ + 'attachments-tree-header': true, + 'header-selected': props.selectedNode === nodeFilters.ALL + })} + data-test-id="validation-tree-header"> + <div className="tree-header-title"> + {/*<SVGIcon name='zip' color={props.selectedNode === nodeFilters.ALL ? 'primary' : ''} iconClassName='header-icon' />*/} + <span + className={classNames({ + 'tree-header-title-text': true, + 'tree-header-title-selected': + props.selectedNode === nodeFilters.ALL + })}> + {i18n('{title} {hasErrors}', { + title: props.headerTitle, + hasErrors: hasErrors ? '(Draft)' : '' + })} + </span> + </div> + <ErrorsAndWarningsCount errorList={props.errorList} size="large" /> + </div> + ); } -class HeatFileTree extends React.Component { - static propTypes = { - attachmentsTree: PropTypes.object.isRequired, - errorList: PropTypes.array.isRequired, - onSelectNode: PropTypes.func.isRequired, - onDeselectNode: PropTypes.func.isRequired, - toggleExpanded: PropTypes.func.isRequired, - selectedNode: PropTypes.string - }; - state = { - treeWidth: '400' - }; - render() { - let {attachmentsTree} = this.props; - return ( - <div className='validation-tree-section' style={{'width' : this.state.treeWidth + 'px'}}> - <div className='vsp-attachments-heat-validation-tree'> - <div className='tree-wrapper'> - {attachmentsTree && attachmentsTree.children && attachmentsTree.children.map((child, ind) => this.renderNode(child, [ind]))} - </div> - </div> - <div onMouseDown={(e) => this.onChangeTreeWidth(e)} - className='vsp-attachments-heat-validation-separator' data-test-id='validation-tree-separator'></div> - </div>); - } - renderNode(node, path) { - let rand = Math.random() * (3000 - 1) + 1; - let isFolder = node.children && node.children.length > 0; - let {selectedNode} = this.props; - return ( - <div key={node.name + rand} className={classNames({'tree-block-inside' : !node.header})}> - { - node.header ? - <HeatFileTreeHeader headerTitle={node.name} selectedNode={selectedNode} errorList={this.props.errorList} selectNode={(nodeName) => this.selectNode(nodeName)} /> : - <HeatFileTreeRow toggleExpanded={this.props.toggleExpanded} node={node} path={path} selectedNode={selectedNode} selectNode={() => this.selectNode(node.name)} /> - } - { - isFolder && - <Collapse in={node.expanded}> - <div className='tree-node-children'> - { - node.children.map((child, ind) => this.renderNode(child, [...path, ind])) - } - </div> - </Collapse> - } - </div> - ); - } - - - - - - selectNode(currentSelectedNode) { - let {onDeselectNode, onSelectNode, selectedNode} = this.props; - if (currentSelectedNode !== selectedNode) { - onSelectNode(currentSelectedNode); - } else { - onDeselectNode(); - } - - +class HeatFileTree extends React.Component { + static propTypes = { + attachmentsTree: PropTypes.object.isRequired, + errorList: PropTypes.array.isRequired, + onSelectNode: PropTypes.func.isRequired, + onDeselectNode: PropTypes.func.isRequired, + toggleExpanded: PropTypes.func.isRequired, + selectedNode: PropTypes.string + }; + state = { + treeWidth: '400' + }; + render() { + let { attachmentsTree } = this.props; + return ( + <div + className="validation-tree-section" + style={{ width: this.state.treeWidth + 'px' }}> + <div className="vsp-attachments-heat-validation-tree"> + <div className="tree-wrapper"> + {attachmentsTree && + attachmentsTree.children && + attachmentsTree.children.map((child, ind) => + this.renderNode(child, [ind]) + )} + </div> + </div> + <div + onMouseDown={e => this.onChangeTreeWidth(e)} + className="vsp-attachments-heat-validation-separator" + data-test-id="validation-tree-separator" + /> + </div> + ); + } + renderNode(node, path) { + let rand = Math.random() * (3000 - 1) + 1; + let isFolder = node.children && node.children.length > 0; + let { selectedNode } = this.props; + return ( + <div + key={node.name + rand} + className={classNames({ 'tree-block-inside': !node.header })}> + {node.header ? ( + <HeatFileTreeHeader + headerTitle={node.name} + selectedNode={selectedNode} + errorList={this.props.errorList} + selectNode={nodeName => this.selectNode(nodeName)} + /> + ) : ( + <HeatFileTreeRow + toggleExpanded={this.props.toggleExpanded} + node={node} + path={path} + selectedNode={selectedNode} + selectNode={() => this.selectNode(node.name)} + /> + )} + {isFolder && ( + <Collapse in={node.expanded}> + <div className="tree-node-children"> + {node.children.map((child, ind) => + this.renderNode(child, [...path, ind]) + )} + </div> + </Collapse> + )} + </div> + ); + } - } + selectNode(currentSelectedNode) { + let { onDeselectNode, onSelectNode, selectedNode } = this.props; + if (currentSelectedNode !== selectedNode) { + onSelectNode(currentSelectedNode); + } else { + onDeselectNode(); + } + } - onChangeTreeWidth(e) { - if (e.button === mouseActions.MOUSE_BUTTON_CLICK) { - let onMouseMove = (e) => { - this.setState({treeWidth: e.clientX - leftPanelWidth}); - }; - let onMouseUp = () => { - document.removeEventListener('mousemove', onMouseMove); - document.removeEventListener('mouseup', onMouseUp); - }; - document.addEventListener('mousemove', onMouseMove); - document.addEventListener('mouseup', onMouseUp); - } - } + onChangeTreeWidth(e) { + if (e.button === mouseActions.MOUSE_BUTTON_CLICK) { + let onMouseMove = e => { + this.setState({ treeWidth: e.clientX - leftPanelWidth }); + }; + let onMouseUp = () => { + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp); + }; + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('mouseup', onMouseUp); + } + } } class HeatMessageBoard extends Component { - static propTypes = { - currentErrors: PropTypes.array, - currentWarnings: PropTypes.array, - selectedNode: PropTypes.string - }; - render() { - let {errors, warnings} = this.props; - let allItems = [...errors, ...warnings]; - return ( - <div className='message-board-section'> - { allItems.map(error => this.renderError(error)) } - </div> - ); - } - renderError(error) { - let rand = Math.random() * (3000 - 1) + 1; - return ( - <div - key={error.name + error.errorMessage + error.parentName + rand} - className='error-item' data-test-id='validation-error'> - {error.level === errorLevels.WARNING ? - <SVGIcon name='exclamationTriangleLine' iconClassName='large' color='warning' /> : <SVGIcon name='error' iconClassName='large' color='negative' /> } - <span className='error-item-file-type'> - { - (this.props.selectedNode === nodeFilters.ALL) ? - <span> - <span className='error-file-name'> - {error.name} - </span> - <span> - {error.errorMessage} - </span> - </span> : - error.errorMessage - } - </span> - </div> - ); - } + static propTypes = { + currentErrors: PropTypes.array, + currentWarnings: PropTypes.array, + selectedNode: PropTypes.string + }; + render() { + let { errors, warnings } = this.props; + let allItems = [...errors, ...warnings]; + return ( + <div className="message-board-section"> + {allItems.map(error => this.renderError(error))} + </div> + ); + } + renderError(error) { + let rand = Math.random() * (3000 - 1) + 1; + return ( + <div + key={error.name + error.errorMessage + error.parentName + rand} + className="error-item" + data-test-id="validation-error"> + {error.level === errorLevels.WARNING ? ( + <SVGIcon + name="exclamationTriangleLine" + iconClassName="large" + color="warning" + /> + ) : ( + <SVGIcon + name="error" + iconClassName="large" + color="negative" + /> + )} + <span className="error-item-file-type"> + {this.props.selectedNode === nodeFilters.ALL ? ( + <span> + <span className="error-file-name"> + {error.name} + </span> + <span>{error.errorMessage}</span> + </span> + ) : ( + error.errorMessage + )} + </span> + </div> + ); + } } class ErrorsAndWarningsCount extends Component { - static propTypes = { - errorList: PropTypes.array, - size: PropTypes.string - }; - render() { - let errors = this.getErrorsAndWarningsCount(this.props.errorList); - if (!errors) { - return null; - } - let {size} = this.props; - return (<div className='counters'> - {(errors.errorCount > 0) && <div className='counter'> - <SVGIcon name='error' color='negative' iconClassName={size}/> - <div className={'error-text ' + (size ? size : '')} data-test-id='validation-error-count'>{errors.errorCount}</div> - </div>} - {(errors.warningCount > 0) && <div className='counter'> - <SVGIcon name='exclamationTriangleLine' iconClassName={size} color='warning'/> - <div className={'warning-text ' + (size ? size : '')} data-test-id='validation-warning-count'>{errors.warningCount}</div> - </div>} - </div>); - } - getErrorsAndWarningsCount(errorList) { - let errorCount = 0, warningCount = 0; - if (errorList && errorList.length > 0) { - for (let i = 0; i < errorList.length; i++) { - if (errorList[i].level === errorLevels.ERROR) { - errorCount++; - } else if (errorList[i].level === errorLevels.WARNING) { - warningCount++; - } - } - } - if (errorCount === 0 && warningCount === 0) { - return null; - } - return {errorCount, warningCount}; - } + static propTypes = { + errorList: PropTypes.array, + size: PropTypes.string + }; + render() { + let errors = this.getErrorsAndWarningsCount(this.props.errorList); + if (!errors) { + return null; + } + let { size } = this.props; + return ( + <div className="counters"> + {errors.errorCount > 0 && ( + <div className="counter"> + <SVGIcon + name="error" + color="negative" + iconClassName={size} + /> + <div + className={'error-text ' + (size ? size : '')} + data-test-id="validation-error-count"> + {errors.errorCount} + </div> + </div> + )} + {errors.warningCount > 0 && ( + <div className="counter"> + <SVGIcon + name="exclamationTriangleLine" + iconClassName={size} + color="warning" + /> + <div + className={'warning-text ' + (size ? size : '')} + data-test-id="validation-warning-count"> + {errors.warningCount} + </div> + </div> + )} + </div> + ); + } + getErrorsAndWarningsCount(errorList) { + let errorCount = 0, + warningCount = 0; + if (errorList && errorList.length > 0) { + for (let i = 0; i < errorList.length; i++) { + if (errorList[i].level === errorLevels.ERROR) { + errorCount++; + } else if (errorList[i].level === errorLevels.WARNING) { + warningCount++; + } + } + } + if (errorCount === 0 && warningCount === 0) { + return null; + } + return { errorCount, warningCount }; + } } export default HeatValidationView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js index b13bde03c8..e59337c122 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js @@ -13,79 +13,83 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, forms} from './SoftwareProductComponentsConstants.js'; +import { actionTypes, forms } from './SoftwareProductComponentsConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.COMPONENT_CREATE_OPEN: - return { - ...state, - formName: forms.CREATE_FORM, - formReady: null, - genericFieldInfo: { - 'displayName' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}, {type: 'validateName', data: true}, {type: 'maxLength', data: 25}] - }, - 'description' : { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 1000}] - } - } - }; - case actionTypes.COMPONENT_LOAD: - return { - ...state, - data: action.component, - formReady: null, - formName: forms.ALL_SPC_FORMS, - genericFieldInfo: { - 'displayName' : { - isValid: true, - errorText: '', - validations: [] - }, - 'vfcCode' : { - isValid: true, - errorText: '', - validations: [] - }, - 'nfcFunction' : { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 30}] - }, - 'description' : { - isValid: true, - errorText: '', - validations: [] - } - } - }; - case actionTypes.COMPONENT_UPDATE: - return { - ...state, - data: action.component - }; - case actionTypes.COMPONENT_QUESTIONNAIRE_UPDATE: - return { - ...state, - qdata: action.payload.qdata || state.qdata, - qschema: action.payload.qschema || state.qschema - }; - case actionTypes.COMPONENT_DATA_CHANGED: - return { - ...state, - data: { - ...state.data, - ...action.deltaData - } - }; - case actionTypes.COMPONENT_DATA_CLEAR: - return {}; - default: - return state; - } + switch (action.type) { + case actionTypes.COMPONENT_CREATE_OPEN: + return { + ...state, + formName: forms.CREATE_FORM, + formReady: null, + genericFieldInfo: { + displayName: { + isValid: true, + errorText: '', + validations: [ + { type: 'required', data: true }, + { type: 'validateName', data: true }, + { type: 'maxLength', data: 25 } + ] + }, + description: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 1000 }] + } + } + }; + case actionTypes.COMPONENT_LOAD: + return { + ...state, + data: action.component, + formReady: null, + formName: forms.ALL_SPC_FORMS, + genericFieldInfo: { + displayName: { + isValid: true, + errorText: '', + validations: [] + }, + vfcCode: { + isValid: true, + errorText: '', + validations: [] + }, + nfcFunction: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 30 }] + }, + description: { + isValid: true, + errorText: '', + validations: [] + } + } + }; + case actionTypes.COMPONENT_UPDATE: + return { + ...state, + data: action.component + }; + case actionTypes.COMPONENT_QUESTIONNAIRE_UPDATE: + return { + ...state, + qdata: action.payload.qdata || state.qdata, + qschema: action.payload.qschema || state.qschema + }; + case actionTypes.COMPONENT_DATA_CHANGED: + return { + ...state, + data: { + ...state.data, + ...action.deltaData + } + }; + case actionTypes.COMPONENT_DATA_CLEAR: + return {}; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js index f74b2fe2fb..bffa9f7d25 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js @@ -1,50 +1,71 @@ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; import SoftwareProductComponentsActionHelper from '../components/SoftwareProductComponentsActionHelper.js'; -import {onboardingMethod as onboardingMethodTypes} from '../SoftwareProductConstants.js'; +import { onboardingMethod as onboardingMethodTypes } from '../SoftwareProductConstants.js'; import ConfirmationModalConstants from 'nfvo-components/modal/GlobalModalConstants.js'; import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js'; -import {screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js'; +import { screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js'; import SoftwareProductComponentsView from './SoftwareProductComponentsListView.jsx'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; -const generateMessage = (name) => { - return i18n('Are you sure you want to delete {name}?', {name: name}); +const generateMessage = name => { + return i18n('Are you sure you want to delete {name}?', { name: name }); }; -const mapStateToProps = ({softwareProduct, currentScreen: {props: {version}}}) => { - let {softwareProductEditor: {data: currentSoftwareProduct = {}}, softwareProductComponents} = softwareProduct; - let {componentsList} = softwareProductComponents; - let {onboardingMethod = onboardingMethodTypes.HEAT} = currentSoftwareProduct; - return { - currentSoftwareProduct, - componentsList, - isManual: onboardingMethod === onboardingMethodTypes.MANUAL, - version - }; +const mapStateToProps = ({ + softwareProduct, + currentScreen: { props: { version } } +}) => { + let { + softwareProductEditor: { data: currentSoftwareProduct = {} }, + softwareProductComponents + } = softwareProduct; + let { componentsList } = softwareProductComponents; + let { + onboardingMethod = onboardingMethodTypes.HEAT + } = currentSoftwareProduct; + return { + currentSoftwareProduct, + componentsList, + isManual: onboardingMethod === onboardingMethodTypes.MANUAL, + version + }; }; -const mapActionToProps = (dispatch) => { - return { - onComponentSelect: ({id: softwareProductId, componentId, version}) => - ScreensHelper.loadScreen(dispatch, { - screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version, componentId} - }), - onAddComponent: (softwareProductId, version) => SoftwareProductActionHelper.addComponent(dispatch, {softwareProductId, version, modalClassName: 'create-vfc-modal'}), - onDeleteComponent: (component, softwareProductId, version) => dispatch({ - type: ConfirmationModalConstants.GLOBAL_MODAL_WARNING, - data:{ - msg: generateMessage(component.displayName), - onConfirmed: ()=>SoftwareProductComponentsActionHelper.deleteComponent(dispatch, { - softwareProductId, - componentId: component.id, - version - }) - } - }) - }; +const mapActionToProps = dispatch => { + return { + onComponentSelect: ({ id: softwareProductId, componentId, version }) => + ScreensHelper.loadScreen(dispatch, { + screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version, componentId } + }), + onAddComponent: (softwareProductId, version) => + SoftwareProductActionHelper.addComponent(dispatch, { + softwareProductId, + version, + modalClassName: 'create-vfc-modal' + }), + onDeleteComponent: (component, softwareProductId, version) => + dispatch({ + type: ConfirmationModalConstants.GLOBAL_MODAL_WARNING, + data: { + msg: generateMessage(component.displayName), + onConfirmed: () => + SoftwareProductComponentsActionHelper.deleteComponent( + dispatch, + { + softwareProductId, + componentId: component.id, + version + } + ) + } + }) + }; }; -export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(SoftwareProductComponentsView); +export default connect(mapStateToProps, mapActionToProps, null, { + withRef: true +})(SoftwareProductComponentsView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js index cf63ad79d0..73a971ccbb 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js @@ -16,157 +16,265 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; -import {actionTypes, COMPONENTS_QUESTIONNAIRE} from './SoftwareProductComponentsConstants.js'; +import { + actionTypes, + COMPONENTS_QUESTIONNAIRE +} from './SoftwareProductComponentsConstants.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; function baseUrl(softwareProductId, version) { - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components`; } function fetchSoftwareProductComponents(softwareProductId, version) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); + return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); } -function putSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId, vspComponent) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire`, vspComponent); +function putSoftwareProductComponentQuestionnaire( + softwareProductId, + version, + vspComponentId, + vspComponent +) { + return RestAPIUtil.put( + `${baseUrl( + softwareProductId, + version + )}/${vspComponentId}/questionnaire`, + vspComponent + ); } -function fetchSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId){ - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire`); +function fetchSoftwareProductComponentQuestionnaire( + softwareProductId, + version, + vspComponentId +) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire` + ); } -function fetchSoftwareProductComponent(softwareProductId, version, vspComponentId){ - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${vspComponentId}`); +function fetchSoftwareProductComponent( + softwareProductId, + version, + vspComponentId +) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version)}/${vspComponentId}` + ); } -function putSoftwareProductComponent(softwareProductId, version, vspComponentId, vspComponent) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${vspComponentId}`, { - name: vspComponent.name, - displayName: vspComponent.displayName, - vfcCode: vspComponent.vfcCode, - nfcFunction: vspComponent.nfcFunction, - description: vspComponent.description - }); +function putSoftwareProductComponent( + softwareProductId, + version, + vspComponentId, + vspComponent +) { + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version)}/${vspComponentId}`, + { + name: vspComponent.name, + displayName: vspComponent.displayName, + vfcCode: vspComponent.vfcCode, + nfcFunction: vspComponent.nfcFunction, + description: vspComponent.description + } + ); } -function deleteSoftwareProductComponent(softwareProductId, componentId, version) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${componentId}`,); +function deleteSoftwareProductComponent( + softwareProductId, + componentId, + version +) { + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version)}/${componentId}` + ); } +function postSoftwareProductComponent( + softwareProductId, + vspComponent, + version +) { + return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { + name: vspComponent.displayName, + displayName: vspComponent.displayName, + description: vspComponent.description + }); +} -function postSoftwareProductComponent(softwareProductId, vspComponent, version) { +const SoftwareProductComponentsActionHelper = { + fetchSoftwareProductComponents(dispatch, { softwareProductId, version }) { + return fetchSoftwareProductComponents(softwareProductId, version).then( + response => { + dispatch({ + type: actionTypes.COMPONENTS_LIST_UPDATE, + componentsList: response.results + }); + return response; + } + ); + }, - return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { - name: vspComponent.displayName, - displayName: vspComponent.displayName, - description: vspComponent.description - }); -} + updateSoftwareProductComponent( + dispatch, + { softwareProductId, version, vspComponentId, componentData, qdata } + ) { + return Promise.all([ + SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire( + dispatch, + { softwareProductId, version, vspComponentId, qdata } + ), + SoftwareProductComponentsActionHelper.updateSoftwareProductComponentData( + dispatch, + { softwareProductId, version, vspComponentId, componentData } + ) + ]); + }, + updateSoftwareProductComponentQuestionnaire( + dispatch, + { softwareProductId, version, vspComponentId, qdata } + ) { + return putSoftwareProductComponentQuestionnaire( + softwareProductId, + version, + vspComponentId, + qdata + ); + }, -const SoftwareProductComponentsActionHelper = { - fetchSoftwareProductComponents(dispatch, {softwareProductId, version}) { - return fetchSoftwareProductComponents(softwareProductId, version).then(response => { - dispatch({ - type: actionTypes.COMPONENTS_LIST_UPDATE, - componentsList: response.results - }); - return response; - }); - }, - - updateSoftwareProductComponent(dispatch, {softwareProductId, version, vspComponentId, componentData, qdata}) { - return Promise.all([ - SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId, qdata}), - SoftwareProductComponentsActionHelper.updateSoftwareProductComponentData(dispatch, {softwareProductId, version, vspComponentId, componentData}) - ]); - }, - - updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId, qdata}) { - return putSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId, qdata); - }, - - updateSoftwareProductComponentData(dispatch, {softwareProductId, version, vspComponentId, componentData}) { - return putSoftwareProductComponent(softwareProductId, version, vspComponentId, componentData).then(() => dispatch({ - type: actionTypes.COMPONENTS_LIST_EDIT, - component: { - id: vspComponentId, - ...componentData - } - })); - }, - - fetchSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId}) { - return fetchSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId).then(response => { - ValidationHelper.qDataLoaded(dispatch, {qName: COMPONENTS_QUESTIONNAIRE, response: {qdata: response.data ? JSON.parse(response.data) : {}, - qschema: JSON.parse(response.schema)}}); - }); - }, - - fetchSoftwareProductComponent(dispatch, {softwareProductId, version, vspComponentId}) { - return Promise.all([ - fetchSoftwareProductComponent(softwareProductId, version, vspComponentId).then(response => { - dispatch({ - type: actionTypes.COMPONENT_LOAD, - component: response.data - }); - return response; - }), - fetchSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId).then(response => { - ValidationHelper.qDataLoaded(dispatch, {qName: COMPONENTS_QUESTIONNAIRE, response: {qdata: response.data ? JSON.parse(response.data) : {}, - qschema: JSON.parse(response.schema)}}); - }) - ]); - }, - - - clearComponentsStore(dispatch) { - dispatch({ - type: actionTypes.COMPONENTS_LIST_UPDATE, - componentsList: [] - }); - }, - - createSoftwareProductComponent(dispatch,{softwareProductId, componentData, version}) { - SoftwareProductComponentsActionHelper.closeComponentCreationModal(dispatch); - /* for mock only */ - - dispatch({ - type: actionTypes.COMPONENTS_LIST_UPDATE, - componentsList: [{id: '123', ...componentData}] - }); - - postSoftwareProductComponent(softwareProductId, componentData, version).then(() => { - SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version}); - }); - }, - - clearComponentCreationData(dispatch) { - dispatch({ - type: actionTypes.COMPONENT_DATA_CLEAR - }); - }, - - closeComponentCreationModal(dispatch) { - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_CLOSE - }); - SoftwareProductComponentsActionHelper.clearComponentCreationData(dispatch); - }, - - deleteComponent(dispatch, {softwareProductId, componentId, version}) { - deleteSoftwareProductComponent(softwareProductId, componentId, version); - dispatch({ - type: actionTypes.COMPONENT_DELETE, - componentId: componentId - }); - }, + updateSoftwareProductComponentData( + dispatch, + { softwareProductId, version, vspComponentId, componentData } + ) { + return putSoftwareProductComponent( + softwareProductId, + version, + vspComponentId, + componentData + ).then(() => + dispatch({ + type: actionTypes.COMPONENTS_LIST_EDIT, + component: { + id: vspComponentId, + ...componentData + } + }) + ); + }, + + fetchSoftwareProductComponentQuestionnaire( + dispatch, + { softwareProductId, version, vspComponentId } + ) { + return fetchSoftwareProductComponentQuestionnaire( + softwareProductId, + version, + vspComponentId + ).then(response => { + ValidationHelper.qDataLoaded(dispatch, { + qName: COMPONENTS_QUESTIONNAIRE, + response: { + qdata: response.data ? JSON.parse(response.data) : {}, + qschema: JSON.parse(response.schema) + } + }); + }); + }, + + fetchSoftwareProductComponent( + dispatch, + { softwareProductId, version, vspComponentId } + ) { + return Promise.all([ + fetchSoftwareProductComponent( + softwareProductId, + version, + vspComponentId + ).then(response => { + dispatch({ + type: actionTypes.COMPONENT_LOAD, + component: response.data + }); + return response; + }), + fetchSoftwareProductComponentQuestionnaire( + softwareProductId, + version, + vspComponentId + ).then(response => { + ValidationHelper.qDataLoaded(dispatch, { + qName: COMPONENTS_QUESTIONNAIRE, + response: { + qdata: response.data ? JSON.parse(response.data) : {}, + qschema: JSON.parse(response.schema) + } + }); + }) + ]); + }, + + clearComponentsStore(dispatch) { + dispatch({ + type: actionTypes.COMPONENTS_LIST_UPDATE, + componentsList: [] + }); + }, + + createSoftwareProductComponent( + dispatch, + { softwareProductId, componentData, version } + ) { + SoftwareProductComponentsActionHelper.closeComponentCreationModal( + dispatch + ); + /* for mock only */ + + dispatch({ + type: actionTypes.COMPONENTS_LIST_UPDATE, + componentsList: [{ id: '123', ...componentData }] + }); + + postSoftwareProductComponent( + softwareProductId, + componentData, + version + ).then(() => { + SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents( + dispatch, + { softwareProductId, version } + ); + }); + }, + clearComponentCreationData(dispatch) { + dispatch({ + type: actionTypes.COMPONENT_DATA_CLEAR + }); + }, + closeComponentCreationModal(dispatch) { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }); + SoftwareProductComponentsActionHelper.clearComponentCreationData( + dispatch + ); + }, + deleteComponent(dispatch, { softwareProductId, componentId, version }) { + deleteSoftwareProductComponent(softwareProductId, componentId, version); + dispatch({ + type: actionTypes.COMPONENT_DELETE, + componentId: componentId + }); + } }; export default SoftwareProductComponentsActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js index 35633b65cf..cc120d359a 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js @@ -16,40 +16,40 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - COMPONENTS_LIST_UPDATE: null, - COMPONENTS_LIST_EDIT: null, - COMPONENT_UPDATE: null, - COMPONENT_DATA_CHANGED: null, - COMPONENT_DATA_CLEAR: null, - COMPONENT_QUESTIONNAIRE_UPDATE: null, - COMPONENT_DELETE: null, - COMPONENT_LOAD: null, - COMPONENT_CREATE_OPEN: null + COMPONENTS_LIST_UPDATE: null, + COMPONENTS_LIST_EDIT: null, + COMPONENT_UPDATE: null, + COMPONENT_DATA_CHANGED: null, + COMPONENT_DATA_CLEAR: null, + COMPONENT_QUESTIONNAIRE_UPDATE: null, + COMPONENT_DELETE: null, + COMPONENT_LOAD: null, + COMPONENT_CREATE_OPEN: null }); -export const storageConstants = keyMirror({ - backupType: { - ON_SITE: 'OnSite', - OFF_SITE: 'OffSite' - } +export const storageConstants = keyMirror({ + backupType: { + ON_SITE: 'OnSite', + OFF_SITE: 'OffSite' + } }); export const forms = keyMirror({ - ALL_SPC_FORMS: null, - NIC_EDIT_FORM: null, - CREATE_FORM: null, - IMAGE_EDIT_FORM: null + ALL_SPC_FORMS: null, + NIC_EDIT_FORM: null, + CREATE_FORM: null, + IMAGE_EDIT_FORM: null }); export const COMPONENTS_QUESTIONNAIRE = 'component'; export const COMPONENTS_COMPUTE_QUESTIONNAIRE = 'compute'; export const navigationItems = keyMirror({ - STORAGE: 'Storage', - PROCESS_DETAILS: 'Process Details', - MONITORING: 'Monitoring', - NETWORK: 'Network', - IMAGES: 'Images', - COMPUTE: 'Compute', - LOAD_BALANCING: 'High Availability & Load Balancing' + STORAGE: 'Storage', + PROCESS_DETAILS: 'Process Details', + MONITORING: 'Monitoring', + NETWORK: 'Network', + IMAGES: 'Images', + COMPUTE: 'Compute', + LOAD_BALANCING: 'High Availability & Load Balancing' }); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js index 92211e0fd2..e1cf5f4fc3 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js @@ -13,18 +13,26 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductComponentsConstants.js'; +import { actionTypes } from './SoftwareProductComponentsConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.COMPONENTS_LIST_UPDATE: - return [...action.componentsList]; - case actionTypes.COMPONENTS_LIST_EDIT: - const indexForEdit = state.findIndex(component => component.id === action.component.id); - return [...state.slice(0, indexForEdit), action.component, ...state.slice(indexForEdit + 1)]; - case actionTypes.COMPONENT_DELETE: - return state.filter(component => component.id !== action.componentId); - default: - return state; - } + switch (action.type) { + case actionTypes.COMPONENTS_LIST_UPDATE: + return [...action.componentsList]; + case actionTypes.COMPONENTS_LIST_EDIT: + const indexForEdit = state.findIndex( + component => component.id === action.component.id + ); + return [ + ...state.slice(0, indexForEdit), + action.component, + ...state.slice(indexForEdit + 1) + ]; + case actionTypes.COMPONENT_DELETE: + return state.filter( + component => component.id !== action.componentId + ); + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx index 0bf32df1a3..fc8abf6ff6 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx @@ -22,85 +22,113 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx'; const ComponentPropType = PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string, - displayName: PropTypes.string, - description: PropTypes.string + id: PropTypes.string, + name: PropTypes.string, + displayName: PropTypes.string, + description: PropTypes.string }); class SoftwareProductComponentsListView extends React.Component { + state = { + localFilter: '' + }; - state = { - localFilter: '' - }; + static propTypes = { + isReadOnlyMode: PropTypes.bool, + componentsList: PropTypes.arrayOf(ComponentPropType), + onComponentSelect: PropTypes.func + }; - static propTypes = { - isReadOnlyMode: PropTypes.bool, - componentsList: PropTypes.arrayOf(ComponentPropType), - onComponentSelect: PropTypes.func - }; + render() { + let { componentsList = [], isManual } = this.props; + return ( + <div className=""> + {(componentsList.length > 0 || isManual) && + this.renderComponents()} + </div> + ); + } - render() { - let {componentsList = [], isManual} = this.props; - return ( - <div className=''> - { - (componentsList.length > 0 || isManual) && this.renderComponents() - } - </div> - ); - } + renderComponents() { + const { localFilter } = this.state; + const { + isManual, + onAddComponent, + isReadOnlyMode, + version, + currentSoftwareProduct: { id: softwareProductId }, + componentsList + } = this.props; + return ( + <ListEditorView + title={i18n('Virtual Function Components')} + filterValue={localFilter} + placeholder={i18n('Filter Components')} + onFilter={value => this.setState({ localFilter: value })} + isReadOnlyMode={isReadOnlyMode || !!this.filterList().length} + plusButtonTitle={i18n('Add Component')} + onAdd={ + isManual && componentsList.length === 0 + ? () => onAddComponent(softwareProductId, version) + : false + } + twoColumns> + {this.filterList().map(component => + this.renderComponentsListItem(component) + )} + </ListEditorView> + ); + } - renderComponents() { - const {localFilter} = this.state; - const {isManual, onAddComponent, isReadOnlyMode, version, currentSoftwareProduct: {id: softwareProductId}, componentsList } = this.props; - return ( - <ListEditorView - title={i18n('Virtual Function Components')} - filterValue={localFilter} - placeholder={i18n('Filter Components')} - onFilter={value => this.setState({localFilter: value})} - isReadOnlyMode={isReadOnlyMode || !!this.filterList().length} - plusButtonTitle={i18n('Add Component')} - onAdd={isManual && componentsList.length === 0 ? () => onAddComponent(softwareProductId, version) : false} - twoColumns> - {this.filterList().map(component => this.renderComponentsListItem(component))} - </ListEditorView> - ); - } + renderComponentsListItem(component) { + let { + id: componentId, + name, + displayName, + description = '' + } = component; + let { + currentSoftwareProduct: { id }, + onComponentSelect, + version + } = this.props; + return ( + <ListEditorItemView + key={ + name + Math.floor(Math.random() * (100 - 1) + 1).toString() + } + className="list-editor-item-view" + onSelect={() => + onComponentSelect({ id, componentId, version }) + }> + <ListEditorItemViewField> + <div className="name">{displayName}</div> + </ListEditorItemViewField> + <ListEditorItemViewField> + <div className="description">{description}</div> + </ListEditorItemViewField> + </ListEditorItemView> + ); + } - renderComponentsListItem(component) { - let {id: componentId, name, displayName, description = ''} = component; - let {currentSoftwareProduct: {id}, onComponentSelect, version} = this.props; - return ( - <ListEditorItemView - key={name + Math.floor(Math.random() * (100 - 1) + 1).toString()} - className='list-editor-item-view' - onSelect={() => onComponentSelect({id, componentId, version})}> - <ListEditorItemViewField> - <div className='name'>{displayName}</div> - </ListEditorItemViewField> - <ListEditorItemViewField> - <div className='description'>{description}</div> - </ListEditorItemViewField> - </ListEditorItemView> - ); - } + filterList() { + let { componentsList = [] } = this.props; - filterList() { - let {componentsList = []} = this.props; - - let {localFilter} = this.state; - if (localFilter.trim()) { - const filter = new RegExp(escape(localFilter), 'i'); - return componentsList.filter(({displayName = '', description = ''}) => { - return escape(displayName).match(filter) || escape(description).match(filter); - }); - } - else { - return componentsList; - } - } + let { localFilter } = this.state; + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return componentsList.filter( + ({ displayName = '', description = '' }) => { + return ( + escape(displayName).match(filter) || + escape(description).match(filter) + ); + } + ); + } else { + return componentsList; + } + } } export default SoftwareProductComponentsListView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js index 02c09fbdf8..cd37c317af 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js @@ -16,154 +16,270 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes} from './computeComponents/computeFlavor/ComputeFlavorConstants.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; -import {actionTypes as globalModalActionTypes, modalSizes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes } from './computeComponents/computeFlavor/ComputeFlavorConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; +import { + actionTypes as globalModalActionTypes, + modalSizes +} from 'nfvo-components/modal/GlobalModalConstants.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { COMPONENTS_COMPUTE_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; function baseUrl(softwareProductId, componentId, version) { - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/compute-flavors`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/compute-flavors`; } -function baseUrlVSPLevel(softwareProductId, version){ - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/compute-flavors`; +function baseUrlVSPLevel(softwareProductId, version) { + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/compute-flavors`; } -function fetchComputesList(softwareProductId, componentId, version){ - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}`); +function fetchComputesList(softwareProductId, componentId, version) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, componentId, version)}` + ); } -function fetchComputesListForVSP(softwareProductId, version){ - return RestAPIUtil.fetch(`${baseUrlVSPLevel(softwareProductId, version)}`); +function fetchComputesListForVSP(softwareProductId, version) { + return RestAPIUtil.fetch(`${baseUrlVSPLevel(softwareProductId, version)}`); } function fetchCompute(softwareProductId, componentId, computeId, version) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}/${computeId}`); + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, componentId, version)}/${computeId}` + ); } -function fetchComputeQuestionnaire({softwareProductId, componentId, computeId, version}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}/${computeId}/questionnaire`); +function fetchComputeQuestionnaire({ + softwareProductId, + componentId, + computeId, + version +}) { + return RestAPIUtil.fetch( + `${baseUrl( + softwareProductId, + componentId, + version + )}/${computeId}/questionnaire` + ); } -function postCompute({softwareProductId, componentId, compute, version}) { - return RestAPIUtil.post(baseUrl(softwareProductId, componentId, version), compute); +function postCompute({ softwareProductId, componentId, compute, version }) { + return RestAPIUtil.post( + baseUrl(softwareProductId, componentId, version), + compute + ); } -function putCompute({softwareProductId, componentId, compute, version}) { - const computeData = { - name: compute.name, - description: compute.description - }; - return RestAPIUtil.put(`${baseUrl(softwareProductId, componentId, version)}/${compute.id}`, computeData); +function putCompute({ softwareProductId, componentId, compute, version }) { + const computeData = { + name: compute.name, + description: compute.description + }; + return RestAPIUtil.put( + `${baseUrl(softwareProductId, componentId, version)}/${compute.id}`, + computeData + ); } -function putComputeQuestionnaire({softwareProductId, componentId, computeId, qdata, version}) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, componentId, version)}/${computeId}/questionnaire`, qdata); +function putComputeQuestionnaire({ + softwareProductId, + componentId, + computeId, + qdata, + version +}) { + return RestAPIUtil.put( + `${baseUrl( + softwareProductId, + componentId, + version + )}/${computeId}/questionnaire`, + qdata + ); } -function deleteCompute({softwareProductId, componentId, computeId, version}) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, componentId, version)}/${computeId}`); +function deleteCompute({ softwareProductId, componentId, computeId, version }) { + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, componentId, version)}/${computeId}` + ); } - const ComputeFlavorActionHelper = { - openComputeEditor(dispatch, {props}) { - dispatch({ - type: actionTypes.computeEditor.LOAD_EDITOR_DATA, - compute: props.compute || {} - }); - dispatch({ - type: globalModalActionTypes.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.COMPONENT_COMPUTE_FLAVOR_EDITOR, - modalClassName: `compute-flavor-editor-modal-${props.compute ? 'edit' : 'create'}`, - modalComponentProps: {...props, size: props.compute ? modalSizes.LARGE : undefined, dialogClassName:'compute-flavor-editor-modal'}, - title: `${props.compute ? i18n('Edit Compute Flavor') : i18n('Create New Compute Flavor')}` - } - }); - }, - - closeComputeEditor(dispatch){ - dispatch({ - type: globalModalActionTypes.GLOBAL_MODAL_CLOSE - }); - dispatch({ - type: actionTypes.computeEditor.CLEAR_DATA - }); - }, - - fetchComputesList(dispatch, {softwareProductId, componentId, version}) { - return fetchComputesList(softwareProductId, componentId, version).then(response => dispatch({ - type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED, - response - })); - }, - - fetchComputesListForVSP(dispatch, {softwareProductId, version}) { - return fetchComputesListForVSP(softwareProductId, version).then(response => dispatch({ - type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED, - response - })); - }, - - loadComputeData({softwareProductId, componentId, computeId, version}) { - return fetchCompute(softwareProductId, componentId, computeId, version); - }, - - loadComputeQuestionnaire(dispatch, {softwareProductId, componentId, computeId, version}) { - return fetchComputeQuestionnaire({softwareProductId, componentId, computeId, version}).then(response => - ValidationHelper.qDataLoaded(dispatch, {qName: COMPONENTS_COMPUTE_QUESTIONNAIRE ,response: { - qdata: response.data ? JSON.parse(response.data) : {}, - qschema: JSON.parse(response.schema) - }}) - ); - }, - - loadCompute(dispatch, {softwareProductId, componentId, version, computeId, isReadOnlyMode}){ - return ComputeFlavorActionHelper.loadComputeData({softwareProductId, componentId, computeId, version}).then(({data}) => - ComputeFlavorActionHelper.loadComputeQuestionnaire(dispatch, {softwareProductId, componentId, computeId, version}).then(() => - ComputeFlavorActionHelper.openComputeEditor(dispatch, {props: {softwareProductId, componentId, version, isReadOnlyMode, compute: {id: computeId, ...data}}}) - )); - }, - - saveComputeDataAndQuestionnaire(dispatch, {softwareProductId, componentId, data: compute, qdata, version}) { - ComputeFlavorActionHelper.closeComputeEditor(dispatch); - if(compute.id) { - return Promise.all([ - putComputeQuestionnaire({softwareProductId, componentId, computeId: compute.id, qdata, version}), - putCompute({softwareProductId, componentId, compute, version}).then(() => { - dispatch({ - type: actionTypes.COMPUTE_LIST_EDIT, - compute - }); - }) - ]); - } - else { - return postCompute({softwareProductId, componentId, compute, version}).then(response => - dispatch({ - type: actionTypes.ADD_COMPUTE, - compute: { - ...compute, - id: response.id, - componentId - } - }) - ); - } - }, - - deleteCompute(dispatch, {softwareProductId, componentId, computeId, version}) { - return deleteCompute({softwareProductId, componentId, computeId, version}).then(() => dispatch({ - type: actionTypes.DELETE_COMPUTE, - computeId - })); - } + openComputeEditor(dispatch, { props }) { + dispatch({ + type: actionTypes.computeEditor.LOAD_EDITOR_DATA, + compute: props.compute || {} + }); + dispatch({ + type: globalModalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: + modalContentMapper.COMPONENT_COMPUTE_FLAVOR_EDITOR, + modalClassName: `compute-flavor-editor-modal-${ + props.compute ? 'edit' : 'create' + }`, + modalComponentProps: { + ...props, + size: props.compute ? modalSizes.LARGE : undefined, + dialogClassName: 'compute-flavor-editor-modal' + }, + title: `${ + props.compute + ? i18n('Edit Compute Flavor') + : i18n('Create New Compute Flavor') + }` + } + }); + }, + + closeComputeEditor(dispatch) { + dispatch({ + type: globalModalActionTypes.GLOBAL_MODAL_CLOSE + }); + dispatch({ + type: actionTypes.computeEditor.CLEAR_DATA + }); + }, + + fetchComputesList(dispatch, { softwareProductId, componentId, version }) { + return fetchComputesList(softwareProductId, componentId, version).then( + response => + dispatch({ + type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED, + response + }) + ); + }, + + fetchComputesListForVSP(dispatch, { softwareProductId, version }) { + return fetchComputesListForVSP(softwareProductId, version).then( + response => + dispatch({ + type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED, + response + }) + ); + }, + + loadComputeData({ softwareProductId, componentId, computeId, version }) { + return fetchCompute(softwareProductId, componentId, computeId, version); + }, + + loadComputeQuestionnaire( + dispatch, + { softwareProductId, componentId, computeId, version } + ) { + return fetchComputeQuestionnaire({ + softwareProductId, + componentId, + computeId, + version + }).then(response => + ValidationHelper.qDataLoaded(dispatch, { + qName: COMPONENTS_COMPUTE_QUESTIONNAIRE, + response: { + qdata: response.data ? JSON.parse(response.data) : {}, + qschema: JSON.parse(response.schema) + } + }) + ); + }, + + loadCompute( + dispatch, + { softwareProductId, componentId, version, computeId, isReadOnlyMode } + ) { + return ComputeFlavorActionHelper.loadComputeData({ + softwareProductId, + componentId, + computeId, + version + }).then(({ data }) => + ComputeFlavorActionHelper.loadComputeQuestionnaire(dispatch, { + softwareProductId, + componentId, + computeId, + version + }).then(() => + ComputeFlavorActionHelper.openComputeEditor(dispatch, { + props: { + softwareProductId, + componentId, + version, + isReadOnlyMode, + compute: { id: computeId, ...data } + } + }) + ) + ); + }, + + saveComputeDataAndQuestionnaire( + dispatch, + { softwareProductId, componentId, data: compute, qdata, version } + ) { + ComputeFlavorActionHelper.closeComputeEditor(dispatch); + if (compute.id) { + return Promise.all([ + putComputeQuestionnaire({ + softwareProductId, + componentId, + computeId: compute.id, + qdata, + version + }), + putCompute({ + softwareProductId, + componentId, + compute, + version + }).then(() => { + dispatch({ + type: actionTypes.COMPUTE_LIST_EDIT, + compute + }); + }) + ]); + } else { + return postCompute({ + softwareProductId, + componentId, + compute, + version + }).then(response => + dispatch({ + type: actionTypes.ADD_COMPUTE, + compute: { + ...compute, + id: response.id, + componentId + } + }) + ); + } + }, + + deleteCompute( + dispatch, + { softwareProductId, componentId, computeId, version } + ) { + return deleteCompute({ + softwareProductId, + componentId, + computeId, + version + }).then(() => + dispatch({ + type: actionTypes.DELETE_COMPUTE, + computeId + }) + ); + } }; export default ComputeFlavorActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js index 574828c9ef..d595a82e11 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js @@ -13,35 +13,63 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductComponentComputeView from './SoftwareProductComponentComputeView.jsx'; import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js'; -import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {onboardingMethod} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { onboardingMethod } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductEditor: { data: currentVSP }, + softwareProductComponents + } = softwareProduct; + let { + componentEditor: { qdata, dataMap, qgenericFieldInfo }, + computeFlavor: { computesList: computeFlavorsList } + } = softwareProductComponents; -const mapStateToProps = ({softwareProduct}) => { - let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct; - let {componentEditor: {qdata, dataMap, qgenericFieldInfo}, computeFlavor: {computesList: computeFlavorsList}} = softwareProductComponents; - - return { - qdata, - dataMap, - qgenericFieldInfo, - computeFlavorsList, - isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL - }; + return { + qdata, + dataMap, + qgenericFieldInfo, + computeFlavorsList, + isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL + }; }; -const mapActionToProps = (dispatch, {softwareProductId, version, componentId}) => { - return { - onQDataChanged: (deltaData, customValidations) => ValidationHelper.qDataChanged(dispatch, {deltaData, customValidations: customValidations, - qName: COMPONENTS_QUESTIONNAIRE}), - onSubmit: ({qdata}) =>{ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata});}, - qValidateData: (data, customValidations) => ValidationHelper.qValidateData(dispatch, {data, customValidations: customValidations, - qName: COMPONENTS_QUESTIONNAIRE}) - }; +const mapActionToProps = ( + dispatch, + { softwareProductId, version, componentId } +) => { + return { + onQDataChanged: (deltaData, customValidations) => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + customValidations: customValidations, + qName: COMPONENTS_QUESTIONNAIRE + }), + onSubmit: ({ qdata }) => { + return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire( + dispatch, + { + softwareProductId, + version, + vspComponentId: componentId, + qdata + } + ); + }, + qValidateData: (data, customValidations) => + ValidationHelper.qValidateData(dispatch, { + data, + customValidations: customValidations, + qName: COMPONENTS_QUESTIONNAIRE + }) + }; }; -export default connect(mapStateToProps, mapActionToProps, null, {withRef: true}) (SoftwareProductComponentComputeView); +export default connect(mapStateToProps, mapActionToProps, null, { + withRef: true +})(SoftwareProductComponentComputeView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentComputeView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentComputeView.jsx index 55e5e2b30b..e6ce96666e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentComputeView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentComputeView.jsx @@ -22,67 +22,99 @@ import ComputeFlavors from './computeComponents/ComputeFlavors.js'; import Validator from 'nfvo-utils/Validator.js'; class SoftwareProductComponentComputeView extends React.Component { + static propTypes = { + dataMap: PropTypes.object, + qgenericFieldInfo: PropTypes.object, + isReadOnlyMode: PropTypes.bool, + isManual: PropTypes.bool, + onQDataChanged: PropTypes.func.isRequired, + qValidateData: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired + }; - static propTypes = { - dataMap: PropTypes.object, - qgenericFieldInfo: PropTypes.object, - isReadOnlyMode: PropTypes.bool, - isManual: PropTypes.bool, - onQDataChanged: PropTypes.func.isRequired, - qValidateData: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired - }; + render() { + let { + softwareProductId, + componentId, + version, + qdata, + dataMap, + qgenericFieldInfo, + isReadOnlyMode, + onQDataChanged, + qValidateData, + onSubmit, + computeFlavorsList, + isManual + } = this.props; - render() { - let {softwareProductId, componentId, version, qdata, dataMap, qgenericFieldInfo, isReadOnlyMode, onQDataChanged, qValidateData, - onSubmit, computeFlavorsList, isManual} = this.props; + return ( + <div className="vsp-component-questionnaire-view"> + {qgenericFieldInfo && ( + <Form + ref={form => { + this.form = form; + }} + formReady={null} + isValid={true} + hasButtons={false} + onSubmit={() => onSubmit({ qdata })} + className="component-questionnaire-validation-form" + isReadOnlyMode={isReadOnlyMode}> + <NumberOfVms + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qgenericFieldInfo} + qValidateData={qValidateData} + customValidations={{ + 'compute/numOfVMs/maximum': this.validateMax, + 'compute/numOfVMs/minimum': this.validateMin + }} + /> + <GuestOs + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qgenericFieldInfo} + /> + <ComputeFlavors + computeFlavorsList={computeFlavorsList} + softwareProductId={softwareProductId} + componentId={componentId} + version={version} + isReadOnlyMode={isReadOnlyMode} + isManual={isManual} + /> + </Form> + )} + </div> + ); + } - return ( - <div className='vsp-component-questionnaire-view'> - { qgenericFieldInfo && <Form - ref={ (form) => { this.form = form; }} - formReady={null} - isValid={true} - hasButtons={false} - onSubmit={() => onSubmit({qdata})} - className='component-questionnaire-validation-form' - isReadOnlyMode={isReadOnlyMode} > - <NumberOfVms onQDataChanged={onQDataChanged} dataMap={dataMap} - qgenericFieldInfo={qgenericFieldInfo} qValidateData={qValidateData} - customValidations={{'compute/numOfVMs/maximum' : this.validateMax, 'compute/numOfVMs/minimum': this.validateMin}} /> - <GuestOs onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} /> - <ComputeFlavors computeFlavorsList={computeFlavorsList} softwareProductId={softwareProductId} componentId={componentId} - version={version} isReadOnlyMode={isReadOnlyMode} isManual={isManual}/> - </Form> } - </div> - ); - } + save() { + return this.form.handleFormSubmit(new Event('dummy')); + } - save(){ - return this.form.handleFormSubmit(new Event('dummy')); - } + validateMin(value, state) { + let maxVal = state.dataMap['compute/numOfVMs/maximum']; + // we are allowed to have an empty maxval, that will allow all minvals. + // if we do not have a minval than there is no point to check it either. + if (value === undefined || maxVal === undefined) { + return { isValid: true, errorText: '' }; + } else { + return Validator.validateItem(value, maxVal, 'maximum'); + } + } - validateMin(value, state) { - let maxVal = state.dataMap['compute/numOfVMs/maximum']; - // we are allowed to have an empty maxval, that will allow all minvals. - // if we do not have a minval than there is no point to check it either. - if (value === undefined || maxVal === undefined) { - return { isValid: true, errorText: '' }; - } else { - return Validator.validateItem(value, maxVal,'maximum'); - } - } - - validateMax(value, state) { - let minVal = state.dataMap['compute/numOfVMs/minimum']; - if (minVal === undefined ) { - // having no minimum is the same as 0, maximum value doesn't need to be checked - // against it. - return { isValid: true, errorText: '' }; - } else { - return Validator.validateItem(value,minVal,'minimum'); - } - } + validateMax(value, state) { + let minVal = state.dataMap['compute/numOfVMs/minimum']; + if (minVal === undefined) { + // having no minimum is the same as 0, maximum value doesn't need to be checked + // against it. + return { isValid: true, errorText: '' }; + } else { + return Validator.validateItem(value, minVal, 'minimum'); + } + } } export default SoftwareProductComponentComputeView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js index 2b6d84f381..2004c94137 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js @@ -15,103 +15,159 @@ */ import React from 'react'; import PropTypes from 'prop-types'; -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx'; import ComputeFlavorActionHelper from 'sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; -const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => { - return { - onAddComputeClick: (isReadOnlyMode) => ComputeFlavorActionHelper.openComputeEditor(dispatch, {props: {softwareProductId, componentId, isReadOnlyMode, version}}), - onEditCompute: ({computeId, isReadOnlyMode}) => ComputeFlavorActionHelper.loadCompute(dispatch, {softwareProductId, componentId, version, computeId, isReadOnlyMode}), - onDeleteCompute: ({id, name}) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data:{ - msg: i18n('Are you sure you want to delete "{name}"?', {name: name}), - onConfirmed: () => ComputeFlavorActionHelper.deleteCompute(dispatch, {softwareProductId, componentId, computeId: id, version}) - } - }) - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, componentId, version } +) => { + return { + onAddComputeClick: isReadOnlyMode => + ComputeFlavorActionHelper.openComputeEditor(dispatch, { + props: { + softwareProductId, + componentId, + isReadOnlyMode, + version + } + }), + onEditCompute: ({ computeId, isReadOnlyMode }) => + ComputeFlavorActionHelper.loadCompute(dispatch, { + softwareProductId, + componentId, + version, + computeId, + isReadOnlyMode + }), + onDeleteCompute: ({ id, name }) => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + msg: i18n('Are you sure you want to delete "{name}"?', { + name: name + }), + onConfirmed: () => + ComputeFlavorActionHelper.deleteCompute(dispatch, { + softwareProductId, + componentId, + computeId: id, + version + }) + } + }) + }; }; const computeItemPropType = PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string, - description: PropTypes.string + id: PropTypes.string, + name: PropTypes.string, + description: PropTypes.string }); class ComputeFlavors extends React.Component { + static propTypes = { + isReadOnlyMode: PropTypes.bool, + isManual: PropTypes.bool, + onAddComputeClick: PropTypes.func, + computeFlavorsList: PropTypes.arrayOf(computeItemPropType) + }; - static propTypes = { - isReadOnlyMode: PropTypes.bool, - isManual: PropTypes.bool, - onAddComputeClick: PropTypes.func, - computeFlavorsList: PropTypes.arrayOf(computeItemPropType) - }; + state = { + localFilter: '' + }; - state = { - localFilter: '' - }; + render() { + const { localFilter } = this.state; + const { + isReadOnlyMode, + isManual, + onAddComputeClick, + onEditCompute, + onDeleteCompute + } = this.props; + return ( + <div className="computes-list"> + <ListEditorView + title={i18n('Computes')} + plusButtonTitle={i18n('Add Compute')} + onAdd={ + isManual + ? () => onAddComputeClick(isReadOnlyMode) + : null + } + isReadOnlyMode={isReadOnlyMode} + onFilter={ + isManual + ? value => this.setState({ localFilter: value }) + : null + } + filterValue={localFilter} + twoColumns> + {this.filterList().map(computeItem => ( + <ComputeItem + key={computeItem.id} + computeItem={computeItem} + isReadOnlyMode={isReadOnlyMode} + isManual={isManual} + onEditCompute={onEditCompute} + onDeleteCompute={onDeleteCompute} + /> + ))} + </ListEditorView> + </div> + ); + } - render() { - const {localFilter} = this.state; - const {isReadOnlyMode, isManual, onAddComputeClick, onEditCompute, onDeleteCompute} = this.props; - return ( - <div className='computes-list'> - <ListEditorView - title={i18n('Computes')} - plusButtonTitle={i18n('Add Compute')} - onAdd={isManual ? () => onAddComputeClick(isReadOnlyMode) : null} - isReadOnlyMode={isReadOnlyMode} - onFilter={isManual ? value => this.setState({localFilter: value}) : null} - filterValue={localFilter} - twoColumns> - {this.filterList().map(computeItem => - <ComputeItem key={computeItem.id} - computeItem={computeItem} isReadOnlyMode={isReadOnlyMode} isManual={isManual} - onEditCompute={onEditCompute} onDeleteCompute={onDeleteCompute}/>) - } - </ListEditorView> - </div> - ); - } + filterList() { + const { computeFlavorsList = [] } = this.props; - filterList() { - const {computeFlavorsList = []} = this.props; - - const {localFilter} = this.state; - if (localFilter.trim()) { - const filter = new RegExp(escape(localFilter), 'i'); - return computeFlavorsList.filter(({name = '', description = ''}) => { - return escape(name).match(filter) || escape(description).match(filter); - }); - } - else { - return computeFlavorsList; - } - } + const { localFilter } = this.state; + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return computeFlavorsList.filter( + ({ name = '', description = '' }) => { + return ( + escape(name).match(filter) || + escape(description).match(filter) + ); + } + ); + } else { + return computeFlavorsList; + } + } } -const ComputeItem = ({computeItem, isReadOnlyMode, isManual, onEditCompute, onDeleteCompute}) => { - const {id, name, description} = computeItem; - return ( - <ListEditorItemView - key={'item_' + id} - className='list-editor-item-view' - isReadOnlyMode={isReadOnlyMode} - onSelect={() => onEditCompute({computeId: id, isReadOnlyMode})} - onDelete={isManual ? () => onDeleteCompute({id, name}) : null}> - - <div className='list-editor-item-view-field'> - <div className='name'>{name}</div> - </div> - <div className='list-editor-item-view-field'> - <div className='description'>{description}</div> - </div> - </ListEditorItemView> - ); +const ComputeItem = ({ + computeItem, + isReadOnlyMode, + isManual, + onEditCompute, + onDeleteCompute +}) => { + const { id, name, description } = computeItem; + return ( + <ListEditorItemView + key={'item_' + id} + className="list-editor-item-view" + isReadOnlyMode={isReadOnlyMode} + onSelect={() => onEditCompute({ computeId: id, isReadOnlyMode })} + onDelete={isManual ? () => onDeleteCompute({ id, name }) : null}> + <div className="list-editor-item-view-field"> + <div className="name">{name}</div> + </div> + <div className="list-editor-item-view-field"> + <div className="description">{description}</div> + </div> + </ListEditorItemView> + ); }; -export default connect(null, mapActionsToProps, null, {withRef: true})(ComputeFlavors); +export default connect(null, mapActionsToProps, null, { withRef: true })( + ComputeFlavors +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx index 8ae9961859..c16ab5cdfe 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx @@ -19,57 +19,91 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; - -const GuestOs = ({qgenericFieldInfo, dataMap, onQDataChanged}) => { - return( - <div> - <GridSection title={i18n('Guest OS')} hasLastColSet> - <GridItem> - <div className='vertical-flex'> - <label key='label' className='control-label'>{i18n('OS Bit Size')}</label> - <div className='radio-options-content-row'> - {qgenericFieldInfo['compute/guestOS/bitSize'].enum.map(bitSize => ( - <Input - data-test-id='guestOS-bitSize' - type='radio' - key={bitSize.enum} - name={'compute/guestOS/bitSize'} - className='radio-field' - value={bitSize.enum} - label={bitSize.title} - onChange={(bit) => onQDataChanged({'compute/guestOS/bitSize' : Number(bit)})} - isValid={qgenericFieldInfo['compute/guestOS/bitSize'].isValid} - errorText={qgenericFieldInfo['compute/guestOS/bitSize'].errorText} - checked={dataMap['compute/guestOS/bitSize'] === bitSize.enum} /> )) } - </div> - </div> - </GridItem> - <GridItem colSpan={2}/> - <GridItem colSpan={2}> - <Input - data-test-id='guestOS-name' - label={i18n('Guest OS')} - type='textarea' - onChange={(tools) => onQDataChanged({'compute/guestOS/name' : tools})} - isValid={qgenericFieldInfo['compute/guestOS/name'].isValid} - errorText={qgenericFieldInfo['compute/guestOS/name'].errorText} - value={dataMap['compute/guestOS/name']} /> - </GridItem> - <GridItem colSpan={2} lastColInRow> - <Input - data-test-id='guestOS-tools' - type='textarea' - label={i18n('Guest OS Tools:')} - onChange={(tools) => onQDataChanged({'compute/guestOS/tools' : tools})} - isValid={qgenericFieldInfo['compute/guestOS/tools'].isValid} - errorText={qgenericFieldInfo['compute/guestOS/tools'].errorText} - value={dataMap['compute/guestOS/tools']} /> - </GridItem> - </GridSection> - - - </div> - ); +const GuestOs = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => { + return ( + <div> + <GridSection title={i18n('Guest OS')} hasLastColSet> + <GridItem> + <div className="vertical-flex"> + <label key="label" className="control-label"> + {i18n('OS Bit Size')} + </label> + <div className="radio-options-content-row"> + {qgenericFieldInfo[ + 'compute/guestOS/bitSize' + ].enum.map(bitSize => ( + <Input + data-test-id="guestOS-bitSize" + type="radio" + key={bitSize.enum} + name={'compute/guestOS/bitSize'} + className="radio-field" + value={bitSize.enum} + label={bitSize.title} + onChange={bit => + onQDataChanged({ + 'compute/guestOS/bitSize': Number( + bit + ) + }) + } + isValid={ + qgenericFieldInfo[ + 'compute/guestOS/bitSize' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'compute/guestOS/bitSize' + ].errorText + } + checked={ + dataMap['compute/guestOS/bitSize'] === + bitSize.enum + } + /> + ))} + </div> + </div> + </GridItem> + <GridItem colSpan={2} /> + <GridItem colSpan={2}> + <Input + data-test-id="guestOS-name" + label={i18n('Guest OS')} + type="textarea" + onChange={tools => + onQDataChanged({ 'compute/guestOS/name': tools }) + } + isValid={ + qgenericFieldInfo['compute/guestOS/name'].isValid + } + errorText={ + qgenericFieldInfo['compute/guestOS/name'].errorText + } + value={dataMap['compute/guestOS/name']} + /> + </GridItem> + <GridItem colSpan={2} lastColInRow> + <Input + data-test-id="guestOS-tools" + type="textarea" + label={i18n('Guest OS Tools:')} + onChange={tools => + onQDataChanged({ 'compute/guestOS/tools': tools }) + } + isValid={ + qgenericFieldInfo['compute/guestOS/tools'].isValid + } + errorText={ + qgenericFieldInfo['compute/guestOS/tools'].errorText + } + value={dataMap['compute/guestOS/tools']} + /> + </GridItem> + </GridSection> + </div> + ); }; export default GuestOs; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx index 967c6f7aef..5451354502 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx @@ -20,38 +20,77 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; - -const NumberOfVms = ({qgenericFieldInfo, dataMap, onQDataChanged, qValidateData, customValidations}) => { - return( - <GridSection titleClassName='software-product-compute-number-of-vms' title={i18n('NUMBER OF VMs')}> - <GridItem> - <Input - data-test-id='numOfVMs-minimum' - type='number' - label={i18n('Minimum')} - onChange={(tools) => { onQDataChanged({'compute/numOfVMs/minimum' : tools}, customValidations); - qValidateData({'compute/numOfVMs/maximum' : dataMap['compute/numOfVMs/maximum']}, customValidations); } } - isValid={qgenericFieldInfo['compute/numOfVMs/minimum'].isValid} - errorText={qgenericFieldInfo['compute/numOfVMs/minimum'].errorText} - value={dataMap['compute/numOfVMs/minimum']} /> - </GridItem> - <GridItem> - <Input - data-test-id='numOfVMs-maximum' - type='number' - label={i18n('Maximum')} - onChange={(tools) => { onQDataChanged({'compute/numOfVMs/maximum' : tools}, customValidations); - qValidateData({'compute/numOfVMs/minimum' : dataMap['compute/numOfVMs/minimum']}, customValidations); } } - isValid={qgenericFieldInfo['compute/numOfVMs/maximum'].isValid} - errorText={qgenericFieldInfo['compute/numOfVMs/maximum'].errorText} - value={dataMap['compute/numOfVMs/maximum']} /> - </GridItem> - </GridSection> - ); +const NumberOfVms = ({ + qgenericFieldInfo, + dataMap, + onQDataChanged, + qValidateData, + customValidations +}) => { + return ( + <GridSection + titleClassName="software-product-compute-number-of-vms" + title={i18n('NUMBER OF VMs')}> + <GridItem> + <Input + data-test-id="numOfVMs-minimum" + type="number" + label={i18n('Minimum')} + onChange={tools => { + onQDataChanged( + { 'compute/numOfVMs/minimum': tools }, + customValidations + ); + qValidateData( + { + 'compute/numOfVMs/maximum': + dataMap['compute/numOfVMs/maximum'] + }, + customValidations + ); + }} + isValid={ + qgenericFieldInfo['compute/numOfVMs/minimum'].isValid + } + errorText={ + qgenericFieldInfo['compute/numOfVMs/minimum'].errorText + } + value={dataMap['compute/numOfVMs/minimum']} + /> + </GridItem> + <GridItem> + <Input + data-test-id="numOfVMs-maximum" + type="number" + label={i18n('Maximum')} + onChange={tools => { + onQDataChanged( + { 'compute/numOfVMs/maximum': tools }, + customValidations + ); + qValidateData( + { + 'compute/numOfVMs/minimum': + dataMap['compute/numOfVMs/minimum'] + }, + customValidations + ); + }} + isValid={ + qgenericFieldInfo['compute/numOfVMs/maximum'].isValid + } + errorText={ + qgenericFieldInfo['compute/numOfVMs/maximum'].errorText + } + value={dataMap['compute/numOfVMs/maximum']} + /> + </GridItem> + </GridSection> + ); }; NumberOfVms.propTypes = { - minNumberOfVMsSelectedByUser: PropTypes.number + minNumberOfVMsSelectedByUser: PropTypes.number }; export default NumberOfVms; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js index 41728eefb0..58c27c6bba 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js @@ -19,14 +19,14 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const COMPUTE_FLAVOR_FORM = 'COMPUTE_FLAVOR_FORM'; export const actionTypes = keyMirror({ - ADD_COMPUTE: null, - COMPUTE_FLAVORS_LIST_LOADED: null, - COMPUTE_LIST_EDIT: null, - EDIT_COMPUTE_FLAVOR: null, - DELETE_COMPUTE: null, - CONFIRM_DELETE_COMPUTE: null, - computeEditor: { - LOAD_EDITOR_DATA: null, - CLEAR_DATA: null - } + ADD_COMPUTE: null, + COMPUTE_FLAVORS_LIST_LOADED: null, + COMPUTE_LIST_EDIT: null, + EDIT_COMPUTE_FLAVOR: null, + DELETE_COMPUTE: null, + CONFIRM_DELETE_COMPUTE: null, + computeEditor: { + LOAD_EDITOR_DATA: null, + CLEAR_DATA: null + } }); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js index a3ba5fbc4a..06f9e8fd19 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js @@ -13,49 +13,78 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import ComputeFlavorEditorView from './ComputeFlavorEditorView.jsx'; -import {COMPUTE_FLAVOR_FORM} from './ComputeFlavorConstants.js'; +import { COMPUTE_FLAVOR_FORM } from './ComputeFlavorConstants.js'; import ComputeFlavorActionHelper from 'sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; -import {onboardingMethod} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { COMPONENTS_COMPUTE_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { onboardingMethod } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; export const mapStateToProps = ({ - softwareProduct: { - softwareProductEditor, - softwareProductComponents: {computeFlavor: {computeEditor = {}}} - }, - currentScreen: { - props: {isReadOnlyMode} - } + softwareProduct: { + softwareProductEditor, + softwareProductComponents: { computeFlavor: { computeEditor = {} } } + }, + currentScreen: { props: { isReadOnlyMode } } }) => { - const {data: currentSoftwareProduct = {}} = softwareProductEditor; - let {data , qdata, qgenericFieldInfo, dataMap, genericFieldInfo, formReady} = computeEditor; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); + const { data: currentSoftwareProduct = {} } = softwareProductEditor; + let { + data, + qdata, + qgenericFieldInfo, + dataMap, + genericFieldInfo, + formReady + } = computeEditor; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - return { - data, - qdata, - qgenericFieldInfo, - dataMap, - genericFieldInfo, - isReadOnlyMode, - isFormValid, - formReady, - isManual: currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL - }; + return { + data, + qdata, + qgenericFieldInfo, + dataMap, + genericFieldInfo, + isReadOnlyMode, + isFormValid, + formReady, + isManual: + currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL + }; }; - -const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => { - return { - onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: COMPUTE_FLAVOR_FORM}), - onQDataChanged: deltaData => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_COMPUTE_QUESTIONNAIRE}), - onCancel: () => ComputeFlavorActionHelper.closeComputeEditor(dispatch), - onSubmit: ({data, qdata}) => ComputeFlavorActionHelper.saveComputeDataAndQuestionnaire(dispatch, {softwareProductId, componentId, data, qdata, version}), - onValidateForm: () => ValidationHelper.validateForm(dispatch, COMPUTE_FLAVOR_FORM) - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, componentId, version } +) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: COMPUTE_FLAVOR_FORM + }), + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: COMPONENTS_COMPUTE_QUESTIONNAIRE + }), + onCancel: () => ComputeFlavorActionHelper.closeComputeEditor(dispatch), + onSubmit: ({ data, qdata }) => + ComputeFlavorActionHelper.saveComputeDataAndQuestionnaire( + dispatch, + { + softwareProductId, + componentId, + data, + qdata, + version + } + ), + onValidateForm: () => + ValidationHelper.validateForm(dispatch, COMPUTE_FLAVOR_FORM) + }; }; -export default connect(mapStateToProps, mapActionsToProps)(ComputeFlavorEditorView); +export default connect(mapStateToProps, mapActionsToProps)( + ComputeFlavorEditorView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx index e542ce1fd1..840f722bb2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx @@ -23,75 +23,112 @@ import VmSizing from './VmSizing.jsx'; import i18n from 'nfvo-utils/i18n/i18n.js'; class ComputeEditorView extends React.Component { + static propTypes = { + data: PropTypes.object, + qdata: PropTypes.object, + qschema: PropTypes.object, + isReadOnlyMode: PropTypes.bool, + isManual: PropTypes.bool, + onDataChanged: PropTypes.func.isRequired, + onQDataChanged: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired + }; - static propTypes = { - data: PropTypes.object, - qdata: PropTypes.object, - qschema: PropTypes.object, - isReadOnlyMode: PropTypes.bool, - isManual: PropTypes.bool, - onDataChanged: PropTypes.func.isRequired, - onQDataChanged: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, - onCancel: PropTypes.func.isRequired - }; + render() { + let { + data = {}, + qdata = {}, + qgenericFieldInfo, + dataMap, + genericFieldInfo, + isReadOnlyMode, + isManual, + isFormValid, + formReady, + onDataChanged, + onQDataChanged, + onSubmit, + onCancel, + onValidateForm + } = this.props; + const { id, name, description } = data; + const edittingComputeMode = Boolean(id); - render() { - let {data = {}, qdata = {}, qgenericFieldInfo, dataMap, genericFieldInfo, isReadOnlyMode, isManual, isFormValid, formReady, - onDataChanged, onQDataChanged, onSubmit, onCancel, onValidateForm} = this.props; - const {id, name, description} = data; - const edittingComputeMode = Boolean(id); + return ( + <div className="vsp-component-computeFlavor-view"> + {genericFieldInfo && ( + <Form + ref={form => { + this.form = form; + }} + hasButtons={true} + onSubmit={() => onSubmit({ data, qdata })} + onReset={() => onCancel()} + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + isValid={isFormValid} + formReady={formReady} + onValidateForm={() => onValidateForm()} + className="component-questionnaire-validation-form" + submitButtonText={ + edittingComputeMode ? i18n('Save') : i18n('Create') + }> + <GridSection hasLostColSet> + <GridItem + colSpan={edittingComputeMode ? 2 : 4} + lastColInRow={!edittingComputeMode}> + <Input + disabled={!isManual} + data-test-id="name" + type="text" + label={i18n('Flavor Name')} + value={name} + onChange={name => onDataChanged({ name })} + isValid={genericFieldInfo['name'].isValid} + errorText={ + genericFieldInfo['name'].errorText + } + isRequired + /> + </GridItem> + <GridItem + colSpan={edittingComputeMode ? 2 : 4} + lastColInRow> + <Input + data-test-id="description" + type="textarea" + label={i18n('Description')} + value={description} + onChange={description => + onDataChanged({ description }) + } + isValid={ + genericFieldInfo['description'].isValid + } + errorText={ + genericFieldInfo['description'] + .errorText + } + /> + </GridItem> + </GridSection> + {edittingComputeMode && ( + <VmSizing + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + )} + </Form> + )} + </div> + ); + } - return ( - <div className='vsp-component-computeFlavor-view'> - {genericFieldInfo && <Form - ref={(form) => { - this.form = form; - }} - hasButtons={true} - onSubmit={ () => onSubmit({data, qdata}) } - onReset={ () => onCancel() } - labledButtons={true} - isReadOnlyMode={isReadOnlyMode} - isValid={isFormValid} - formReady={formReady} - onValidateForm={() => onValidateForm() } - className='component-questionnaire-validation-form' - submitButtonText={edittingComputeMode ? i18n('Save') : i18n('Create')}> - <GridSection hasLostColSet> - <GridItem colSpan={edittingComputeMode ? 2 : 4} lastColInRow={!edittingComputeMode}> - <Input - disabled={!isManual} - data-test-id='name' - type='text' - label={i18n('Flavor Name')} - value={name} - onChange={name => onDataChanged({name})} - isValid={genericFieldInfo['name'].isValid} - errorText={genericFieldInfo['name'].errorText} - isRequired/> - </GridItem> - <GridItem colSpan={edittingComputeMode ? 2 : 4} lastColInRow> - <Input - data-test-id='description' - type='textarea' - label={i18n('Description')} - value={description} - onChange={description => onDataChanged({description})} - isValid={genericFieldInfo['description'].isValid} - errorText={genericFieldInfo['description'].errorText}/> - </GridItem> - </GridSection> - {edittingComputeMode && <VmSizing qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged}/>} - </Form> - } - </div> - ); - } - - save(){ - return this.form.handleFormSubmit(new Event('dummy')); - } + save() { + return this.form.handleFormSubmit(new Event('dummy')); + } } export default ComputeEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js index 6c02f36c90..b691084cc3 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js @@ -14,20 +14,26 @@ * permissions and limitations under the License. */ -import {actionTypes} from './ComputeFlavorConstants.js'; +import { actionTypes } from './ComputeFlavorConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.COMPUTE_FLAVORS_LIST_LOADED: - return [...action.response.results]; - case actionTypes.ADD_COMPUTE: - return [...state, action.compute]; - case actionTypes.COMPUTE_LIST_EDIT: - const indexForEdit = state.findIndex(({id}) => id === action.compute.id); - return [...state.slice(0, indexForEdit), action.compute, ...state.slice(indexForEdit + 1)]; - case actionTypes.DELETE_COMPUTE: - return state.filter(({id}) => id !== action.computeId); - default: - return state; - } -};
\ No newline at end of file + switch (action.type) { + case actionTypes.COMPUTE_FLAVORS_LIST_LOADED: + return [...action.response.results]; + case actionTypes.ADD_COMPUTE: + return [...state, action.compute]; + case actionTypes.COMPUTE_LIST_EDIT: + const indexForEdit = state.findIndex( + ({ id }) => id === action.compute.id + ); + return [ + ...state.slice(0, indexForEdit), + action.compute, + ...state.slice(indexForEdit + 1) + ]; + case actionTypes.DELETE_COMPUTE: + return state.filter(({ id }) => id !== action.computeId); + default: + return state; + } +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js index a476f85a19..00d76eff23 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js @@ -13,33 +13,32 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, COMPUTE_FLAVOR_FORM} from './ComputeFlavorConstants.js'; +import { actionTypes, COMPUTE_FLAVOR_FORM } from './ComputeFlavorConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.computeEditor.LOAD_EDITOR_DATA: - return { - ...state, - formName: COMPUTE_FLAVOR_FORM, - data: action.compute, - formReady: null, - genericFieldInfo: { - name: { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true }] - }, - description: { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 300}] - } - } - }; - case actionTypes.computeEditor.CLEAR_DATA: - return {}; - default: - return state; - } + switch (action.type) { + case actionTypes.computeEditor.LOAD_EDITOR_DATA: + return { + ...state, + formName: COMPUTE_FLAVOR_FORM, + data: action.compute, + formReady: null, + genericFieldInfo: { + name: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + }, + description: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 300 }] + } + } + }; + case actionTypes.computeEditor.CLEAR_DATA: + return {}; + default: + return state; + } }; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx index 54f22e0760..2f40706736 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx @@ -18,89 +18,146 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const VmSizing = ({qgenericFieldInfo, dataMap, onQDataChanged}) => { - return( - <GridSection title={i18n('VM Sizing')} hasLastColSet> - <GridItem> - <Input - data-test-id='numOfCPUs' - type='number' - label={i18n('Number of CPUs')} - onChange={(tools) => onQDataChanged({'vmSizing/numOfCPUs' : tools})} - isValid={qgenericFieldInfo['vmSizing/numOfCPUs'].isValid} - errorText={qgenericFieldInfo['vmSizing/numOfCPUs'].errorText} - value={dataMap['vmSizing/numOfCPUs']} /> - </GridItem> - <GridItem> - <Input - data-test-id='fileSystemSizeGB' - type='number' - label={i18n('File System Size (GB)')} - onChange={(tools) => onQDataChanged({'vmSizing/fileSystemSizeGB' : tools})} - isValid={qgenericFieldInfo['vmSizing/fileSystemSizeGB'].isValid} - errorText={qgenericFieldInfo['vmSizing/fileSystemSizeGB'].errorText} - value={dataMap['vmSizing/fileSystemSizeGB']} /> - </GridItem> - <GridItem> - <Input - data-test-id='persistentStorageVolumeSize' - type='number' - label={i18n('Persistent Storage/Volume Size (GB)')} - onChange={(tools) => onQDataChanged({'vmSizing/persistentStorageVolumeSize' : tools})} - isValid={qgenericFieldInfo['vmSizing/persistentStorageVolumeSize'].isValid} - errorText={qgenericFieldInfo['vmSizing/persistentStorageVolumeSize'].errorText} - value={dataMap['vmSizing/persistentStorageVolumeSize']} /> - </GridItem> - <GridItem lastColInRow> - <Input - data-test-id='ioOperationsPerSec' - type='number' - label={i18n('I/O Operations (per second)')} - onChange={(tools) => onQDataChanged({'vmSizing/ioOperationsPerSec' : tools})} - isValid={qgenericFieldInfo['vmSizing/ioOperationsPerSec'].isValid} - errorText={qgenericFieldInfo['vmSizing/ioOperationsPerSec'].errorText} - value={dataMap['vmSizing/ioOperationsPerSec']} /> - </GridItem> - <GridItem> - <Input - data-test-id='numOfVMs-cpuOverSubscriptionRatio' - label={i18n('CPU Oversubscription Ratio')} - type='select' - groupClassName='bootstrap-input-options' - className='input-options-select' - isValid={qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].isValid} - errorText={qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].errorText} - value={dataMap['vmSizing/cpuOverSubscriptionRatio']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'vmSizing/cpuOverSubscriptionRatio' : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - {qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].enum.map(cpuOSR => <option value={cpuOSR.enum} key={cpuOSR.enum}>{cpuOSR.title}</option>)} - </Input> - </GridItem> - <GridItem> - <Input - data-test-id='numOfVMs-memoryRAM' - type='select' - label={i18n('Memory - RAM')} - groupClassName='bootstrap-input-options' - className='input-options-select' - isValid={qgenericFieldInfo['vmSizing/memoryRAM'].isValid} - errorText={qgenericFieldInfo['vmSizing/memoryRAM'].errorText} - value={dataMap['vmSizing/memoryRAM']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'vmSizing/memoryRAM' : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - {qgenericFieldInfo['vmSizing/memoryRAM'].enum.map(mRAM => <option value={mRAM.enum} key={mRAM.enum}>{mRAM.title}</option>)} - </Input> - </GridItem> - </GridSection> - ); +const VmSizing = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => { + return ( + <GridSection title={i18n('VM Sizing')} hasLastColSet> + <GridItem> + <Input + data-test-id="numOfCPUs" + type="number" + label={i18n('Number of CPUs')} + onChange={tools => + onQDataChanged({ 'vmSizing/numOfCPUs': tools }) + } + isValid={qgenericFieldInfo['vmSizing/numOfCPUs'].isValid} + errorText={ + qgenericFieldInfo['vmSizing/numOfCPUs'].errorText + } + value={dataMap['vmSizing/numOfCPUs']} + /> + </GridItem> + <GridItem> + <Input + data-test-id="fileSystemSizeGB" + type="number" + label={i18n('File System Size (GB)')} + onChange={tools => + onQDataChanged({ 'vmSizing/fileSystemSizeGB': tools }) + } + isValid={ + qgenericFieldInfo['vmSizing/fileSystemSizeGB'].isValid + } + errorText={ + qgenericFieldInfo['vmSizing/fileSystemSizeGB'].errorText + } + value={dataMap['vmSizing/fileSystemSizeGB']} + /> + </GridItem> + <GridItem> + <Input + data-test-id="persistentStorageVolumeSize" + type="number" + label={i18n('Persistent Storage/Volume Size (GB)')} + onChange={tools => + onQDataChanged({ + 'vmSizing/persistentStorageVolumeSize': tools + }) + } + isValid={ + qgenericFieldInfo[ + 'vmSizing/persistentStorageVolumeSize' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'vmSizing/persistentStorageVolumeSize' + ].errorText + } + value={dataMap['vmSizing/persistentStorageVolumeSize']} + /> + </GridItem> + <GridItem lastColInRow> + <Input + data-test-id="ioOperationsPerSec" + type="number" + label={i18n('I/O Operations (per second)')} + onChange={tools => + onQDataChanged({ 'vmSizing/ioOperationsPerSec': tools }) + } + isValid={ + qgenericFieldInfo['vmSizing/ioOperationsPerSec'].isValid + } + errorText={ + qgenericFieldInfo['vmSizing/ioOperationsPerSec'] + .errorText + } + value={dataMap['vmSizing/ioOperationsPerSec']} + /> + </GridItem> + <GridItem> + <Input + data-test-id="numOfVMs-cpuOverSubscriptionRatio" + label={i18n('CPU Oversubscription Ratio')} + type="select" + groupClassName="bootstrap-input-options" + className="input-options-select" + isValid={ + qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'] + .isValid + } + errorText={ + qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'] + .errorText + } + value={dataMap['vmSizing/cpuOverSubscriptionRatio']} + onChange={e => { + const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onQDataChanged({ + 'vmSizing/cpuOverSubscriptionRatio': val + }); + }}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {qgenericFieldInfo[ + 'vmSizing/cpuOverSubscriptionRatio' + ].enum.map(cpuOSR => ( + <option value={cpuOSR.enum} key={cpuOSR.enum}> + {cpuOSR.title} + </option> + ))} + </Input> + </GridItem> + <GridItem> + <Input + data-test-id="numOfVMs-memoryRAM" + type="select" + label={i18n('Memory - RAM')} + groupClassName="bootstrap-input-options" + className="input-options-select" + isValid={qgenericFieldInfo['vmSizing/memoryRAM'].isValid} + errorText={ + qgenericFieldInfo['vmSizing/memoryRAM'].errorText + } + value={dataMap['vmSizing/memoryRAM']} + onChange={e => { + const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onQDataChanged({ 'vmSizing/memoryRAM': val }); + }}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {qgenericFieldInfo['vmSizing/memoryRAM'].enum.map(mRAM => ( + <option value={mRAM.enum} key={mRAM.enum}> + {mRAM.title} + </option> + ))} + </Input> + </GridItem> + </GridSection> + ); }; export default VmSizing; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js index 9f59cd5b27..d831765674 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js @@ -14,36 +14,50 @@ * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductComponentCreationView from './SoftwareProductComponentCreationView.jsx'; import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {forms} from '../SoftwareProductComponentsConstants.js'; +import { forms } from '../SoftwareProductComponentsConstants.js'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductComponents: {componentEditor: {data, genericFieldInfo, formReady}}} = softwareProduct; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - return { - data, - genericFieldInfo, - formReady, - isFormValid - }; +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductComponents: { + componentEditor: { data, genericFieldInfo, formReady } + } + } = softwareProduct; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); + return { + data, + genericFieldInfo, + formReady, + isFormValid + }; }; - -const mapActionsToProps = (dispatch, {softwareProductId, version}) => { - return { - onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.CREATE_FORM}), - //onDataChanged: deltaData => SoftwareProductComponentsActionHelper.componentDataChanged(dispatch, {deltaData}), - onSubmit: (componentData) => { - return SoftwareProductComponentsActionHelper.createSoftwareProductComponent(dispatch, - {softwareProductId, componentData, version}); - }, - onCancel: () => SoftwareProductComponentsActionHelper.closeComponentCreationModal(dispatch), - onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName) - }; - +const mapActionsToProps = (dispatch, { softwareProductId, version }) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: forms.CREATE_FORM + }), + //onDataChanged: deltaData => SoftwareProductComponentsActionHelper.componentDataChanged(dispatch, {deltaData}), + onSubmit: componentData => { + return SoftwareProductComponentsActionHelper.createSoftwareProductComponent( + dispatch, + { softwareProductId, componentData, version } + ); + }, + onCancel: () => + SoftwareProductComponentsActionHelper.closeComponentCreationModal( + dispatch + ), + onValidateForm: formName => + ValidationHelper.validateForm(dispatch, formName) + }; }; -export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentCreationView); +export default connect(mapStateToProps, mapActionsToProps)( + SoftwareProductComponentCreationView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx index 42804ce5a6..0b33b4017f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx @@ -21,59 +21,80 @@ import Form from 'nfvo-components/input/validation/Form.jsx'; import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -import {forms} from '../SoftwareProductComponentsConstants.js'; +import { forms } from '../SoftwareProductComponentsConstants.js'; class ComponentCreationView extends React.Component { - render() { - let {data = {}, onDataChanged, onCancel, genericFieldInfo} = this.props; - let {displayName, description} = data; - return( - <div> - { - genericFieldInfo && <Form - ref='validationForm' - hasButtons={true} - onSubmit={ () => this.submit() } - onReset={ () => onCancel() } - submitButtonText={i18n('Create')} - labledButtons={true} - isValid={this.props.isFormValid} - formReady={this.props.formReady} - onValidateForm={() => this.props.onValidateForm(forms.CREATE_FORM) } - className='entitlement-pools-form'> - <GridSection hasLastColSet> - <GridItem colSpan={4} lastColInRow> - <Input - data-test-id='name' - onChange={displayName => onDataChanged({displayName})} - label={i18n('Name')} - isRequired={true} - isValid={genericFieldInfo.displayName.isValid} - errorText={genericFieldInfo.displayName.errorText} - value={displayName} - type='text'/> - </GridItem> - <GridItem colSpan={4} lastColInRow> - <Input - label={i18n('Description')} - onChange={description => onDataChanged({description})} - value={description} - isValid={genericFieldInfo.description.isValid} - errorText={genericFieldInfo.description.errorText} - data-test-id='description' - type='textarea'/> - </GridItem> - </GridSection> - </Form> - } - </div> - ); - } + render() { + let { + data = {}, + onDataChanged, + onCancel, + genericFieldInfo + } = this.props; + let { displayName, description } = data; + return ( + <div> + {genericFieldInfo && ( + <Form + ref="validationForm" + hasButtons={true} + onSubmit={() => this.submit()} + onReset={() => onCancel()} + submitButtonText={i18n('Create')} + labledButtons={true} + isValid={this.props.isFormValid} + formReady={this.props.formReady} + onValidateForm={() => + this.props.onValidateForm(forms.CREATE_FORM) + } + className="entitlement-pools-form"> + <GridSection hasLastColSet> + <GridItem colSpan={4} lastColInRow> + <Input + data-test-id="name" + onChange={displayName => + onDataChanged({ displayName }) + } + label={i18n('Name')} + isRequired={true} + isValid={ + genericFieldInfo.displayName.isValid + } + errorText={ + genericFieldInfo.displayName.errorText + } + value={displayName} + type="text" + /> + </GridItem> + <GridItem colSpan={4} lastColInRow> + <Input + label={i18n('Description')} + onChange={description => + onDataChanged({ description }) + } + value={description} + isValid={ + genericFieldInfo.description.isValid + } + errorText={ + genericFieldInfo.description.errorText + } + data-test-id="description" + type="textarea" + /> + </GridItem> + </GridSection> + </Form> + )} + </div> + ); + } - submit() { - const {onSubmit, data} = this.props; - onSubmit(data); - } + submit() { + const { onSubmit, data } = this.props; + onSubmit(data); + } } export default ComponentCreationView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js index 8c06fd0ab8..f3f64e4b20 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js @@ -13,41 +13,79 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductComponentsGeneralView from './SoftwareProductComponentsGeneralView.jsx'; import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; -import {forms, COMPONENTS_QUESTIONNAIRE} from '../SoftwareProductComponentsConstants.js'; -import {onboardingMethod} from '../../SoftwareProductConstants.js'; +import { + forms, + COMPONENTS_QUESTIONNAIRE +} from '../SoftwareProductComponentsConstants.js'; +import { onboardingMethod } from '../../SoftwareProductConstants.js'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct; - let {componentEditor: {data: componentData = {} , qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap, genericFieldInfo}} = softwareProductComponents; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductEditor: { data: currentVSP }, + softwareProductComponents + } = softwareProduct; + let { + componentEditor: { + data: componentData = {}, + qdata, + qgenericFieldInfo: qGenericFieldInfo, + dataMap, + genericFieldInfo + } + } = softwareProductComponents; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - return { - componentData, - qdata, - isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL, - genericFieldInfo, - qGenericFieldInfo, - dataMap, - isFormValid - }; + return { + componentData, + qdata, + isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL, + genericFieldInfo, + qGenericFieldInfo, + dataMap, + isFormValid + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => { - return { - onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.ALL_SPC_FORMS}), - onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}), - onSubmit: ({componentData, qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch, - {softwareProductId, version, vspComponentId: componentId, componentData, qdata}); - }, - onValidityChanged: isValidityData => SoftwareProductActionHelper.setIsValidityData(dispatch, {isValidityData}) - }; - +const mapActionsToProps = ( + dispatch, + { softwareProductId, version, componentId } +) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: forms.ALL_SPC_FORMS + }), + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: COMPONENTS_QUESTIONNAIRE + }), + onSubmit: ({ componentData, qdata }) => { + return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent( + dispatch, + { + softwareProductId, + version, + vspComponentId: componentId, + componentData, + qdata + } + ); + }, + onValidityChanged: isValidityData => + SoftwareProductActionHelper.setIsValidityData(dispatch, { + isValidityData + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsGeneralView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductComponentsGeneralView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx index 6aa51d1609..ad1fcaacff 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx @@ -21,9 +21,18 @@ 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'; -const GeneralSection = ({onDataChanged, displayName, vfcCode, nfcFunction, description, isReadOnlyMode, genericFieldInfo, isManual}) => ( - <GridSection title={i18n('General')}> - {/* disabled until backend will be ready to implement it +const GeneralSection = ({ + onDataChanged, + displayName, + vfcCode, + nfcFunction, + description, + isReadOnlyMode, + genericFieldInfo, + isManual +}) => ( + <GridSection title={i18n('General')}> + {/* disabled until backend will be ready to implement it <div className='validation-input-wrapper'> <div className='form-group'> <label className='control-label'>{i18n('Name')}</label> @@ -32,156 +41,248 @@ const GeneralSection = ({onDataChanged, displayName, vfcCode, nfcFunction, descr </div> */} - <GridItem> - <Input - data-test-id='name' - label={i18n('Name')} - value={displayName} - disabled={!isManual || isReadOnlyMode} - type='text'/> - {!isManual && <Input - data-test-id='vfcCode' - label={i18n('Naming Code')} - value={vfcCode} - isValid={genericFieldInfo.vfcCode.isValid} - errorText={genericFieldInfo.vfcCode.errorText} - onChange={vfcCode => onDataChanged({vfcCode})} - disabled={isReadOnlyMode} - type='text'/> } - <Input - data-test-id='nfcFunction' - label={i18n('Function')} - value={nfcFunction} - isValid={genericFieldInfo.nfcFunction.isValid} - errorText={genericFieldInfo.nfcFunction.errorText} - onChange={nfcFunction => onDataChanged({nfcFunction})} - disabled={isReadOnlyMode} - type='text'/> - </GridItem> - <GridItem colSpan={2}> - <Input - label={i18n('Description')} - isValid={genericFieldInfo.description.isValid} - errorText={genericFieldInfo.description.errorText} - onChange={description => onDataChanged({description})} - disabled={isReadOnlyMode} - value={description} - groupClassName='multi-line-textarea' - data-test-id='description' - type='textarea'/> - </GridItem> - <GridItem /> - </GridSection> + <GridItem> + <Input + data-test-id="name" + label={i18n('Name')} + value={displayName} + disabled={!isManual || isReadOnlyMode} + type="text" + /> + {!isManual && ( + <Input + data-test-id="vfcCode" + label={i18n('Naming Code')} + value={vfcCode} + isValid={genericFieldInfo.vfcCode.isValid} + errorText={genericFieldInfo.vfcCode.errorText} + onChange={vfcCode => onDataChanged({ vfcCode })} + disabled={isReadOnlyMode} + type="text" + /> + )} + <Input + data-test-id="nfcFunction" + label={i18n('Function')} + value={nfcFunction} + isValid={genericFieldInfo.nfcFunction.isValid} + errorText={genericFieldInfo.nfcFunction.errorText} + onChange={nfcFunction => onDataChanged({ nfcFunction })} + disabled={isReadOnlyMode} + type="text" + /> + </GridItem> + <GridItem colSpan={2}> + <Input + label={i18n('Description')} + isValid={genericFieldInfo.description.isValid} + errorText={genericFieldInfo.description.errorText} + onChange={description => onDataChanged({ description })} + disabled={isReadOnlyMode} + value={description} + groupClassName="multi-line-textarea" + data-test-id="description" + type="textarea" + /> + </GridItem> + <GridItem /> + </GridSection> ); -const HypervisorSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('Hypervisor')}> - <GridItem> - <Input - data-test-id='hypervisor' - label={i18n('Supported Hypervisors')} - type='select' - className='input-options-select' - groupClassName='bootstrap-input-options' - isValid={qgenericFieldInfo['general/hypervisor/hypervisor'].isValid} - errorText={qgenericFieldInfo['general/hypervisor/hypervisor'].errorText} - value={dataMap['general/hypervisor/hypervisor']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'general/hypervisor/hypervisor' : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - {qgenericFieldInfo['general/hypervisor/hypervisor'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)} - </Input> - </GridItem> - <GridItem colSpan={2}> - <Input - data-test-id='drivers' - onChange={(driver) => onQDataChanged({'general/hypervisor/drivers' : driver})} - label={i18n('Hypervisor Drivers')} - type='text' - isValid={qgenericFieldInfo['general/hypervisor/drivers'].isValid} - errorText={qgenericFieldInfo['general/hypervisor/drivers'].errorText} - value={dataMap['general/hypervisor/drivers']}/> - </GridItem> - <GridItem colSpan={3}> - <Input - data-test-id='containerFeaturesDescription' - label={i18n('Describe Container Features')} - type='textarea' - onChange={(containerFeaturesDescription) => onQDataChanged({'general/hypervisor/containerFeaturesDescription' : containerFeaturesDescription})} - isValid={qgenericFieldInfo['general/hypervisor/containerFeaturesDescription'].isValid} - errorText={qgenericFieldInfo['general/hypervisor/containerFeaturesDescription'].errorText} - value={dataMap['general/hypervisor/containerFeaturesDescription']}/> - </GridItem> - </GridSection> +const HypervisorSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => ( + <GridSection title={i18n('Hypervisor')}> + <GridItem> + <Input + data-test-id="hypervisor" + label={i18n('Supported Hypervisors')} + type="select" + className="input-options-select" + groupClassName="bootstrap-input-options" + isValid={ + qgenericFieldInfo['general/hypervisor/hypervisor'].isValid + } + errorText={ + qgenericFieldInfo['general/hypervisor/hypervisor'].errorText + } + value={dataMap['general/hypervisor/hypervisor']} + onChange={e => { + const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onQDataChanged({ 'general/hypervisor/hypervisor': val }); + }}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {qgenericFieldInfo['general/hypervisor/hypervisor'].enum.map( + hv => ( + <option value={hv.enum} key={hv.enum}> + {hv.title} + </option> + ) + )} + </Input> + </GridItem> + <GridItem colSpan={2}> + <Input + data-test-id="drivers" + onChange={driver => + onQDataChanged({ 'general/hypervisor/drivers': driver }) + } + label={i18n('Hypervisor Drivers')} + type="text" + isValid={ + qgenericFieldInfo['general/hypervisor/drivers'].isValid + } + errorText={ + qgenericFieldInfo['general/hypervisor/drivers'].errorText + } + value={dataMap['general/hypervisor/drivers']} + /> + </GridItem> + <GridItem colSpan={3}> + <Input + data-test-id="containerFeaturesDescription" + label={i18n('Describe Container Features')} + type="textarea" + onChange={containerFeaturesDescription => + onQDataChanged({ + 'general/hypervisor/containerFeaturesDescription': containerFeaturesDescription + }) + } + isValid={ + qgenericFieldInfo[ + 'general/hypervisor/containerFeaturesDescription' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'general/hypervisor/containerFeaturesDescription' + ].errorText + } + value={ + dataMap['general/hypervisor/containerFeaturesDescription'] + } + /> + </GridItem> + </GridSection> ); -const ImageSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('Disk')}> - <GridItem> - <Input - data-test-id='bootDiskSizePerVM' - onChange={(bootDiskSizePerVM) => onQDataChanged({'general/disk/bootDiskSizePerVM' : bootDiskSizePerVM})} - label={i18n('Size of boot disk per VM (GB)')} - type='number' - isValid={qgenericFieldInfo['general/disk/bootDiskSizePerVM'].isValid} - errorText={qgenericFieldInfo['general/disk/bootDiskSizePerVM'].errorText} - value={dataMap['general/disk/bootDiskSizePerVM']}/> - </GridItem> - <GridItem> - <Input - data-test-id='ephemeralDiskSizePerVM' - onChange={(ephemeralDiskSizePerVM) => onQDataChanged({'general/disk/ephemeralDiskSizePerVM' : ephemeralDiskSizePerVM})} - label={i18n('Size of ephemeral disk per VM (GB)')} - type='number' - isValid={qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'].isValid} - errorText={qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'].errorText} - value={dataMap['general/disk/ephemeralDiskSizePerVM']}/> - </GridItem> - </GridSection> +const ImageSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => ( + <GridSection title={i18n('Disk')}> + <GridItem> + <Input + data-test-id="bootDiskSizePerVM" + onChange={bootDiskSizePerVM => + onQDataChanged({ + 'general/disk/bootDiskSizePerVM': bootDiskSizePerVM + }) + } + label={i18n('Size of boot disk per VM (GB)')} + type="number" + isValid={ + qgenericFieldInfo['general/disk/bootDiskSizePerVM'].isValid + } + errorText={ + qgenericFieldInfo['general/disk/bootDiskSizePerVM'] + .errorText + } + value={dataMap['general/disk/bootDiskSizePerVM']} + /> + </GridItem> + <GridItem> + <Input + data-test-id="ephemeralDiskSizePerVM" + onChange={ephemeralDiskSizePerVM => + onQDataChanged({ + 'general/disk/ephemeralDiskSizePerVM': ephemeralDiskSizePerVM + }) + } + label={i18n('Size of ephemeral disk per VM (GB)')} + type="number" + isValid={ + qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'] + .isValid + } + errorText={ + qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'] + .errorText + } + value={dataMap['general/disk/ephemeralDiskSizePerVM']} + /> + </GridItem> + </GridSection> ); -const RecoverySection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('Recovery')}> - <GridItem> - <Input - data-test-id='pointObjective' - label={i18n('VM Recovery Point Objective (Minutes)')} - type='number' - onChange={(pointObjective) => onQDataChanged({'general/recovery/pointObjective' : pointObjective})} - isValid={qgenericFieldInfo['general/recovery/pointObjective'].isValid} - errorText={qgenericFieldInfo['general/recovery/pointObjective'].errorText} - value={dataMap['general/recovery/pointObjective']}/> - </GridItem> - <GridItem> - <Input - data-test-id='timeObjective' - label={i18n('VM Recovery Time Objective (Minutes)')} - type='number' - onChange={(timeObjective) => onQDataChanged({'general/recovery/timeObjective' : timeObjective})} - isValid={qgenericFieldInfo['general/recovery/timeObjective'].isValid} - errorText={qgenericFieldInfo['general/recovery/timeObjective'].errorText} - value={dataMap['general/recovery/timeObjective']}/> - <div className='empty-two-col' /> - </GridItem> - <GridItem colSpan={2} /> - <GridItem colSpan={2}> - <Input - data-test-id='vmProcessFailuresHandling' - className='textarea' - label={i18n('How are in VM process failures handled?')} - type='textarea' - onChange={(vmProcessFailuresHandling) => onQDataChanged({'general/recovery/vmProcessFailuresHandling' : vmProcessFailuresHandling})} - isValid={qgenericFieldInfo['general/recovery/vmProcessFailuresHandling'].isValid} - errorText={qgenericFieldInfo['general/recovery/vmProcessFailuresHandling'].errorText} - value={dataMap['general/recovery/vmProcessFailuresHandling']}/> - <div className='empty-two-col' /> - - </GridItem> - { - /** disabled until backend will be ready to implement it +const RecoverySection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => ( + <GridSection title={i18n('Recovery')}> + <GridItem> + <Input + data-test-id="pointObjective" + label={i18n('VM Recovery Point Objective (Minutes)')} + type="number" + onChange={pointObjective => + onQDataChanged({ + 'general/recovery/pointObjective': pointObjective + }) + } + isValid={ + qgenericFieldInfo['general/recovery/pointObjective'].isValid + } + errorText={ + qgenericFieldInfo['general/recovery/pointObjective'] + .errorText + } + value={dataMap['general/recovery/pointObjective']} + /> + </GridItem> + <GridItem> + <Input + data-test-id="timeObjective" + label={i18n('VM Recovery Time Objective (Minutes)')} + type="number" + onChange={timeObjective => + onQDataChanged({ + 'general/recovery/timeObjective': timeObjective + }) + } + isValid={ + qgenericFieldInfo['general/recovery/timeObjective'].isValid + } + errorText={ + qgenericFieldInfo['general/recovery/timeObjective'] + .errorText + } + value={dataMap['general/recovery/timeObjective']} + /> + <div className="empty-two-col" /> + </GridItem> + <GridItem colSpan={2} /> + <GridItem colSpan={2}> + <Input + data-test-id="vmProcessFailuresHandling" + className="textarea" + label={i18n('How are in VM process failures handled?')} + type="textarea" + onChange={vmProcessFailuresHandling => + onQDataChanged({ + 'general/recovery/vmProcessFailuresHandling': vmProcessFailuresHandling + }) + } + isValid={ + qgenericFieldInfo[ + 'general/recovery/vmProcessFailuresHandling' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'general/recovery/vmProcessFailuresHandling' + ].errorText + } + value={dataMap['general/recovery/vmProcessFailuresHandling']} + /> + <div className="empty-two-col" /> + </GridItem> + {/** disabled until backend will be ready to implement it <div className='row'> <div className='col-md-3'> <Input @@ -190,78 +291,127 @@ const RecoverySection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( pointer='/general/recovery/VMRecoveryDocument'/> </div> </div> - */ - } - </GridSection> + */} + </GridSection> ); -const DNSConfigurationSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('DNS Configuration')}> - <GridItem colSpan={2}> - <Input - data-test-id='dnsConfiguration' - label={i18n('Do you have a need for DNS as a Service? Please describe.')} - type='textarea' - onChange={(dnsConfiguration) => onQDataChanged({'general/dnsConfiguration' : dnsConfiguration})} - isValid={qgenericFieldInfo['general/dnsConfiguration'].isValid} - errorText={qgenericFieldInfo['general/dnsConfiguration'].errorText} - value={dataMap['general/dnsConfiguration']}/> - </GridItem> - </GridSection> +const DNSConfigurationSection = ({ + dataMap, + onQDataChanged, + qgenericFieldInfo +}) => ( + <GridSection title={i18n('DNS Configuration')}> + <GridItem colSpan={2}> + <Input + data-test-id="dnsConfiguration" + label={i18n( + 'Do you have a need for DNS as a Service? Please describe.' + )} + type="textarea" + onChange={dnsConfiguration => + onQDataChanged({ + 'general/dnsConfiguration': dnsConfiguration + }) + } + isValid={qgenericFieldInfo['general/dnsConfiguration'].isValid} + errorText={ + qgenericFieldInfo['general/dnsConfiguration'].errorText + } + value={dataMap['general/dnsConfiguration']} + /> + </GridItem> + </GridSection> ); -const CloneSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('Clone')}> - <GridItem colSpan={2}> - <Input - data-test-id='vmCloneUsage' - label={i18n('Describe VM Clone Use')} - type='textarea' - onChange={(vmCloneUsage) => onQDataChanged({'general/vmCloneUsage' : vmCloneUsage})} - isValid={qgenericFieldInfo['general/vmCloneUsage'].isValid} - errorText={qgenericFieldInfo['general/vmCloneUsage'].errorText} - value={dataMap['general/vmCloneUsage']}/> - </GridItem> - </GridSection> +const CloneSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => ( + <GridSection title={i18n('Clone')}> + <GridItem colSpan={2}> + <Input + data-test-id="vmCloneUsage" + label={i18n('Describe VM Clone Use')} + type="textarea" + onChange={vmCloneUsage => + onQDataChanged({ 'general/vmCloneUsage': vmCloneUsage }) + } + isValid={qgenericFieldInfo['general/vmCloneUsage'].isValid} + errorText={qgenericFieldInfo['general/vmCloneUsage'].errorText} + value={dataMap['general/vmCloneUsage']} + /> + </GridItem> + </GridSection> ); class SoftwareProductComponentsGeneralView extends React.Component { + render() { + let { + isManual, + onQDataChanged, + onDataChanged, + genericFieldInfo, + dataMap, + qGenericFieldInfo, + componentData: { displayName, vfcCode, nfcFunction, description }, + isReadOnlyMode + } = this.props; + return ( + <div className="vsp-components-general"> + <div className="general-data"> + {genericFieldInfo && + qGenericFieldInfo && ( + <Form + isValid={this.props.isFormValid} + formReady={null} + isReadOnlyMode={isReadOnlyMode} + onValidityChanged={isValidityData => + this.props.onValidityChanged(isValidityData) + } + hasButtons={false}> + <GeneralSection + onDataChanged={onDataChanged} + displayName={displayName} + vfcCode={vfcCode} + nfcFunction={nfcFunction} + description={description} + isManual={isManual} + isReadOnlyMode={isReadOnlyMode} + genericFieldInfo={genericFieldInfo} + /> + <HypervisorSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + <ImageSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + <RecoverySection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + <DNSConfigurationSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + <CloneSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + </Form> + )} + </div> + </div> + ); + } - render() { - let {isManual, onQDataChanged, onDataChanged, genericFieldInfo, dataMap, qGenericFieldInfo, componentData: {displayName, vfcCode, nfcFunction, description}, isReadOnlyMode} = this.props; - return( - <div className='vsp-components-general'> - <div className='general-data'> - {genericFieldInfo && qGenericFieldInfo && <Form - isValid={this.props.isFormValid} - formReady={null} - isReadOnlyMode={isReadOnlyMode} - onValidityChanged={(isValidityData) => this.props.onValidityChanged(isValidityData)} - hasButtons={false}> - <GeneralSection - onDataChanged={onDataChanged} - displayName={displayName} - vfcCode={vfcCode} - nfcFunction={nfcFunction} - description={description} - isManual={isManual} - isReadOnlyMode={isReadOnlyMode} - genericFieldInfo={genericFieldInfo}/> - <HypervisorSection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - <ImageSection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - <RecoverySection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - <DNSConfigurationSection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - <CloneSection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - </Form> } - </div> - </div> - ); - } - - save() { - let {onSubmit, componentData, qdata} = this.props; - return onSubmit({componentData, qdata}); - } + save() { + let { onSubmit, componentData, qdata } = this.props; + return onSubmit({ componentData, qdata }); + } } export default SoftwareProductComponentsGeneralView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/ImageValidations.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/ImageValidations.js index 2483d0aaa2..900a9a1c46 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/ImageValidations.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/ImageValidations.js @@ -1,6 +1,6 @@ - import Validator from 'nfvo-utils/Validator.js'; -export const imageCustomValidations = { - 'version': value => Validator.validate('version', value, [{type: 'required', data: true}]) +export const imageCustomValidations = { + version: value => + Validator.validate('version', value, [{ type: 'required', data: true }]) }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js index 8d70d6f14c..3f661b76fe 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js @@ -17,157 +17,268 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; import Configuration from 'sdc-app/config/Configuration.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {IMAGE_QUESTIONNAIRE} from './SoftwareProductComponentsImageConstants.js'; -import {actionTypes} from './SoftwareProductComponentsImageConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; +import { IMAGE_QUESTIONNAIRE } from './SoftwareProductComponentsImageConstants.js'; +import { actionTypes } from './SoftwareProductComponentsImageConstants.js'; function baseUrl(softwareProductId, version, componentId) { - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/images`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/images`; } -function fetchImagesList({softwareProductId, componentId, version}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`); +function fetchImagesList({ softwareProductId, componentId, version }) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version, componentId)}` + ); } -function fetchImage({softwareProductId, componentId, imageId, version}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${imageId}`); +function fetchImage({ softwareProductId, componentId, imageId, version }) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version, componentId)}/${imageId}` + ); } -function destroyImage({softwareProductId, componentId, version, imageId}) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${imageId}`); +function destroyImage({ softwareProductId, componentId, version, imageId }) { + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version, componentId)}/${imageId}` + ); } -function createImage({softwareProductId, componentId, version, data}) { - return RestAPIUtil.post(baseUrl(softwareProductId, version, componentId), { - fileName: data.fileName - }); +function createImage({ softwareProductId, componentId, version, data }) { + return RestAPIUtil.post(baseUrl(softwareProductId, version, componentId), { + fileName: data.fileName + }); } -function fetchImageQuestionnaire({softwareProductId, componentId, imageId, version}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${imageId}/questionnaire`); +function fetchImageQuestionnaire({ + softwareProductId, + componentId, + imageId, + version +}) { + return RestAPIUtil.fetch( + `${baseUrl( + softwareProductId, + version, + componentId + )}/${imageId}/questionnaire` + ); } -function saveImage({softwareProductId, version, componentId, image: {id, fileName}}) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${id}`,{ - fileName - }); - +function saveImage({ + softwareProductId, + version, + componentId, + image: { id, fileName } +}) { + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version, componentId)}/${id}`, + { + fileName + } + ); } -function saveImageQuestionnaire({softwareProductId, componentId, version, imageId, qdata}) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${imageId}/questionnaire`, qdata); +function saveImageQuestionnaire({ + softwareProductId, + componentId, + version, + imageId, + qdata +}) { + return RestAPIUtil.put( + `${baseUrl( + softwareProductId, + version, + componentId + )}/${imageId}/questionnaire`, + qdata + ); } const SoftwareProductComponentImagesActionHelper = { - fetchImagesList(dispatch, {softwareProductId, componentId, version}) { - dispatch({ - type: actionTypes.IMAGES_LIST_UPDATE, - response: [] - }); - - return fetchImagesList({softwareProductId, componentId, version}).then((response) => { - dispatch({ - type: actionTypes.IMAGES_LIST_UPDATE, - response: response.results, - componentId : componentId - }); - }); - }, - - deleteImage(dispatch, {softwareProductId, componentId, version, imageId}) { - return destroyImage({softwareProductId, componentId, version, imageId}).then(() => { - return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version}); - }); - }, - - loadImageData({softwareProductId, componentId, imageId, version}) { - return fetchImage({softwareProductId, componentId, imageId, version}); - }, - - openEditImageEditor(dispatch, {image, softwareProductId, componentId, version, isReadOnlyMode}) { - return SoftwareProductComponentImagesActionHelper.loadImageData({softwareProductId, componentId, imageId: image.id, version}).then(({data}) => { - SoftwareProductComponentImagesActionHelper.loadImageQuestionnaire(dispatch, { - softwareProductId, - componentId, - imageId: image.id, - version - }).then(() => { - SoftwareProductComponentImagesActionHelper.openImageEditor(dispatch, { - softwareProductId, - componentId, - version, - isReadOnlyMode, - image, - data - }); - }); - }); - }, - - openImageEditor(dispatch, {image = {}, data = {}, softwareProductId, componentId, version, isReadOnlyMode}) { - - let {id} = image; - let title = id ? i18n('Edit Image') : i18n('Create New Image'); - let className = id ? 'image-modal-edit' : 'image-modal-new'; - - dispatch({ - type: actionTypes.ImageEditor.OPEN, - image: {...data, id} - }); - - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR, - title: title, - modalClassName: className, - modalComponentProps: {softwareProductId, componentId, version, isReadOnlyMode} - } - }); - - }, - - closeImageEditor(dispatch) { - - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_CLOSE - }); - - dispatch({ - type: actionTypes.ImageEditor.CLOSE - }); - - }, - - loadImageQuestionnaire(dispatch, {softwareProductId, componentId, imageId, version}) { - return fetchImageQuestionnaire({softwareProductId, componentId, imageId, version}).then((response) => { - ValidationHelper.qDataLoaded(dispatch, {qName: IMAGE_QUESTIONNAIRE ,response: { - qdata: response.data ? JSON.parse(response.data) : {}, - qschema: JSON.parse(response.schema) - }}); - }); - }, - - saveImageDataAndQuestionnaire(dispatch, {softwareProductId, componentId, version, data, qdata}) { - SoftwareProductComponentImagesActionHelper.closeImageEditor(dispatch); - if (data !== null && data.id) { - // editor in edit mode - return Promise.all([ - saveImageQuestionnaire({softwareProductId, version, componentId, imageId: data.id, qdata}), - saveImage({softwareProductId, version, componentId, image: data}).then(() => { - return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version}); - }) - ]); - } else { - // editor in create mode - createImage({softwareProductId, componentId, version, data}).then(() => { - return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version}); - }); - } - } + fetchImagesList(dispatch, { softwareProductId, componentId, version }) { + dispatch({ + type: actionTypes.IMAGES_LIST_UPDATE, + response: [] + }); + + return fetchImagesList({ + softwareProductId, + componentId, + version + }).then(response => { + dispatch({ + type: actionTypes.IMAGES_LIST_UPDATE, + response: response.results, + componentId: componentId + }); + }); + }, + + deleteImage( + dispatch, + { softwareProductId, componentId, version, imageId } + ) { + return destroyImage({ + softwareProductId, + componentId, + version, + imageId + }).then(() => { + return SoftwareProductComponentImagesActionHelper.fetchImagesList( + dispatch, + { softwareProductId, componentId, version } + ); + }); + }, + + loadImageData({ softwareProductId, componentId, imageId, version }) { + return fetchImage({ softwareProductId, componentId, imageId, version }); + }, + + openEditImageEditor( + dispatch, + { image, softwareProductId, componentId, version, isReadOnlyMode } + ) { + return SoftwareProductComponentImagesActionHelper.loadImageData({ + softwareProductId, + componentId, + imageId: image.id, + version + }).then(({ data }) => { + SoftwareProductComponentImagesActionHelper.loadImageQuestionnaire( + dispatch, + { + softwareProductId, + componentId, + imageId: image.id, + version + } + ).then(() => { + SoftwareProductComponentImagesActionHelper.openImageEditor( + dispatch, + { + softwareProductId, + componentId, + version, + isReadOnlyMode, + image, + data + } + ); + }); + }); + }, + + openImageEditor( + dispatch, + { + image = {}, + data = {}, + softwareProductId, + componentId, + version, + isReadOnlyMode + } + ) { + let { id } = image; + let title = id ? i18n('Edit Image') : i18n('Create New Image'); + let className = id ? 'image-modal-edit' : 'image-modal-new'; + + dispatch({ + type: actionTypes.ImageEditor.OPEN, + image: { ...data, id } + }); + + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: + modalContentMapper.SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR, + title: title, + modalClassName: className, + modalComponentProps: { + softwareProductId, + componentId, + version, + isReadOnlyMode + } + } + }); + }, + + closeImageEditor(dispatch) { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }); + + dispatch({ + type: actionTypes.ImageEditor.CLOSE + }); + }, + + loadImageQuestionnaire( + dispatch, + { softwareProductId, componentId, imageId, version } + ) { + return fetchImageQuestionnaire({ + softwareProductId, + componentId, + imageId, + version + }).then(response => { + ValidationHelper.qDataLoaded(dispatch, { + qName: IMAGE_QUESTIONNAIRE, + response: { + qdata: response.data ? JSON.parse(response.data) : {}, + qschema: JSON.parse(response.schema) + } + }); + }); + }, + + saveImageDataAndQuestionnaire( + dispatch, + { softwareProductId, componentId, version, data, qdata } + ) { + SoftwareProductComponentImagesActionHelper.closeImageEditor(dispatch); + if (data !== null && data.id) { + // editor in edit mode + return Promise.all([ + saveImageQuestionnaire({ + softwareProductId, + version, + componentId, + imageId: data.id, + qdata + }), + saveImage({ + softwareProductId, + version, + componentId, + image: data + }).then(() => { + return SoftwareProductComponentImagesActionHelper.fetchImagesList( + dispatch, + { softwareProductId, componentId, version } + ); + }) + ]); + } else { + // editor in create mode + createImage({ softwareProductId, componentId, version, data }).then( + () => { + return SoftwareProductComponentImagesActionHelper.fetchImagesList( + dispatch, + { softwareProductId, componentId, version } + ); + } + ); + } + } }; export default SoftwareProductComponentImagesActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js index 6b6c9a30e5..300b2898e1 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js @@ -16,12 +16,12 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - IMAGES_LIST_UPDATE: null, + IMAGES_LIST_UPDATE: null, - ImageEditor: { - CLOSE: null, - OPEN: null - } + ImageEditor: { + CLOSE: null, + OPEN: null + } }); export const IMAGE_QUESTIONNAIRE = 'image'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js index c5f23e7681..0243a38f1b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js @@ -13,56 +13,93 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; import SoftwareProductComponentsImageActionHelper from './SoftwareProductComponentsImageActionHelper.js'; import SoftwareProductComponentsImageEditorView from './SoftwareProductComponentsImageEditorView.jsx'; -import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js'; -import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; -import {IMAGE_QUESTIONNAIRE} from './SoftwareProductComponentsImageConstants.js'; +import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js'; +import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { IMAGE_QUESTIONNAIRE } from './SoftwareProductComponentsImageConstants.js'; export const mapStateToProps = ({ - softwareProduct, - currentScreen: {props: {isReadOnlyMode}} + softwareProduct, + currentScreen: { props: { isReadOnlyMode } } }) => { + let { + softwareProductEditor: { + data: currentSoftwareProduct = {}, + isValidityData = true + }, + softwareProductComponents + } = softwareProduct; - let {softwareProductEditor: {data:currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct; - - let {images: {imageEditor = {}}} = softwareProductComponents; - let {data, qdata, genericFieldInfo, qgenericFieldInfo, dataMap, formReady} = imageEditor; - let {version, onboardingMethod} = currentSoftwareProduct; - let isManual = onboardingMethod === onboardingMethodTypes.MANUAL; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo) && ValidationHelper.checkFormValid(qgenericFieldInfo); - - return { - version, - currentSoftwareProduct, - isValidityData, - data, - qdata, - dataMap, - isFormValid, - formReady, - genericFieldInfo, - qgenericFieldInfo, - isReadOnlyMode, - isManual: isManual - }; + let { images: { imageEditor = {} } } = softwareProductComponents; + let { + data, + qdata, + genericFieldInfo, + qgenericFieldInfo, + dataMap, + formReady + } = imageEditor; + let { version, onboardingMethod } = currentSoftwareProduct; + let isManual = onboardingMethod === onboardingMethodTypes.MANUAL; + let isFormValid = + ValidationHelper.checkFormValid(genericFieldInfo) && + ValidationHelper.checkFormValid(qgenericFieldInfo); + return { + version, + currentSoftwareProduct, + isValidityData, + data, + qdata, + dataMap, + isFormValid, + formReady, + genericFieldInfo, + qgenericFieldInfo, + isReadOnlyMode, + isManual: isManual + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => { - return { - onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.IMAGE_EDIT_FORM}), - onSubmit: ({data, qdata}) => SoftwareProductComponentsImageActionHelper.saveImageDataAndQuestionnaire(dispatch, {softwareProductId, componentId, version, data, qdata}), - onCancel: () => SoftwareProductComponentsImageActionHelper.closeImageEditor(dispatch), - onValidateForm: customValidations => { - ValidationHelper.validateForm(dispatch, forms.IMAGE_EDIT_FORM); - ValidationHelper.qValidateForm(dispatch, IMAGE_QUESTIONNAIRE, customValidations); - }, - onQDataChanged: (deltaData, customValidations) => ValidationHelper.qDataChanged(dispatch, {deltaData, - qName: IMAGE_QUESTIONNAIRE, customValidations}), - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, componentId, version } +) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: forms.IMAGE_EDIT_FORM + }), + onSubmit: ({ data, qdata }) => + SoftwareProductComponentsImageActionHelper.saveImageDataAndQuestionnaire( + dispatch, + { softwareProductId, componentId, version, data, qdata } + ), + onCancel: () => + SoftwareProductComponentsImageActionHelper.closeImageEditor( + dispatch + ), + onValidateForm: customValidations => { + ValidationHelper.validateForm(dispatch, forms.IMAGE_EDIT_FORM); + ValidationHelper.qValidateForm( + dispatch, + IMAGE_QUESTIONNAIRE, + customValidations + ); + }, + onQDataChanged: (deltaData, customValidations) => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: IMAGE_QUESTIONNAIRE, + customValidations + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentsImageEditorView); +export default connect(mapStateToProps, mapActionsToProps)( + SoftwareProductComponentsImageEditorView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js index 7c357429e5..3846d45772 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js @@ -13,30 +13,29 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductComponentsImageConstants.js'; -import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { actionTypes } from './SoftwareProductComponentsImageConstants.js'; +import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.ImageEditor.CLOSE: - return {}; - case actionTypes.ImageEditor.OPEN: - return { - ...state, - data: { - ...action.image - }, - genericFieldInfo: { - 'fileName' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}] - } - }, - formName: forms.IMAGE_EDIT_FORM - }; - default: - return state; - } + switch (action.type) { + case actionTypes.ImageEditor.CLOSE: + return {}; + case actionTypes.ImageEditor.OPEN: + return { + ...state, + data: { + ...action.image + }, + genericFieldInfo: { + fileName: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + } + }, + formName: forms.IMAGE_EDIT_FORM + }; + default: + return state; + } }; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx index a5ef152e01..3670ab910d 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx @@ -21,53 +21,81 @@ import Form from 'nfvo-components/input/validation/Form.jsx'; import FileDetails from './imagesEditorComponents/FileDetails.jsx'; import ImageDetails from './imagesEditorComponents/ImageDetails.jsx'; -import {imageCustomValidations} from './ImageValidations.js'; +import { imageCustomValidations } from './ImageValidations.js'; class SoftwareProductComponentsImageEditorView extends React.Component { - static propTypes = { - onDataChanged: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, - onCancel: PropTypes.func.isRequired - }; + static propTypes = { + onDataChanged: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired + }; - render() { - let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, genericFieldInfo, qgenericFieldInfo, dataMap, onDataChanged, isManual, onQDataChanged} = this.props; - let {id, fileName} = data; - let editingMode = Boolean(id); - return ( - <div> - {genericFieldInfo && <Form - ref={(form) => { this.form = form; }} - hasButtons={true} - onSubmit={ () => this.submit() } - onReset={ () => onCancel() } - labledButtons={true} - isReadOnlyMode={isReadOnlyMode} - isValid={isFormValid} - formReady={formReady} - submitButtonText={editingMode ? i18n('Save') : i18n('Create')} - onValidateForm={() => onValidateForm(imageCustomValidations) } - className='vsp-components-image-editor'> - <div className='editor-data'> - <FileDetails - editingMode={editingMode} - genericFieldInfo={genericFieldInfo} - qgenericFieldInfo={qgenericFieldInfo} - fileName={fileName} - onDataChanged={onDataChanged} - isManual={isManual} - dataMap={dataMap} - onQDataChanged={onQDataChanged}/> - {editingMode && <ImageDetails dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged}/>} - </div> - </Form>} - </div> - ); - } - submit() { - let {data, qdata, onSubmit, version} = this.props; - onSubmit({data, qdata, version}); - } + render() { + let { + onCancel, + onValidateForm, + isReadOnlyMode, + isFormValid, + formReady, + data = {}, + genericFieldInfo, + qgenericFieldInfo, + dataMap, + onDataChanged, + isManual, + onQDataChanged + } = this.props; + let { id, fileName } = data; + let editingMode = Boolean(id); + return ( + <div> + {genericFieldInfo && ( + <Form + ref={form => { + this.form = form; + }} + hasButtons={true} + onSubmit={() => this.submit()} + onReset={() => onCancel()} + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + isValid={isFormValid} + formReady={formReady} + submitButtonText={ + editingMode ? i18n('Save') : i18n('Create') + } + onValidateForm={() => + onValidateForm(imageCustomValidations) + } + className="vsp-components-image-editor"> + <div className="editor-data"> + <FileDetails + editingMode={editingMode} + genericFieldInfo={genericFieldInfo} + qgenericFieldInfo={qgenericFieldInfo} + fileName={fileName} + onDataChanged={onDataChanged} + isManual={isManual} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + {editingMode && ( + <ImageDetails + dataMap={dataMap} + qgenericFieldInfo={qgenericFieldInfo} + onQDataChanged={onQDataChanged} + /> + )} + </div> + </Form> + )} + </div> + ); + } + submit() { + let { data, qdata, onSubmit, version } = this.props; + onSubmit({ data, qdata, version }); + } } export default SoftwareProductComponentsImageEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js index d071647058..f3c39c3048 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js @@ -13,73 +13,122 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; import SoftwareProductComponentsImageListView from './SoftwareProductComponentsImageListView.jsx'; import ImageHelper from './SoftwareProductComponentsImageActionHelper.js'; import SoftwareProductComponentsImagesActionHelper from './SoftwareProductComponentsImageActionHelper.js'; import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js'; -import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js'; +import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js'; -export const mapStateToProps = ({softwareProduct}) => { +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductEditor: { + data: currentSoftwareProduct = {}, + isValidityData = true + }, + softwareProductComponents + } = softwareProduct; + let { + images: { imagesList = [] }, + componentEditor: { + data: componentData, + qdata, + dataMap, + qgenericFieldInfo + } + } = softwareProductComponents; + let { onboardingMethod } = currentSoftwareProduct; + let isManual = onboardingMethod === onboardingMethodTypes.MANUAL; - let {softwareProductEditor: {data: currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct; - let {images: {imagesList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents; - let {onboardingMethod} = currentSoftwareProduct; - let isManual = onboardingMethod === onboardingMethodTypes.MANUAL; - - return { - componentData, - qdata, - dataMap, - qgenericFieldInfo, - isValidityData, - imagesList, - isManual : isManual - }; + return { + componentData, + qdata, + dataMap, + qgenericFieldInfo, + isValidityData, + imagesList, + isManual: isManual + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => { - return { - onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, - qName: COMPONENTS_QUESTIONNAIRE}), - onAddImage: (isReadOnlyMode) => { - SoftwareProductComponentsImagesActionHelper.openImageEditor(dispatch, - {isReadOnlyMode, softwareProductId, - componentId, version} - );}, - onDeleteImage: (image) => { - let shortenedFileName = (image.fileName.length > 40) ? image.fileName.substr(0,40) + '...' : image.fileName; - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data: { - msg: i18n('Are you sure you want to delete "{shortenedFileName}"?', {shortenedFileName: shortenedFileName}), - onConfirmed: () => ImageHelper.deleteImage(dispatch, { - softwareProductId, - componentId, - version, - imageId: image.id - }) - } - }); - }, - onEditImageClick: (image, isReadOnlyMode) => { - SoftwareProductComponentsImagesActionHelper.openEditImageEditor(dispatch, { - image, isReadOnlyMode, softwareProductId, componentId, version, modalClassName: 'image-modal-edit'} - ); - }, - onSubmit: (qdata) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, - {softwareProductId, - vspComponentId: componentId, - version, - qdata}); - } - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, componentId, version } +) => { + return { + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: COMPONENTS_QUESTIONNAIRE + }), + onAddImage: isReadOnlyMode => { + SoftwareProductComponentsImagesActionHelper.openImageEditor( + dispatch, + { + isReadOnlyMode, + softwareProductId, + componentId, + version + } + ); + }, + onDeleteImage: image => { + let shortenedFileName = + image.fileName.length > 40 + ? image.fileName.substr(0, 40) + '...' + : image.fileName; + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + msg: i18n( + 'Are you sure you want to delete "{shortenedFileName}"?', + { + shortenedFileName: shortenedFileName + } + ), + onConfirmed: () => + ImageHelper.deleteImage(dispatch, { + softwareProductId, + componentId, + version, + imageId: image.id + }) + } + }); + }, + onEditImageClick: (image, isReadOnlyMode) => { + SoftwareProductComponentsImagesActionHelper.openEditImageEditor( + dispatch, + { + image, + isReadOnlyMode, + softwareProductId, + componentId, + version, + modalClassName: 'image-modal-edit' + } + ); + }, + onSubmit: qdata => { + return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire( + dispatch, + { + softwareProductId, + vspComponentId: componentId, + version, + qdata + } + ); + } + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsImageListView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductComponentsImageListView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js index 5dd2fb623b..a7c1bfafbe 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js @@ -13,14 +13,13 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductComponentsImageConstants.js'; +import { actionTypes } from './SoftwareProductComponentsImageConstants.js'; export default (state = [], action) => { - switch (action.type) { - - case actionTypes.IMAGES_LIST_UPDATE: - return [...action.response]; - default: - return state; - } + switch (action.type) { + case actionTypes.IMAGES_LIST_UPDATE: + return [...action.response]; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx index 004cbebe5d..cb67856caa 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx @@ -20,113 +20,152 @@ import Form from 'nfvo-components/input/validation/Form.jsx'; import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx'; import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx'; -import Input from'nfvo-components/input/validation/Input.jsx'; +import Input from 'nfvo-components/input/validation/Input.jsx'; class SoftwareProductComponentsImageListView extends React.Component { - state = { - localFilter: '' - }; + state = { + localFilter: '' + }; - render() { - let {dataMap, onQDataChanged, isReadOnlyMode, qgenericFieldInfo} = this.props; - return( - <div className='vsp-components-image'> - <div className='image-data'> - <div> - { qgenericFieldInfo && <Form - formReady={null} - isValid={true} - onSubmit={() => this.save()} - isReadOnlyMode={isReadOnlyMode} - hasButtons={false}> - - <h3 className='section-title'>{i18n('Image')}</h3> - <div className='rows-section'> - <div className='row-flex-components'> - <div className='single-col'> - <Input - data-test-id='providedBy' - label={i18n('Image provided by')} - type='select' - isValid={qgenericFieldInfo['general/image/providedBy'].isValid} - errorText={qgenericFieldInfo['general/image/providedBy'].errorText} - value={dataMap['general/image/providedBy']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'general/image/providedBy' : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - { qgenericFieldInfo['general/image/providedBy'].enum.map(proto => - <option value={proto.enum} key={proto.enum}>{proto.title}</option>) } - </Input> - </div> - <div className='empty-two-col' /> - </div> - </div> - - </Form> } - </div> - </div> - {this.renderImagesList()} + render() { + let { + dataMap, + onQDataChanged, + isReadOnlyMode, + qgenericFieldInfo + } = this.props; + return ( + <div className="vsp-components-image"> + <div className="image-data"> + <div> + {qgenericFieldInfo && ( + <Form + formReady={null} + isValid={true} + onSubmit={() => this.save()} + isReadOnlyMode={isReadOnlyMode} + hasButtons={false}> + <h3 className="section-title"> + {i18n('Image')} + </h3> + <div className="rows-section"> + <div className="row-flex-components"> + <div className="single-col"> + <Input + data-test-id="providedBy" + label={i18n( + 'Image provided by' + )} + type="select" + isValid={ + qgenericFieldInfo[ + 'general/image/providedBy' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'general/image/providedBy' + ].errorText + } + value={ + dataMap[ + 'general/image/providedBy' + ] + } + onChange={e => { + const selectedIndex = + e.target.selectedIndex; + const val = + e.target.options[ + selectedIndex + ].value; + onQDataChanged({ + 'general/image/providedBy': val + }); + }}> + <option + key="placeholder" + value=""> + {i18n('Select...')} + </option> + {qgenericFieldInfo[ + 'general/image/providedBy' + ].enum.map(proto => ( + <option + value={proto.enum} + key={proto.enum}> + {proto.title} + </option> + ))} + </Input> + </div> + <div className="empty-two-col" /> + </div> + </div> + </Form> + )} + </div> + </div> + {this.renderImagesList()} </div> - ); - }; - - renderImagesList() { - const {localFilter} = this.state; - let {isReadOnlyMode, onAddImage, isManual} = this.props; - - return ( - <ListEditorView - title={i18n('Images')} - filterValue={localFilter} - placeholder={i18n('Filter Images by Name')} - isReadOnlyMode={isReadOnlyMode} - onFilter={value => this.setState({localFilter: value})} - onAdd={isManual ? () => onAddImage(isReadOnlyMode) : null} - plusButtonTitle={i18n('Add Image')} - twoColumns> - {this.filterList().map(image => this.renderImagesListItem(image, isReadOnlyMode))} - </ListEditorView> - ); - }; + ); + } + renderImagesList() { + const { localFilter } = this.state; + let { isReadOnlyMode, onAddImage, isManual } = this.props; - renderImagesListItem(image, isReadOnlyMode) { - let {id, fileName} = image; - let {onEditImageClick, isManual, onDeleteImage} = this.props; - return ( - <ListEditorItemView - key={id} - isReadOnlyMode={isReadOnlyMode} - onSelect={() => onEditImageClick(image, isReadOnlyMode)} - onDelete={isManual ? () => onDeleteImage(image) : null}> + return ( + <ListEditorView + title={i18n('Images')} + filterValue={localFilter} + placeholder={i18n('Filter Images by Name')} + isReadOnlyMode={isReadOnlyMode} + onFilter={value => this.setState({ localFilter: value })} + onAdd={isManual ? () => onAddImage(isReadOnlyMode) : null} + plusButtonTitle={i18n('Add Image')} + twoColumns> + {this.filterList().map(image => + this.renderImagesListItem(image, isReadOnlyMode) + )} + </ListEditorView> + ); + } - <ListEditorItemViewField> - <div className='image-filename-cell'><span className='image-filename'>{fileName}</span></div> - </ListEditorItemViewField> - </ListEditorItemView> - ); - } + renderImagesListItem(image, isReadOnlyMode) { + let { id, fileName } = image; + let { onEditImageClick, isManual, onDeleteImage } = this.props; + return ( + <ListEditorItemView + key={id} + isReadOnlyMode={isReadOnlyMode} + onSelect={() => onEditImageClick(image, isReadOnlyMode)} + onDelete={isManual ? () => onDeleteImage(image) : null}> + <ListEditorItemViewField> + <div className="image-filename-cell"> + <span className="image-filename">{fileName}</span> + </div> + </ListEditorItemViewField> + </ListEditorItemView> + ); + } - filterList() { - let {imagesList} = this.props; - let {localFilter} = this.state; - if (localFilter.trim()) { - const filter = new RegExp(escape(localFilter), 'i'); - return imagesList.filter(({fileName = ''}) => { - return escape(fileName).match(filter); - }); - } - else { - return imagesList; - } - } + filterList() { + let { imagesList } = this.props; + let { localFilter } = this.state; + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return imagesList.filter(({ fileName = '' }) => { + return escape(fileName).match(filter); + }); + } else { + return imagesList; + } + } - save() { - let {onSubmit, qdata} = this.props; - return onSubmit(qdata); - } + save() { + let { onSubmit, qdata } = this.props; + return onSubmit(qdata); + } } export default SoftwareProductComponentsImageListView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx index 64367c00f2..ec173cd988 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx @@ -18,32 +18,64 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; import Format from './Format.jsx'; import Version from './Version.jsx'; -const FileDetails = ({editingMode, fileName, onDataChanged, isManual, dataMap, onQDataChanged, genericFieldInfo, qgenericFieldInfo}) => { - let fileNameCols = (editingMode) ? 3 : 4; - return( - <GridSection hasLastColSset> - <GridItem colSpan={fileNameCols} lastColInRow={!editingMode}> - <Input - disabled={!isManual} - onChange={fileName => onDataChanged({fileName}, forms.IMAGE_EDIT_FORM)} - label={i18n('Image Name')} - data-test-id='image-filename' - value={fileName} - isValid={genericFieldInfo.fileName.isValid} - errorText={genericFieldInfo.fileName.errorText} - isRequired={true} - type='text' - className='image-filename'/> - </GridItem> - {!editingMode && <div className='note-text'>{i18n('After image creation you must go to Edit Image and add File Version')}</div>} - {editingMode && <Version isManual={isManual} dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged}/>} - {editingMode && <Format isManual={isManual} qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged}/>} - </GridSection> - ); +const FileDetails = ({ + editingMode, + fileName, + onDataChanged, + isManual, + dataMap, + onQDataChanged, + genericFieldInfo, + qgenericFieldInfo +}) => { + let fileNameCols = editingMode ? 3 : 4; + return ( + <GridSection hasLastColSset> + <GridItem colSpan={fileNameCols} lastColInRow={!editingMode}> + <Input + disabled={!isManual} + onChange={fileName => + onDataChanged({ fileName }, forms.IMAGE_EDIT_FORM) + } + label={i18n('Image Name')} + data-test-id="image-filename" + value={fileName} + isValid={genericFieldInfo.fileName.isValid} + errorText={genericFieldInfo.fileName.errorText} + isRequired={true} + type="text" + className="image-filename" + /> + </GridItem> + {!editingMode && ( + <div className="note-text"> + {i18n( + 'After image creation you must go to Edit Image and add File Version' + )} + </div> + )} + {editingMode && ( + <Version + isManual={isManual} + dataMap={dataMap} + qgenericFieldInfo={qgenericFieldInfo} + onQDataChanged={onQDataChanged} + /> + )} + {editingMode && ( + <Format + isManual={isManual} + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + )} + </GridSection> + ); }; export default FileDetails; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx index 1f71c6b277..0ee8fb76d0 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx @@ -18,30 +18,34 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import Input from 'nfvo-components/input/validation/Input.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; - -const Format = ({isManual, dataMap, qgenericFieldInfo, onQDataChanged}) => { - return( - <GridItem colSpan={2}> - <Input - disabled={!isManual} - data-test-id='image-format' - type='select' - label={i18n('Format')} - className='input-options-select' - groupClassName='bootstrap-input-options' - isValid={qgenericFieldInfo['format'].isValid} - errorText={qgenericFieldInfo['format'].errorText} - value={dataMap['format']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'format' : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - {qgenericFieldInfo['format'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)} - </Input> - </GridItem> - ); +const Format = ({ isManual, dataMap, qgenericFieldInfo, onQDataChanged }) => { + return ( + <GridItem colSpan={2}> + <Input + disabled={!isManual} + data-test-id="image-format" + type="select" + label={i18n('Format')} + className="input-options-select" + groupClassName="bootstrap-input-options" + isValid={qgenericFieldInfo['format'].isValid} + errorText={qgenericFieldInfo['format'].errorText} + value={dataMap['format']} + onChange={e => { + const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onQDataChanged({ format: val }); + }}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {qgenericFieldInfo['format'].enum.map(hv => ( + <option value={hv.enum} key={hv.enum}> + {hv.title} + </option> + ))} + </Input> + </GridItem> + ); }; export default Format; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx index 24e54bbbcb..ccf94bc860 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx @@ -19,21 +19,22 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const ImageDetails = ({dataMap, qgenericFieldInfo, onQDataChanged}) => { - return( - <GridSection title={i18n('Image Details')}> - <GridItem colSpan={2}> - <Input - data-test-id='image-md5' - className='image-md5' - type='text' - label={i18n('md5')} - onChange={(md5) => onQDataChanged({'md5' : md5})} - isValid={qgenericFieldInfo['md5'].isValid} - errorText={qgenericFieldInfo['md5'].errorText} - value={dataMap['md5']}/> - </GridItem> - </GridSection> - ); +const ImageDetails = ({ dataMap, qgenericFieldInfo, onQDataChanged }) => { + return ( + <GridSection title={i18n('Image Details')}> + <GridItem colSpan={2}> + <Input + data-test-id="image-md5" + className="image-md5" + type="text" + label={i18n('md5')} + onChange={md5 => onQDataChanged({ md5: md5 })} + isValid={qgenericFieldInfo['md5'].isValid} + errorText={qgenericFieldInfo['md5'].errorText} + value={dataMap['md5']} + /> + </GridItem> + </GridSection> + ); }; export default ImageDetails; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx index bd55c5ba91..60454c52e7 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx @@ -17,25 +17,29 @@ import React from 'react'; import i18n from 'nfvo-utils/i18n/i18n.js'; import Input from 'nfvo-components/input/validation/Input.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -import {imageCustomValidations} from '../ImageValidations.js'; +import { imageCustomValidations } from '../ImageValidations.js'; - -const Version = ({isManual, dataMap, qgenericFieldInfo, onQDataChanged}) => { - return( - <GridItem colSpan={1} lastColInRow> - <Input - disabled={!isManual} - data-test-id='image-version' - type='text' - className='image-version' - label={i18n('Version')} - isRequired={true} - onChange={(version) => onQDataChanged({'version' : version}, {'version' : imageCustomValidations['version']})} - isValid={qgenericFieldInfo['version'].isValid} - errorText={qgenericFieldInfo['version'].errorText} - value={dataMap['version']}/> - </GridItem> - ); +const Version = ({ isManual, dataMap, qgenericFieldInfo, onQDataChanged }) => { + return ( + <GridItem colSpan={1} lastColInRow> + <Input + disabled={!isManual} + data-test-id="image-version" + type="text" + className="image-version" + label={i18n('Version')} + isRequired={true} + onChange={version => + onQDataChanged( + { version: version }, + { version: imageCustomValidations['version'] } + ) + } + isValid={qgenericFieldInfo['version'].isValid} + errorText={qgenericFieldInfo['version'].errorText} + value={dataMap['version']} + /> + </GridItem> + ); }; export default Version; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancing.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancing.js index 350e80c0f8..da8b73fbe0 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancing.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancing.js @@ -13,29 +13,50 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductComponentLoadBalancingView from './SoftwareProductComponentLoadBalancingRefView.jsx'; import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; -export const mapStateToProps = ({softwareProduct: {softwareProductComponents}}) => { - - let {componentEditor: {qdata, qgenericFieldInfo: genericFieldInfo, dataMap}} = softwareProductComponents; - - return { - qdata, - genericFieldInfo, - dataMap - }; +export const mapStateToProps = ({ + softwareProduct: { softwareProductComponents } +}) => { + let { + componentEditor: { qdata, qgenericFieldInfo: genericFieldInfo, dataMap } + } = softwareProductComponents; + return { + qdata, + genericFieldInfo, + dataMap + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => { - return { - onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}), - onSubmit: ({qdata}) =>{ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata});} - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, version, componentId } +) => { + return { + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: COMPONENTS_QUESTIONNAIRE + }), + onSubmit: ({ qdata }) => { + return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire( + dispatch, + { + softwareProductId, + version, + vspComponentId: componentId, + qdata + } + ); + } + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentLoadBalancingView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductComponentLoadBalancingView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx index 1cbb9afc5d..4c90fc0be2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx @@ -19,7 +19,7 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; import Form from 'nfvo-components/input/validation/Form.jsx'; -import Input from'nfvo-components/input/validation/Input.jsx'; +import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; @@ -27,145 +27,244 @@ import GridItem from 'nfvo-components/grid/GridItem.jsx'; const prefix = 'highAvailabilityAndLoadBalancing/'; const pointers = [ - { - key: 'failureLoadDistribution', - description: 'How is load distributed across live vms in the event of a vm/host failure? please describe' - }, - { - key: 'nkModelImplementation', - description: 'Does each VM implement the N+K model for redundancy and failure protection? Please describe.' - }, - { - key: 'architectureChoice', - description: 'What architecture is being implemented: ACTIVE-ACTIVE and/or ACTIVE-PASSIVE. ', - added: 'Will the arrangement be 1-1 or N-M? Please describe.' - }, - {key: 'slaRequirements', description: 'Specify application SLA requirements on Cloud platform.'}, - { - key: 'horizontalScaling', - description: 'Is horizontal scaling the preferred solution for HA and resiliency? Please describe.' - }, - { - key: 'loadDistributionMechanism', - description: 'Can load be distributed across VMs? If so, are special mechanisms needed to re-balance data across VMs?', - added: 'Please describe.' - } + { + key: 'failureLoadDistribution', + description: + 'How is load distributed across live vms in the event of a vm/host failure? please describe' + }, + { + key: 'nkModelImplementation', + description: + 'Does each VM implement the N+K model for redundancy and failure protection? Please describe.' + }, + { + key: 'architectureChoice', + description: + 'What architecture is being implemented: ACTIVE-ACTIVE and/or ACTIVE-PASSIVE. ', + added: 'Will the arrangement be 1-1 or N-M? Please describe.' + }, + { + key: 'slaRequirements', + description: 'Specify application SLA requirements on Cloud platform.' + }, + { + key: 'horizontalScaling', + description: + 'Is horizontal scaling the preferred solution for HA and resiliency? Please describe.' + }, + { + key: 'loadDistributionMechanism', + description: + 'Can load be distributed across VMs? If so, are special mechanisms needed to re-balance data across VMs?', + added: 'Please describe.' + } ]; //TODO check for buttons -const TextAreaItem = ({item, toggle, expanded, genericFieldInfo, dataMap, onQDataChanged}) => ( - <GridItem colSpan={3} key={item.key} > - <div className={expanded ? 'title' : 'title add-padding'} - data-test-id={`btn-${item.key}`} - onClick={() => toggle(item.key)}> - <SVGIcon name={expanded ? 'chevronUp' : 'chevronDown'}/> - <span className='title-text'>{i18n(item.description)}</span> - {item.added && <div className='new-line'>{i18n(item.added)}</div>} - </div> - <div className={expanded ? 'collapse in' : 'collapse'}> - <div> - <div> - <Input - data-test-id={`input-${item.key}`} - type='textarea' - isValid={genericFieldInfo[`${prefix}${item.key}`].isValid} - errorText={genericFieldInfo[`${prefix}${item.key}`].errorText} - value={dataMap[`${prefix}${item.key}`]} - onChange={(val) => onQDataChanged({[`${prefix}${item.key}`] : val})} /> - </div> - </div> - </div> - </GridItem> +const TextAreaItem = ({ + item, + toggle, + expanded, + genericFieldInfo, + dataMap, + onQDataChanged +}) => ( + <GridItem colSpan={3} key={item.key}> + <div + className={expanded ? 'title' : 'title add-padding'} + data-test-id={`btn-${item.key}`} + onClick={() => toggle(item.key)}> + <SVGIcon name={expanded ? 'chevronUp' : 'chevronDown'} /> + <span className="title-text">{i18n(item.description)}</span> + {item.added && <div className="new-line">{i18n(item.added)}</div>} + </div> + <div className={expanded ? 'collapse in' : 'collapse'}> + <div> + <div> + <Input + data-test-id={`input-${item.key}`} + type="textarea" + isValid={ + genericFieldInfo[`${prefix}${item.key}`].isValid + } + errorText={ + genericFieldInfo[`${prefix}${item.key}`].errorText + } + value={dataMap[`${prefix}${item.key}`]} + onChange={val => + onQDataChanged({ [`${prefix}${item.key}`]: val }) + } + /> + </div> + </div> + </div> + </GridItem> ); class SoftwareProductComponentLoadBalancingView extends React.Component { - static propTypes = { - componentId: PropTypes.string.isRequired, - softwareProductId: PropTypes.string.isRequired, - qdata: PropTypes.object, - qschema: PropTypes.object, - currentSoftwareProduct: PropTypes.object - }; + static propTypes = { + componentId: PropTypes.string.isRequired, + softwareProductId: PropTypes.string.isRequired, + qdata: PropTypes.object, + qschema: PropTypes.object, + currentSoftwareProduct: PropTypes.object + }; - state = { - expanded: {} - }; + state = { + expanded: {} + }; - render() { - let {dataMap, genericFieldInfo, onQDataChanged, isReadOnlyMode} = this.props; - return ( - <div className='vsp-components-load-balancing'> - <div className='halb-data'> - { genericFieldInfo && <Form - formReady={null} - isValid={true} - onSubmit={() => this.save()} - isReadOnlyMode={isReadOnlyMode} - hasButtons={false}> - <GridSection title={i18n('High Availability & Load Balancing')}> - <GridItem colSpan={1}> - <Input - data-test-id='input-is-component-mandatory' - label={i18n('Is Component Mandatory')} - type='select' - className='input-options-select' - groupClassName='bootstrap-input-options' - isValid={genericFieldInfo[`${prefix}isComponentMandatory`].isValid} - errorText={genericFieldInfo[`${prefix}isComponentMandatory`].errorText} - value={dataMap[`${prefix}isComponentMandatory`]} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({[`${prefix}isComponentMandatory`] : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - { genericFieldInfo[`${prefix}isComponentMandatory`].enum.map(isMan => <option value={isMan.enum} key={isMan.enum}>{isMan.title}</option>) } - </Input> - </GridItem> - <GridItem colSpan={3}/> - <GridItem colSpan={1}> - <Input - data-test-id='input-high-availability-mode' - label={i18n('High Availability Mode')} - type='select' - className='input-options-select' - groupClassName='bootstrap-input-options' - isValid={genericFieldInfo[`${prefix}highAvailabilityMode`].isValid} - errorText={genericFieldInfo[`${prefix}highAvailabilityMode`].errorText} - value={dataMap[`${prefix}highAvailabilityMode`]} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({[`${prefix}highAvailabilityMode`] : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - {genericFieldInfo[`${prefix}highAvailabilityMode`].enum.map(hmode => <option value={hmode.enum} key={hmode.enum}>{hmode.title}</option>)} - </Input> - </GridItem> - <GridItem colSpan={3}/> - </GridSection> - <GridSection> - {pointers.map(pointer => <TextAreaItem onQDataChanged={onQDataChanged} - genericFieldInfo={genericFieldInfo} dataMap={dataMap} item={pointer} key={pointer.key + 'pKey'} - expanded={this.state.expanded[pointer.key]} toggle={(name)=>{this.toggle(name);}} />)} - </GridSection> - </Form> } - </div> - </div> - ); - } + render() { + let { + dataMap, + genericFieldInfo, + onQDataChanged, + isReadOnlyMode + } = this.props; + return ( + <div className="vsp-components-load-balancing"> + <div className="halb-data"> + {genericFieldInfo && ( + <Form + formReady={null} + isValid={true} + onSubmit={() => this.save()} + isReadOnlyMode={isReadOnlyMode} + hasButtons={false}> + <GridSection + title={i18n( + 'High Availability & Load Balancing' + )}> + <GridItem colSpan={1}> + <Input + data-test-id="input-is-component-mandatory" + label={i18n('Is Component Mandatory')} + type="select" + className="input-options-select" + groupClassName="bootstrap-input-options" + isValid={ + genericFieldInfo[ + `${prefix}isComponentMandatory` + ].isValid + } + errorText={ + genericFieldInfo[ + `${prefix}isComponentMandatory` + ].errorText + } + value={ + dataMap[ + `${prefix}isComponentMandatory` + ] + } + onChange={e => { + const selectedIndex = + e.target.selectedIndex; + const val = + e.target.options[selectedIndex] + .value; + onQDataChanged({ + [`${prefix}isComponentMandatory`]: val + }); + }}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {genericFieldInfo[ + `${prefix}isComponentMandatory` + ].enum.map(isMan => ( + <option + value={isMan.enum} + key={isMan.enum}> + {isMan.title} + </option> + ))} + </Input> + </GridItem> + <GridItem colSpan={3} /> + <GridItem colSpan={1}> + <Input + data-test-id="input-high-availability-mode" + label={i18n('High Availability Mode')} + type="select" + className="input-options-select" + groupClassName="bootstrap-input-options" + isValid={ + genericFieldInfo[ + `${prefix}highAvailabilityMode` + ].isValid + } + errorText={ + genericFieldInfo[ + `${prefix}highAvailabilityMode` + ].errorText + } + value={ + dataMap[ + `${prefix}highAvailabilityMode` + ] + } + onChange={e => { + const selectedIndex = + e.target.selectedIndex; + const val = + e.target.options[selectedIndex] + .value; + onQDataChanged({ + [`${prefix}highAvailabilityMode`]: val + }); + }}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {genericFieldInfo[ + `${prefix}highAvailabilityMode` + ].enum.map(hmode => ( + <option + value={hmode.enum} + key={hmode.enum}> + {hmode.title} + </option> + ))} + </Input> + </GridItem> + <GridItem colSpan={3} /> + </GridSection> + <GridSection> + {pointers.map(pointer => ( + <TextAreaItem + onQDataChanged={onQDataChanged} + genericFieldInfo={genericFieldInfo} + dataMap={dataMap} + item={pointer} + key={pointer.key + 'pKey'} + expanded={ + this.state.expanded[pointer.key] + } + toggle={name => { + this.toggle(name); + }} + /> + ))} + </GridSection> + </Form> + )} + </div> + </div> + ); + } - toggle(name) { - let st = this.state.expanded[name] ? true : false; - let newState = {...this.state}; - newState.expanded[name] = !st; - this.setState(newState); - } + toggle(name) { + let st = this.state.expanded[name] ? true : false; + let newState = { ...this.state }; + newState.expanded[name] = !st; + this.setState(newState); + } - save() { - let {onSubmit, qdata} = this.props; - return onSubmit({qdata}); - } + save() { + let { onSubmit, qdata } = this.props; + return onSubmit({ qdata }); + } } export default SoftwareProductComponentLoadBalancingView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js index 8871aabbb5..0b0b9ae2d9 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js @@ -13,51 +13,54 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductComponentsMonitoringView from './SoftwareProductComponentsMonitoringView.jsx'; import SoftwareProductComponentsMonitoringAction from './SoftwareProductComponentsMonitoringActionHelper.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; - - -export const mapStateToProps = ({softwareProduct}) => { - - let {softwareProductComponents: {monitoring}} = softwareProduct; - return { - filenames: monitoring - }; - +export const mapStateToProps = ({ softwareProduct }) => { + let { softwareProductComponents: { monitoring } } = softwareProduct; + return { + filenames: monitoring + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => { - - return { - onDropMibFileToUpload: (formData, type) => - SoftwareProductComponentsMonitoringAction.uploadFile(dispatch, { - softwareProductId, - version, - componentId, - formData, - type - }), - - onDeleteFile: type => SoftwareProductComponentsMonitoringAction.deleteFile(dispatch, { - softwareProductId, - version, - componentId, - type - }), +const mapActionsToProps = ( + dispatch, + { softwareProductId, version, componentId } +) => { + return { + onDropMibFileToUpload: (formData, type) => + SoftwareProductComponentsMonitoringAction.uploadFile(dispatch, { + softwareProductId, + version, + componentId, + formData, + type + }), - onFileUploadError: () => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_ERROR, - data: { - title: i18n('Upload Failed'), - msg: i18n('Expected "zip" file. Please check the provided file type.') - } - }) - }; + onDeleteFile: type => + SoftwareProductComponentsMonitoringAction.deleteFile(dispatch, { + softwareProductId, + version, + componentId, + type + }), + onFileUploadError: () => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + title: i18n('Upload Failed'), + msg: i18n( + 'Expected "zip" file. Please check the provided file type.' + ) + } + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsMonitoringView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductComponentsMonitoringView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js index 3db708bc92..c60bc5f1be 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js @@ -16,61 +16,90 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; -import {actionTypes} from './SoftwareProductComponentsMonitoringConstants.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes } from './SoftwareProductComponentsMonitoringConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; function baseUrl(vspId, version, componentId) { - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/components/${componentId}/uploads`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/components/${componentId}/uploads`; } -let onInvalidFileSizeUpload = (dispatch) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_ERROR, - data: { - title: i18n('Upload Failed'), - msg: i18n('no zip file was uploaded or zip file doesn\'t exist') - } -}); +let onInvalidFileSizeUpload = dispatch => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + title: i18n('Upload Failed'), + msg: i18n("no zip file was uploaded or zip file doesn't exist") + } + }); -let uploadFile = (dispatch, {softwareProductId, version, componentId, formData, type}) => { - return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}/types/${type}`, formData).then(()=> dispatch({ - type: actionTypes.MONITOR_UPLOADED, data: {filename: formData.get('upload').name, type : type} - })); +let uploadFile = ( + dispatch, + { softwareProductId, version, componentId, formData, type } +) => { + return RestAPIUtil.post( + `${baseUrl(softwareProductId, version, componentId)}/types/${type}`, + formData + ).then(() => + dispatch({ + type: actionTypes.MONITOR_UPLOADED, + data: { filename: formData.get('upload').name, type: type } + }) + ); }; -let deleteFile = (dispatch, {softwareProductId, version, componentId, type}) => { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/types/${type}`).then(()=> dispatch({ - type: actionTypes.MONITOR_DELETED, - data : { type: type} - })); +let deleteFile = ( + dispatch, + { softwareProductId, version, componentId, type } +) => { + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version, componentId)}/types/${type}` + ).then(() => + dispatch({ + type: actionTypes.MONITOR_DELETED, + data: { type: type } + }) + ); }; - const SoftwareProductComponentsMonitoringAction = { + fetchExistingFiles(dispatch, { softwareProductId, version, componentId }) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version, componentId)}` + ).then(response => + dispatch({ + type: actionTypes.MONITOR_FILES_DATA_CHANGE, + data: response + }) + ); + }, - fetchExistingFiles(dispatch, {softwareProductId, version, componentId}){ - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`).then(response => - dispatch({ - type: actionTypes.MONITOR_FILES_DATA_CHANGE, - data: response - }) - ); - }, - - uploadFile(dispatch, {softwareProductId, version, componentId, formData, type}){ - if (formData.get('upload').size) { - return uploadFile(dispatch, {softwareProductId, version, componentId, formData, type}); - } - else { - onInvalidFileSizeUpload(dispatch); - } - }, - - deleteFile(dispatch, {softwareProductId, version, componentId, type}){ - return deleteFile(dispatch, {softwareProductId, version, componentId, type}); - } + uploadFile( + dispatch, + { softwareProductId, version, componentId, formData, type } + ) { + if (formData.get('upload').size) { + return uploadFile(dispatch, { + softwareProductId, + version, + componentId, + formData, + type + }); + } else { + onInvalidFileSizeUpload(dispatch); + } + }, + deleteFile(dispatch, { softwareProductId, version, componentId, type }) { + return deleteFile(dispatch, { + softwareProductId, + version, + componentId, + type + }); + } }; export default SoftwareProductComponentsMonitoringAction; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringConstants.js index bf2cbd2a3f..10049d6b57 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringConstants.js @@ -16,29 +16,26 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; - export const actionTypes = keyMirror({ - MONITOR_FILES_DATA_CHANGE: null, - MONITOR_UPLOADED: null, - MONITOR_DELETED: null + MONITOR_FILES_DATA_CHANGE: null, + MONITOR_UPLOADED: null, + MONITOR_DELETED: null }); export const fileTypes = { - SNMP_TRAP: 'SNMP_TRAP', - SNMP_POLL: 'SNMP_POLL', - VES_EVENT: 'VES_EVENTS' + SNMP_TRAP: 'SNMP_TRAP', + SNMP_POLL: 'SNMP_POLL', + VES_EVENT: 'VES_EVENTS' }; export const type2Name = { - SNMP_TRAP: 'snmpTrap', - SNMP_POLL: 'snmpPoll', - VES_EVENTS: 'vesEvent' + SNMP_TRAP: 'snmpTrap', + SNMP_POLL: 'snmpPoll', + VES_EVENTS: 'vesEvent' }; - export const type2Title = { - SNMP_TRAP : i18n('SNMP Trap'), - SNMP_POLL : i18n('SNMP Poll'), - VES_EVENTS: i18n('VES') + SNMP_TRAP: i18n('SNMP Trap'), + SNMP_POLL: i18n('SNMP Poll'), + VES_EVENTS: i18n('VES') }; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js index f5cfe6f06d..61ad4ec2d9 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js @@ -13,23 +13,26 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, type2Name} from './SoftwareProductComponentsMonitoringConstants.js'; +import { + actionTypes, + type2Name +} from './SoftwareProductComponentsMonitoringConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.MONITOR_FILES_DATA_CHANGE: - return action.data; - case actionTypes.MONITOR_UPLOADED: - return { - ...state, - [type2Name[action.data.type]]: action.data.filename - }; - case actionTypes.MONITOR_DELETED: - return { - ...state, - [type2Name[action.data.type]]: undefined - }; - default: - return state; - } + switch (action.type) { + case actionTypes.MONITOR_FILES_DATA_CHANGE: + return action.data; + case actionTypes.MONITOR_UPLOADED: + return { + ...state, + [type2Name[action.data.type]]: action.data.filename + }; + case actionTypes.MONITOR_DELETED: + return { + ...state, + [type2Name[action.data.type]]: undefined + }; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx index 95d1e4e283..771bca161a 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx @@ -13,123 +13,133 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Dropzone from 'react-dropzone'; import Button from 'sdc-ui/lib/react/Button.js'; import DraggableUploadFileBox from 'nfvo-components/fileupload/DraggableUploadFileBox.jsx'; -import {fileTypes, type2Title, type2Name} from './SoftwareProductComponentsMonitoringConstants.js'; - - +import { + fileTypes, + type2Title, + type2Name +} from './SoftwareProductComponentsMonitoringConstants.js'; class SoftwareProductComponentsMonitoringView extends Component { - - static propTypes = { - isReadOnlyMode: PropTypes.bool, - filenames: PropTypes.object, - softwareProductId: PropTypes.string, - - onDropMibFileToUpload: PropTypes.func, - onDeleteSnmpFile: PropTypes.func - }; - - state = { - dragging: false - }; - - - - - render() { - return ( - <div className='vsp-component-monitoring'> - {this.renderDropzoneWithType(fileTypes.VES_EVENT)} - {this.renderDropzoneWithType(fileTypes.SNMP_TRAP)} - {this.renderDropzoneWithType(fileTypes.SNMP_POLL)} - </div> - ); - } - - renderDropzoneWithType(type) { - let {isReadOnlyMode, filenames} = this.props; - let fileByType = type2Name[type]; - let fileName = (filenames) ? filenames[fileByType] : undefined; - let refAndName = `fileInput${type.toString()}`; - let typeDisplayName = type2Title[type]; - return ( - <Dropzone - className={`dropzone ${this.state.dragging ? 'active-dragging' : ''}`} - onDrop={(acceptedFiles, rejectedFiles) => this.handleImport(acceptedFiles, rejectedFiles, {isReadOnlyMode, type, refAndName})} - onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode)} - onDragLeave={() => this.setState({dragging:false})} - multiple={false} - disableClick={true} - ref={refAndName} - name={refAndName} - accept='.zip'> - <div className='draggable-wrapper'> - <div className='section-title'>{typeDisplayName}</div> - {fileName ? this.renderUploadedFileName(fileName, type, isReadOnlyMode) : this.renderUploadButton(refAndName)} - </div> - </Dropzone> - ); - } - - renderUploadButton(refAndName) { - let {isReadOnlyMode} = this.props; - return ( - <DraggableUploadFileBox - dataTestId={`monitoring-upload-${refAndName}`} - className='software-product-landing-view-top-block-col-upl' - isReadOnlyMode={isReadOnlyMode} - onClick={() => this.refs[refAndName].open()}/> - ); - } - - renderUploadedFileName(filename, type, isReadOnlyMode) { - return ( - <div className='monitoring-file'> - <Button - color='white' - disabled={true} - className='filename'> - {filename} - </Button> - - <Button - color='gray' - data-test-id={`monitoring-delete-${type}`} - disabled={isReadOnlyMode} - onClick={()=>this.props.onDeleteFile(type)} - iconName='close' - className='delete'/> - </div> - ); - } - - - handleOnDragEnter(isReadOnlyMode) { - if (!isReadOnlyMode) { - this.setState({dragging: true}); - } - } - - handleImport(files, rejectedFiles, {isReadOnlyMode, type, refAndName}) { - if (isReadOnlyMode) { - return; - } - if (files.length > 0) { - this.setState({dragging: false}); - let file = files[0]; - let formData = new FormData(); - formData.append('upload', file); - this.refs[refAndName].value = ''; - this.props.onDropMibFileToUpload(formData, type); - } else if (rejectedFiles.length > 0) { - this.setState({dragging: false}); - this.props.onFileUploadError(); - } - } + static propTypes = { + isReadOnlyMode: PropTypes.bool, + filenames: PropTypes.object, + softwareProductId: PropTypes.string, + + onDropMibFileToUpload: PropTypes.func, + onDeleteSnmpFile: PropTypes.func + }; + + state = { + dragging: false + }; + + render() { + return ( + <div className="vsp-component-monitoring"> + {this.renderDropzoneWithType(fileTypes.VES_EVENT)} + {this.renderDropzoneWithType(fileTypes.SNMP_TRAP)} + {this.renderDropzoneWithType(fileTypes.SNMP_POLL)} + </div> + ); + } + + renderDropzoneWithType(type) { + let { isReadOnlyMode, filenames } = this.props; + let fileByType = type2Name[type]; + let fileName = filenames ? filenames[fileByType] : undefined; + let refAndName = `fileInput${type.toString()}`; + let typeDisplayName = type2Title[type]; + return ( + <Dropzone + className={`dropzone ${ + this.state.dragging ? 'active-dragging' : '' + }`} + onDrop={(acceptedFiles, rejectedFiles) => + this.handleImport(acceptedFiles, rejectedFiles, { + isReadOnlyMode, + type, + refAndName + }) + } + onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode)} + onDragLeave={() => this.setState({ dragging: false })} + multiple={false} + disableClick={true} + ref={refAndName} + name={refAndName} + accept=".zip"> + <div className="draggable-wrapper"> + <div className="section-title">{typeDisplayName}</div> + {fileName + ? this.renderUploadedFileName( + fileName, + type, + isReadOnlyMode + ) + : this.renderUploadButton(refAndName)} + </div> + </Dropzone> + ); + } + + renderUploadButton(refAndName) { + let { isReadOnlyMode } = this.props; + return ( + <DraggableUploadFileBox + dataTestId={`monitoring-upload-${refAndName}`} + className="software-product-landing-view-top-block-col-upl" + isReadOnlyMode={isReadOnlyMode} + onClick={() => this.refs[refAndName].open()} + /> + ); + } + + renderUploadedFileName(filename, type, isReadOnlyMode) { + return ( + <div className="monitoring-file"> + <Button color="white" disabled={true} className="filename"> + {filename} + </Button> + + <Button + color="gray" + data-test-id={`monitoring-delete-${type}`} + disabled={isReadOnlyMode} + onClick={() => this.props.onDeleteFile(type)} + iconName="close" + className="delete" + /> + </div> + ); + } + + handleOnDragEnter(isReadOnlyMode) { + if (!isReadOnlyMode) { + this.setState({ dragging: true }); + } + } + + handleImport(files, rejectedFiles, { isReadOnlyMode, type, refAndName }) { + if (isReadOnlyMode) { + return; + } + if (files.length > 0) { + this.setState({ dragging: false }); + let file = files[0]; + let formData = new FormData(); + formData.append('upload', file); + this.refs[refAndName].value = ''; + this.props.onDropMibFileToUpload(formData, type); + } else if (rejectedFiles.length > 0) { + this.setState({ dragging: false }); + this.props.onFileUploadError(); + } + } } export default SoftwareProductComponentsMonitoringView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js index d4aaf7cc7e..e705618a65 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js @@ -13,39 +13,55 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import NICCreationActionHelper from './NICCreationActionHelper.js'; import NICCreationView from './NICCreationView.jsx'; import SoftwareProductComponentsNetworkActionHelper from '../SoftwareProductComponentsNetworkActionHelper.js'; -import {networkTypes, NIC_CREATION_FORM_NAME} from '../SoftwareProductComponentsNetworkConstants.js'; +import { + networkTypes, + NIC_CREATION_FORM_NAME +} from '../SoftwareProductComponentsNetworkConstants.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductEditor: {data:currentSoftwareProduct = {}}, softwareProductComponents} = softwareProduct; - let {network: {nicCreation = {}}} = softwareProductComponents; - let {data, genericFieldInfo, formReady} = nicCreation; - data = {...data, networkType: networkTypes.EXTERNAL}; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductEditor: { data: currentSoftwareProduct = {} }, + softwareProductComponents + } = softwareProduct; + let { network: { nicCreation = {} } } = softwareProductComponents; + let { data, genericFieldInfo, formReady } = nicCreation; + data = { ...data, networkType: networkTypes.EXTERNAL }; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - return { - currentSoftwareProduct, - data, - genericFieldInfo, - isFormValid, - formReady - }; + return { + currentSoftwareProduct, + data, + genericFieldInfo, + isFormValid, + formReady + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version}) => { - return { - onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: NIC_CREATION_FORM_NAME}), - onCancel: () => NICCreationActionHelper.close(dispatch), - onSubmit: ({nic, componentId}) => { - SoftwareProductComponentsNetworkActionHelper.createNIC(dispatch, {nic, softwareProductId, componentId, version}); - NICCreationActionHelper.close(dispatch); - }, - onValidateForm: () => ValidationHelper.validateForm(dispatch, NIC_CREATION_FORM_NAME) - }; +const mapActionsToProps = (dispatch, { softwareProductId, version }) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: NIC_CREATION_FORM_NAME + }), + onCancel: () => NICCreationActionHelper.close(dispatch), + onSubmit: ({ nic, componentId }) => { + SoftwareProductComponentsNetworkActionHelper.createNIC(dispatch, { + nic, + softwareProductId, + componentId, + version + }); + NICCreationActionHelper.close(dispatch); + }, + onValidateForm: () => + ValidationHelper.validateForm(dispatch, NIC_CREATION_FORM_NAME) + }; }; export default connect(mapStateToProps, mapActionsToProps)(NICCreationView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js index a40b32d51a..4f200ce33f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js @@ -13,35 +13,37 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from '../SoftwareProductComponentsNetworkConstants'; +import { actionTypes } from '../SoftwareProductComponentsNetworkConstants'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; export default { + open( + dispatch, + { softwareProductId, componentId, modalClassName, version } + ) { + dispatch({ + type: actionTypes.NICCreation.OPEN + }); - open(dispatch, {softwareProductId, componentId, modalClassName, version}) { - dispatch({ - type: actionTypes.NICCreation.OPEN - }); + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: modalContentMapper.NIC_CREATION, + title: i18n('Create NEW NIC'), + modalClassName, + modalComponentProps: { softwareProductId, componentId, version } + } + }); + }, - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.NIC_CREATION, - title: i18n('Create NEW NIC'), - modalClassName, - modalComponentProps: {softwareProductId, componentId, version} - } - }); - }, - - close(dispatch){ - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_CLOSE - }); - dispatch({ - type: actionTypes.NICCreation.CLEAR_DATA - }); - } + close(dispatch) { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }); + dispatch({ + type: actionTypes.NICCreation.CLEAR_DATA + }); + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js index c7e2495b3d..8309c40451 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js @@ -13,37 +13,40 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, NIC_CREATION_FORM_NAME} from '../SoftwareProductComponentsNetworkConstants.js'; +import { + actionTypes, + NIC_CREATION_FORM_NAME +} from '../SoftwareProductComponentsNetworkConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.NICCreation.OPEN: - return { - ...state, - data: {}, - formName: NIC_CREATION_FORM_NAME, - formReady: null, - genericFieldInfo: { - 'description' : { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 1000}] - }, - 'name' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data : true}] - }, - 'networkDescription' : { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 50}] - } - } - }; - case actionTypes.NICCreation.CLEAR_DATA: - return {}; - default: - return state; - } + switch (action.type) { + case actionTypes.NICCreation.OPEN: + return { + ...state, + data: {}, + formName: NIC_CREATION_FORM_NAME, + formReady: null, + genericFieldInfo: { + description: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 1000 }] + }, + name: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + }, + networkDescription: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 50 }] + } + } + }; + case actionTypes.NICCreation.CLEAR_DATA: + return {}; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx index 258876844a..88525c051d 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx @@ -22,103 +22,136 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; const NICPropType = PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string, - description: PropTypes.string, - networkId: PropTypes.string + id: PropTypes.string, + name: PropTypes.string, + description: PropTypes.string, + networkId: PropTypes.string }); class NICCreationView extends React.Component { + static propTypes = { + data: NICPropType, + onDataChanged: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired + }; - static propTypes = { - data: NICPropType, - onDataChanged: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, - onCancel: PropTypes.func.isRequired - }; + render() { + let { + data = {}, + onDataChanged, + genericFieldInfo, + isFormValid, + onValidateForm, + formReady + } = this.props; + let { name, description, networkDescription } = data; + return ( + <div> + {genericFieldInfo && ( + <Form + ref={form => (this.form = form)} + hasButtons={true} + onSubmit={() => this.submit()} + submitButtonText={ + data.id ? i18n('Save') : i18n('Create') + } + onReset={() => this.props.onCancel()} + labledButtons={true} + isValid={isFormValid} + onValidateForm={() => onValidateForm()} + formReady={formReady}> + <GridSection hasLastColSet> + <GridItem colSpan={4} lastColInRow> + <Input + value={name} + label={i18n('Name')} + data-test-id="nic-name" + onChange={name => onDataChanged({ name })} + isRequired={true} + type="text" + isValid={genericFieldInfo['name'].isValid} + errorText={ + genericFieldInfo['name'].errorText + } + className="field-section" + /> + <Input + value={description} + label={i18n('Description')} + data-test-id="nic-description" + onChange={description => + onDataChanged({ description }) + } + isValid={ + genericFieldInfo['description'].isValid + } + errorText={ + genericFieldInfo['description'] + .errorText + } + type="textarea" + className="field-section" + /> + </GridItem> + </GridSection> + <GridSection title={i18n('Network')} hasLastColSet> + <GridItem colSpan={2}> + <div className="form-group"> + <label className="control-label"> + {i18n('Network Type')} + </label> + <div className="network-type-radio"> + <Input + label={i18n('Internal')} + disabled + checked={false} + data-test-id="nic-internal" + className="network-radio disabled" + type="radio" + /> + <Input + label={i18n('External')} + disabled + checked={true} + data-test-id="nic-external" + className="network-radio disabled" + type="radio" + /> + </div> + </div> + </GridItem> + <GridItem colSpan={2} lastColInRow> + <Input + value={networkDescription} + label={i18n('Network Description')} + data-test-id="nic-network-description" + onChange={networkDescription => + onDataChanged({ networkDescription }) + } + isValid={ + genericFieldInfo['networkDescription'] + .isValid + } + errorText={ + genericFieldInfo['networkDescription'] + .errorText + } + type="text" + className="field-section" + /> + </GridItem> + </GridSection> + </Form> + )} + </div> + ); + } - render() { - let {data = {}, onDataChanged, genericFieldInfo, isFormValid, onValidateForm, formReady} = this.props; - let {name, description, networkDescription} = data; - return ( - <div> - {genericFieldInfo && <Form - ref={(form) => this.form = form} - hasButtons={true} - onSubmit={ () => this.submit() } - submitButtonText={data.id ? i18n('Save') : i18n('Create')} - onReset={ () => this.props.onCancel() } - labledButtons={true} - isValid={isFormValid} - onValidateForm={() => onValidateForm()} - formReady={formReady} > - <GridSection hasLastColSet> - <GridItem colSpan={4} lastColInRow> - <Input - value={name} - label={i18n('Name')} - data-test-id='nic-name' - onChange={name => onDataChanged({name})} - isRequired={true} - type='text' - isValid={genericFieldInfo['name'].isValid} - errorText={genericFieldInfo['name'].errorText} - className='field-section'/> - <Input - value={description} - label={i18n('Description')} - data-test-id='nic-description' - onChange={description => onDataChanged({description})} - isValid={genericFieldInfo['description'].isValid} - errorText={genericFieldInfo['description'].errorText} - type='textarea' - className='field-section'/> - </GridItem> - </GridSection> - <GridSection title={i18n('Network')} hasLastColSet> - <GridItem colSpan={2}> - <div className='form-group'> - <label className='control-label'>{i18n('Network Type')}</label> - <div className='network-type-radio'> - <Input - label={i18n('Internal')} - disabled - checked={false} - data-test-id='nic-internal' - className='network-radio disabled' - type='radio'/> - <Input - label={i18n('External')} - disabled - checked={true} - data-test-id='nic-external' - className='network-radio disabled' - type='radio'/> - </div> - </div> - </GridItem> - <GridItem colSpan={2} lastColInRow> - <Input - value={networkDescription} - label={i18n('Network Description')} - data-test-id='nic-network-description' - onChange={networkDescription => onDataChanged({networkDescription})} - isValid={genericFieldInfo['networkDescription'].isValid} - errorText={genericFieldInfo['networkDescription'].errorText} - type='text' - className='field-section'/> - </GridItem> - </GridSection> - </Form>} - </div> - ); - } - - - submit() { - const {data: nic, componentId} = this.props; - this.props.onSubmit({nic, componentId}); - } + submit() { + const { data: nic, componentId } = this.props; + this.props.onSubmit({ nic, componentId }); + } } export default NICCreationView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js index 93bd0bd67e..d7205b46ed 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js @@ -13,56 +13,93 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductComponentsNetworkActionHelper from './SoftwareProductComponentsNetworkActionHelper.js'; import SoftwareProductComponentsNICEditorView from './SoftwareProductComponentsNICEditorView.jsx'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; -import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js'; -import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js'; +import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { NIC_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js'; +import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js'; -export const mapStateToProps = ({softwareProduct, currentScreen}) => { - - let {softwareProductEditor: {data:currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct; - let {network: {nicEditor = {}}} = softwareProductComponents; - let {data, qdata, genericFieldInfo, qgenericFieldInfo, dataMap, formReady} = nicEditor; - let {props: {isReadOnlyMode}} = currentScreen; - let {onboardingMethod} = currentSoftwareProduct; - let protocols = []; - if(qdata && qdata.protocols && qdata.protocols.protocols && qdata.protocols.protocols.length){ - protocols = qdata.protocols.protocols; - } - let {version} = currentSoftwareProduct; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo) && ValidationHelper.checkFormValid(qgenericFieldInfo); - - return { - currentSoftwareProduct, - isValidityData, - version, - data, - qdata, - dataMap, - isFormValid, - formReady, - genericFieldInfo, - qgenericFieldInfo, - isReadOnlyMode, - protocols, - isManual: onboardingMethod === onboardingMethodTypes.MANUAL - }; +export const mapStateToProps = ({ softwareProduct, currentScreen }) => { + let { + softwareProductEditor: { + data: currentSoftwareProduct = {}, + isValidityData = true + }, + softwareProductComponents + } = softwareProduct; + let { network: { nicEditor = {} } } = softwareProductComponents; + let { + data, + qdata, + genericFieldInfo, + qgenericFieldInfo, + dataMap, + formReady + } = nicEditor; + let { props: { isReadOnlyMode } } = currentScreen; + let { onboardingMethod } = currentSoftwareProduct; + let protocols = []; + if ( + qdata && + qdata.protocols && + qdata.protocols.protocols && + qdata.protocols.protocols.length + ) { + protocols = qdata.protocols.protocols; + } + let { version } = currentSoftwareProduct; + let isFormValid = + ValidationHelper.checkFormValid(genericFieldInfo) && + ValidationHelper.checkFormValid(qgenericFieldInfo); + return { + currentSoftwareProduct, + isValidityData, + version, + data, + qdata, + dataMap, + isFormValid, + formReady, + genericFieldInfo, + qgenericFieldInfo, + isReadOnlyMode, + protocols, + isManual: onboardingMethod === onboardingMethodTypes.MANUAL + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => { - return { - onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, - formName: forms.NIC_EDIT_FORM}), - onSubmit: ({data, qdata}) => SoftwareProductComponentsNetworkActionHelper.saveNICDataAndQuestionnaire(dispatch, {softwareProductId, version, componentId, data, qdata}), - onCancel: () => SoftwareProductComponentsNetworkActionHelper.closeNICEditor(dispatch), - onValidateForm: () => ValidationHelper.validateForm(dispatch, forms.NIC_EDIT_FORM), - onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, - qName: NIC_QUESTIONNAIRE}), - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, componentId, version } +) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: forms.NIC_EDIT_FORM + }), + onSubmit: ({ data, qdata }) => + SoftwareProductComponentsNetworkActionHelper.saveNICDataAndQuestionnaire( + dispatch, + { softwareProductId, version, componentId, data, qdata } + ), + onCancel: () => + SoftwareProductComponentsNetworkActionHelper.closeNICEditor( + dispatch + ), + onValidateForm: () => + ValidationHelper.validateForm(dispatch, forms.NIC_EDIT_FORM), + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: NIC_QUESTIONNAIRE + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentsNICEditorView); +export default connect(mapStateToProps, mapActionsToProps)( + SoftwareProductComponentsNICEditorView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorReducer.js index dd37135d77..2da9b4b76b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorReducer.js @@ -13,37 +13,37 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js'; -import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { actionTypes } from './SoftwareProductComponentsNetworkConstants.js'; +import { forms } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.NICEditor.FILL_DATA: - return { - ...state, - data: action.nic, - genericFieldInfo: { - 'description' : { - isValid: true, - errorText: '', - validations: [] - }, - 'name' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data : true}] - }, - 'networkDescription' : { - isValid: true, - errorText: '', - validations: [] - } - }, - formName: forms.NIC_EDIT_FORM - }; - case actionTypes.NICEditor.CLEAR_DATA: - return {}; - default: - return state; - } + switch (action.type) { + case actionTypes.NICEditor.FILL_DATA: + return { + ...state, + data: action.nic, + genericFieldInfo: { + description: { + isValid: true, + errorText: '', + validations: [] + }, + name: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + }, + networkDescription: { + isValid: true, + errorText: '', + validations: [] + } + }, + formName: forms.NIC_EDIT_FORM + }; + case actionTypes.NICEditor.CLEAR_DATA: + return {}; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx index fbb3d53033..df2efbe39e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx @@ -26,48 +26,113 @@ import Protocols from './nicEditorComponents/Protocols.jsx'; import NameAndPurpose from './nicEditorComponents/NameAndPurpose.jsx'; class SoftwareProductComponentsNetworkEditorView extends React.Component { + render() { + let { + onCancel, + onValidateForm, + isReadOnlyMode, + isFormValid, + formReady, + data = {}, + qgenericFieldInfo, + dataMap, + onDataChanged, + protocols, + onQDataChanged, + isManual, + genericFieldInfo + } = this.props; + let { + name, + description, + networkName, + networkType, + networkDescription + } = data; + let netWorkValues = [ + { + enum: networkName, + title: networkName + } + ]; + return ( + <div> + {qgenericFieldInfo && ( + <Form + ref={form => { + this.form = form; + }} + hasButtons={true} + onSubmit={() => this.submit()} + onReset={() => onCancel()} + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + isValid={isFormValid} + formReady={formReady} + onValidateForm={() => onValidateForm()} + className="vsp-components-network-editor"> + <div className="editor-data"> + <NameAndPurpose + isManual={isManual} + name={name} + description={description} + onDataChanged={onDataChanged} + isReadOnlyMode={isReadOnlyMode} + genericFieldInfo={genericFieldInfo} + /> + <Protocols + protocols={protocols} + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + <IpConfig + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + <Network + networkDescription={networkDescription} + onDataChanged={onDataChanged} + networkValues={netWorkValues} + isReadOnlyMode={isReadOnlyMode} + networkType={networkType} + /> + <Sizing + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + <InFlowTraffic + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + <OutFlowTraffic + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + <FlowLength + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + <Acceptable + qgenericFieldInfo={qgenericFieldInfo} + dataMap={dataMap} + onQDataChanged={onQDataChanged} + /> + </div> + </Form> + )} + </div> + ); + } - render() { - let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, qgenericFieldInfo, - dataMap, onDataChanged, protocols, onQDataChanged, isManual, genericFieldInfo} = this.props; - let {name, description, networkName, networkType, networkDescription} = data; - let netWorkValues = [{ - enum: networkName, - title: networkName - }]; - return ( - <div> - {qgenericFieldInfo && <Form - ref={(form) => { this.form = form; }} - hasButtons={true} - onSubmit={ () => this.submit() } - onReset={ () => onCancel() } - labledButtons={true} - isReadOnlyMode={isReadOnlyMode} - isValid={isFormValid} - formReady={formReady} - onValidateForm={() => onValidateForm() } - className='vsp-components-network-editor'> - <div className='editor-data'> - <NameAndPurpose isManual={isManual} name={name} description={description} onDataChanged={onDataChanged} isReadOnlyMode={isReadOnlyMode} genericFieldInfo={genericFieldInfo} /> - <Protocols protocols={protocols} qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} /> - <IpConfig dataMap={dataMap} onQDataChanged={onQDataChanged} /> - <Network networkDescription={networkDescription} onDataChanged={onDataChanged} networkValues={netWorkValues} isReadOnlyMode={isReadOnlyMode} networkType={networkType} /> - <Sizing qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} /> - <InFlowTraffic qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} /> - <OutFlowTraffic qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} /> - <FlowLength qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} /> - <Acceptable qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} /> - </div> - </Form> } - </div> - ); - } - - submit() { - let {data, qdata, onSubmit} = this.props; - onSubmit({data, qdata}); - } + submit() { + let { data, qdata, onSubmit } = this.props; + onSubmit({ data, qdata }); + } } export default SoftwareProductComponentsNetworkEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICListReducer.js index 5cfc88bdc9..a2e65142a2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICListReducer.js @@ -13,16 +13,22 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js'; +import { actionTypes } from './SoftwareProductComponentsNetworkConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.NIC_LIST_UPDATE: - return [...action.response]; - case actionTypes.NIC_LIST_EDIT: - const indexForEdit = state.findIndex(nic => nic.id === action.nic.id); - return [...state.slice(0, indexForEdit), action.nic, ...state.slice(indexForEdit + 1)]; - default: - return state; - } + switch (action.type) { + case actionTypes.NIC_LIST_UPDATE: + return [...action.response]; + case actionTypes.NIC_LIST_EDIT: + const indexForEdit = state.findIndex( + nic => nic.id === action.nic.id + ); + return [ + ...state.slice(0, indexForEdit), + action.nic, + ...state.slice(indexForEdit + 1) + ]; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js index 1ffbc5919f..58c816134b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js @@ -17,127 +17,223 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js'; -import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {modalContentMapper as modalPagesMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; +import { actionTypes } from './SoftwareProductComponentsNetworkConstants.js'; +import { actionTypes as GlobalModalActions } from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper as modalPagesMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js'; +import { NIC_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js'; function baseUrl(softwareProductId, version, componentId) { - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/nics`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/nics`; } -function createNIC({nic, vspId, componentId, version}) { - return RestAPIUtil.post(baseUrl(vspId, version, componentId), { - name: nic.name, - description: nic.description, - networkDescription: nic.networkDescription, - networkType: nic.networkType - }); +function createNIC({ nic, vspId, componentId, version }) { + return RestAPIUtil.post(baseUrl(vspId, version, componentId), { + name: nic.name, + description: nic.description, + networkDescription: nic.networkDescription, + networkType: nic.networkType + }); } -function fetchNICQuestionnaire({softwareProductId, version, componentId, nicId}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${nicId}/questionnaire`); +function fetchNICQuestionnaire({ + softwareProductId, + version, + componentId, + nicId +}) { + return RestAPIUtil.fetch( + `${baseUrl( + softwareProductId, + version, + componentId + )}/${nicId}/questionnaire` + ); } -function fetchNIC({softwareProductId, version, componentId, nicId}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${nicId}`); +function fetchNIC({ softwareProductId, version, componentId, nicId }) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version, componentId)}/${nicId}` + ); } -function fetchNICsList({softwareProductId, version, componentId}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`); +function fetchNICsList({ softwareProductId, version, componentId }) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version, componentId)}` + ); } -function deleteNIC({softwareProductId, componentId, nicId, version}) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${nicId}`); +function deleteNIC({ softwareProductId, componentId, nicId, version }) { + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version, componentId)}/${nicId}` + ); } -function saveNIC({softwareProductId, version, componentId, nic: {id, name, description, networkId, networkType, networkDescription}}) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${id}`,{ - name, - description, - networkId, - networkDescription, - networkType - }); +function saveNIC({ + softwareProductId, + version, + componentId, + nic: { id, name, description, networkId, networkType, networkDescription } +}) { + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version, componentId)}/${id}`, + { + name, + description, + networkId, + networkDescription, + networkType + } + ); } -function saveNICQuestionnaire({softwareProductId, version, componentId, nicId, qdata}) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${nicId}/questionnaire`, qdata); +function saveNICQuestionnaire({ + softwareProductId, + version, + componentId, + nicId, + qdata +}) { + return RestAPIUtil.put( + `${baseUrl( + softwareProductId, + version, + componentId + )}/${nicId}/questionnaire`, + qdata + ); } const SoftwareProductComponentNetworkActionHelper = { - - fetchNICsList(dispatch, {softwareProductId, version, componentId}) { - return fetchNICsList({softwareProductId, version, componentId}).then((response) => { - dispatch({ - type: actionTypes.NIC_LIST_UPDATE, - response: response.results - }); - }); - }, - - openNICEditor(dispatch, {nic = {}, data = {}, softwareProductId, componentId, isReadOnlyMode, modalClassName, version}) { - dispatch({ - type: actionTypes.NICEditor.FILL_DATA, - nic: {...data, id: nic.id} - }); - dispatch({ - type: GlobalModalActions.GLOBAL_MODAL_SHOW, - data: { - modalClassName, - modalComponentProps: {softwareProductId, componentId, isReadOnlyMode, version}, - modalComponentName: modalPagesMapper.NIC_EDITOR, - title: i18n('Edit NIC') - } - }); - }, - - closeNICEditor(dispatch) { - dispatch({ - type: GlobalModalActions.GLOBAL_MODAL_CLOSE - }); - dispatch({ - type: actionTypes.NICEditor.CLEAR_DATA - }); - }, - - createNIC(dispatch, {nic, softwareProductId, componentId, version}){ - return createNIC({nic, vspId: softwareProductId, componentId, version}).then(() => { - return SoftwareProductComponentNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version}); - }); - }, - loadNICData({softwareProductId, version, componentId, nicId}) { - return fetchNIC({softwareProductId, version, componentId, nicId}); - }, - - deleteNIC(dispatch, {softwareProductId, componentId, nicId, version}) { - return deleteNIC({softwareProductId, componentId, nicId, version}).then(() => { - return SoftwareProductComponentNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version}); - }); - }, - loadNICQuestionnaire(dispatch, {softwareProductId, version, componentId, nicId}) { - return fetchNICQuestionnaire({softwareProductId, version, componentId, nicId}).then((response) => { - ValidationHelper.qDataLoaded(dispatch, {qName: NIC_QUESTIONNAIRE ,response: { - qdata: response.data ? JSON.parse(response.data) : {}, - qschema: JSON.parse(response.schema) - }}); - }); - }, - - saveNICDataAndQuestionnaire(dispatch, {softwareProductId, version, componentId, data, qdata}) { - SoftwareProductComponentNetworkActionHelper.closeNICEditor(dispatch); - return Promise.all([ - saveNICQuestionnaire({softwareProductId, version, componentId, nicId: data.id, qdata}), - saveNIC({softwareProductId, version, componentId, nic: data}).then(() => { - dispatch({ - type: actionTypes.NIC_LIST_EDIT, - nic: data - }); - }) - ]); - } + fetchNICsList(dispatch, { softwareProductId, version, componentId }) { + return fetchNICsList({ softwareProductId, version, componentId }).then( + response => { + dispatch({ + type: actionTypes.NIC_LIST_UPDATE, + response: response.results + }); + } + ); + }, + + openNICEditor( + dispatch, + { + nic = {}, + data = {}, + softwareProductId, + componentId, + isReadOnlyMode, + modalClassName, + version + } + ) { + dispatch({ + type: actionTypes.NICEditor.FILL_DATA, + nic: { ...data, id: nic.id } + }); + dispatch({ + type: GlobalModalActions.GLOBAL_MODAL_SHOW, + data: { + modalClassName, + modalComponentProps: { + softwareProductId, + componentId, + isReadOnlyMode, + version + }, + modalComponentName: modalPagesMapper.NIC_EDITOR, + title: i18n('Edit NIC') + } + }); + }, + + closeNICEditor(dispatch) { + dispatch({ + type: GlobalModalActions.GLOBAL_MODAL_CLOSE + }); + dispatch({ + type: actionTypes.NICEditor.CLEAR_DATA + }); + }, + + createNIC(dispatch, { nic, softwareProductId, componentId, version }) { + return createNIC({ + nic, + vspId: softwareProductId, + componentId, + version + }).then(() => { + return SoftwareProductComponentNetworkActionHelper.fetchNICsList( + dispatch, + { softwareProductId, componentId, version } + ); + }); + }, + loadNICData({ softwareProductId, version, componentId, nicId }) { + return fetchNIC({ softwareProductId, version, componentId, nicId }); + }, + + deleteNIC(dispatch, { softwareProductId, componentId, nicId, version }) { + return deleteNIC({ + softwareProductId, + componentId, + nicId, + version + }).then(() => { + return SoftwareProductComponentNetworkActionHelper.fetchNICsList( + dispatch, + { softwareProductId, componentId, version } + ); + }); + }, + loadNICQuestionnaire( + dispatch, + { softwareProductId, version, componentId, nicId } + ) { + return fetchNICQuestionnaire({ + softwareProductId, + version, + componentId, + nicId + }).then(response => { + ValidationHelper.qDataLoaded(dispatch, { + qName: NIC_QUESTIONNAIRE, + response: { + qdata: response.data ? JSON.parse(response.data) : {}, + qschema: JSON.parse(response.schema) + } + }); + }); + }, + + saveNICDataAndQuestionnaire( + dispatch, + { softwareProductId, version, componentId, data, qdata } + ) { + SoftwareProductComponentNetworkActionHelper.closeNICEditor(dispatch); + return Promise.all([ + saveNICQuestionnaire({ + softwareProductId, + version, + componentId, + nicId: data.id, + qdata + }), + saveNIC({ + softwareProductId, + version, + componentId, + nic: data + }).then(() => { + dispatch({ + type: actionTypes.NIC_LIST_EDIT, + nic: data + }); + }) + ]); + } }; export default SoftwareProductComponentNetworkActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js index 8ef8fe8c18..4e361bb1a9 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js @@ -16,23 +16,23 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - NIC_LIST_EDIT: null, - NIC_LIST_UPDATE: null, + NIC_LIST_EDIT: null, + NIC_LIST_UPDATE: null, - NICEditor: { - FILL_DATA: null, - CLEAR_DATA: null, - }, - NICCreation: { - OPEN: null, - CLEAR_DATA: null, - DATA_CHANGED: null - }, + NICEditor: { + FILL_DATA: null, + CLEAR_DATA: null + }, + NICCreation: { + OPEN: null, + CLEAR_DATA: null, + DATA_CHANGED: null + } }); export const networkTypes = { - EXTERNAL: 'External', - INTERNAL: 'Internal' + EXTERNAL: 'External', + INTERNAL: 'Internal' }; export const NIC_QUESTIONNAIRE = 'nic'; export const NIC_CREATION_FORM_NAME = 'nicCreation'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js index bb256d5d41..ac708524cf 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js @@ -13,79 +13,132 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js'; import SoftwareProductComponentsNetworkListView from './SoftwareProductComponentsNetworkListView.jsx'; import SoftwareProductComponentsNetworkActionHelper from './SoftwareProductComponentsNetworkActionHelper.js'; -import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; +import { COMPONENTS_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as GlobalModalActions } from 'nfvo-components/modal/GlobalModalConstants.js'; import NICCreationActionHelper from './NICCreation/NICCreationActionHelper.js'; -import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js'; +import { onboardingMethod as onboardingMethodTypes } from '../../SoftwareProductConstants.js'; +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductEditor: { + data: currentSoftwareProduct = {}, + isValidityData = true + }, + softwareProductComponents + } = softwareProduct; + let { + network: { nicList = [] }, + componentEditor: { + data: componentData, + qdata, + dataMap, + qgenericFieldInfo + } + } = softwareProductComponents; + let { version, onboardingMethod } = currentSoftwareProduct; + let isManual = onboardingMethod === onboardingMethodTypes.MANUAL; -export const mapStateToProps = ({softwareProduct}) => { - - let {softwareProductEditor: {data: currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct; - let {network: {nicList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents; - let {version, onboardingMethod} = currentSoftwareProduct; - let isManual = onboardingMethod === onboardingMethodTypes.MANUAL; - - return { - version, - componentData, - qdata, - dataMap, - qgenericFieldInfo, - isValidityData, - nicList, - isManual - }; - + return { + version, + componentData, + qdata, + dataMap, + qgenericFieldInfo, + isValidityData, + nicList, + isManual + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => { - return { - onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, - qName: COMPONENTS_QUESTIONNAIRE}), - onAddNic: () => NICCreationActionHelper.open(dispatch, {softwareProductId, componentId, modalClassName: 'network-nic-modal-create', version}), - onDeleteNic: (nic) => dispatch({ - type: GlobalModalActions.GLOBAL_MODAL_WARNING, - data:{ - msg: i18n('Are you sure you want to delete "{name}"?', {name: nic.name}), - onConfirmed: () => SoftwareProductComponentsNetworkActionHelper.deleteNIC(dispatch, {softwareProductId, - componentId, nicId: nic.id, version}) - } - }), - onEditNicClick: (nic, isReadOnlyMode) => { - Promise.all([ - SoftwareProductComponentsNetworkActionHelper.loadNICData({ - softwareProductId, - version, - componentId, - nicId: nic.id - }), - SoftwareProductComponentsNetworkActionHelper.loadNICQuestionnaire(dispatch, { - softwareProductId, - version, - componentId, - nicId: nic.id - }) - ]).then( - ([{data}]) => SoftwareProductComponentsNetworkActionHelper.openNICEditor(dispatch, {nic, data, - isReadOnlyMode, softwareProductId, componentId, modalClassName: 'network-nic-modal-edit', version}) - ); - }, - onSubmit: ({qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, - {softwareProductId, version, - vspComponentId: componentId, - qdata}); - } - - - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, componentId, version } +) => { + return { + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: COMPONENTS_QUESTIONNAIRE + }), + onAddNic: () => + NICCreationActionHelper.open(dispatch, { + softwareProductId, + componentId, + modalClassName: 'network-nic-modal-create', + version + }), + onDeleteNic: nic => + dispatch({ + type: GlobalModalActions.GLOBAL_MODAL_WARNING, + data: { + msg: i18n('Are you sure you want to delete "{name}"?', { + name: nic.name + }), + onConfirmed: () => + SoftwareProductComponentsNetworkActionHelper.deleteNIC( + dispatch, + { + softwareProductId, + componentId, + nicId: nic.id, + version + } + ) + } + }), + onEditNicClick: (nic, isReadOnlyMode) => { + Promise.all([ + SoftwareProductComponentsNetworkActionHelper.loadNICData({ + softwareProductId, + version, + componentId, + nicId: nic.id + }), + SoftwareProductComponentsNetworkActionHelper.loadNICQuestionnaire( + dispatch, + { + softwareProductId, + version, + componentId, + nicId: nic.id + } + ) + ]).then(([{ data }]) => + SoftwareProductComponentsNetworkActionHelper.openNICEditor( + dispatch, + { + nic, + data, + isReadOnlyMode, + softwareProductId, + componentId, + modalClassName: 'network-nic-modal-edit', + version + } + ) + ); + }, + onSubmit: ({ qdata }) => { + return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire( + dispatch, + { + softwareProductId, + version, + vspComponentId: componentId, + qdata + } + ); + } + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsNetworkListView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductComponentsNetworkListView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx index 4d460c722d..c631fb24c3 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx @@ -20,138 +20,203 @@ import Form from 'nfvo-components/input/validation/Form.jsx'; import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx'; import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx'; -import Input from'nfvo-components/input/validation/Input.jsx'; - +import Input from 'nfvo-components/input/validation/Input.jsx'; class SoftwareProductComponentsNetworkView extends React.Component { + state = { + localFilter: '' + }; - state = { - localFilter: '' - }; - - render() { - let {dataMap, qgenericFieldInfo, onQDataChanged, isReadOnlyMode} = this.props; - - return( - <div className='vsp-components-network'> - <div className='network-data'> - <div> -{ qgenericFieldInfo && <Form - formReady={null} - isValid={true} - onSubmit={() => this.save()} - isReadOnlyMode={isReadOnlyMode} - hasButtons={false}> - <h3 className='section-title'>{i18n('Network Capacity')}</h3> - <div className='rows-section'> - <div className='row-flex-components'> - <div className='single-col'> - <Input - data-test-id='protocolWithHighestTrafficProfileAcrossAllNICs' - label={i18n('Protocol with Highest Traffic Profile across all NICs')} - type='select' - groupClassName='bootstrap-input-options' - className='input-options-select' - isValid={qgenericFieldInfo['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'].isValid} - errorText={qgenericFieldInfo['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'].errorText} - value={dataMap['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs' : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - { qgenericFieldInfo['network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'].enum.map(proto => - <option value={proto.enum} key={proto.enum}>{proto.title}</option>) } - </Input> - </div> - <div className='single-col add-line-break'> - <Input - data-test-id='networkTransactionsPerSecond' - label={i18n('Network Transactions per Second')} - type='number' - onChange={(ntps) => onQDataChanged({'network/networkCapacity/networkTransactionsPerSecond' : ntps})} - isValid={qgenericFieldInfo['network/networkCapacity/networkTransactionsPerSecond'].isValid} - errorText={qgenericFieldInfo['network/networkCapacity/networkTransactionsPerSecond'].errorText} - value={dataMap['network/networkCapacity/networkTransactionsPerSecond']} /> - </div> - <div className='empty-two-col' /> - </div> - </div> - - </Form> } - </div> - {this.renderNicList()} - </div> - - </div> - ); - } - - renderNicList() { - const {localFilter} = this.state; - let {isReadOnlyMode, onAddNic, isManual} = this.props; - return ( - <ListEditorView - title={i18n('Interfaces')} - filterValue={localFilter} - placeholder={i18n('Filter NICs by Name')} - isReadOnlyMode={isReadOnlyMode} - onFilter={value => this.setState({localFilter: value})} - onAdd={isManual ? onAddNic : null} - plusButtonTitle={i18n('Add NIC')} - twoColumns> - {this.filterList().map(nic => this.renderNicListItem(nic, isReadOnlyMode))} - </ListEditorView> - ); - } + render() { + let { + dataMap, + qgenericFieldInfo, + onQDataChanged, + isReadOnlyMode + } = this.props; - renderNicListItem(nic, isReadOnlyMode) { - let {id, name, description, networkName = ''} = nic; - let {onEditNicClick, version, isManual, onDeleteNic} = this.props; - return ( - <ListEditorItemView - key={id} - isReadOnlyMode={isReadOnlyMode} - onSelect={() => onEditNicClick(nic, version, isReadOnlyMode)} - onDelete={isManual ? () => onDeleteNic(nic, version) : null}> + return ( + <div className="vsp-components-network"> + <div className="network-data"> + <div> + {qgenericFieldInfo && ( + <Form + formReady={null} + isValid={true} + onSubmit={() => this.save()} + isReadOnlyMode={isReadOnlyMode} + hasButtons={false}> + <h3 className="section-title"> + {i18n('Network Capacity')} + </h3> + <div className="rows-section"> + <div className="row-flex-components"> + <div className="single-col"> + <Input + data-test-id="protocolWithHighestTrafficProfileAcrossAllNICs" + label={i18n( + 'Protocol with Highest Traffic Profile across all NICs' + )} + type="select" + groupClassName="bootstrap-input-options" + className="input-options-select" + isValid={ + qgenericFieldInfo[ + 'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs' + ].errorText + } + value={ + dataMap[ + 'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs' + ] + } + onChange={e => { + const selectedIndex = + e.target.selectedIndex; + const val = + e.target.options[ + selectedIndex + ].value; + onQDataChanged({ + 'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs': val + }); + }}> + <option + key="placeholder" + value=""> + {i18n('Select...')} + </option> + {qgenericFieldInfo[ + 'network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs' + ].enum.map(proto => ( + <option + value={proto.enum} + key={proto.enum}> + {proto.title} + </option> + ))} + </Input> + </div> + <div className="single-col add-line-break"> + <Input + data-test-id="networkTransactionsPerSecond" + label={i18n( + 'Network Transactions per Second' + )} + type="number" + onChange={ntps => + onQDataChanged({ + 'network/networkCapacity/networkTransactionsPerSecond': ntps + }) + } + isValid={ + qgenericFieldInfo[ + 'network/networkCapacity/networkTransactionsPerSecond' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'network/networkCapacity/networkTransactionsPerSecond' + ].errorText + } + value={ + dataMap[ + 'network/networkCapacity/networkTransactionsPerSecond' + ] + } + /> + </div> + <div className="empty-two-col" /> + </div> + </div> + </Form> + )} + </div> + {this.renderNicList()} + </div> + </div> + ); + } - <ListEditorItemViewField> - <div className='name'>{name}</div> - </ListEditorItemViewField> - <ListEditorItemViewField> - <div className={isManual ? 'details-col' : 'details'}> - <div className={isManual ? 'manual-title' : 'title'}>{i18n('Purpose of NIC')}</div> - {description && <div className={isManual ? 'description' : ''}>{description}</div>} - </div> - {!isManual && <div className='details'> - <div className='title'>{i18n('Network')}</div> - <div className='artifact-name'>{networkName}</div> - </div>} - </ListEditorItemViewField> + renderNicList() { + const { localFilter } = this.state; + let { isReadOnlyMode, onAddNic, isManual } = this.props; + return ( + <ListEditorView + title={i18n('Interfaces')} + filterValue={localFilter} + placeholder={i18n('Filter NICs by Name')} + isReadOnlyMode={isReadOnlyMode} + onFilter={value => this.setState({ localFilter: value })} + onAdd={isManual ? onAddNic : null} + plusButtonTitle={i18n('Add NIC')} + twoColumns> + {this.filterList().map(nic => + this.renderNicListItem(nic, isReadOnlyMode) + )} + </ListEditorView> + ); + } - </ListEditorItemView> - ); - } + renderNicListItem(nic, isReadOnlyMode) { + let { id, name, description, networkName = '' } = nic; + let { onEditNicClick, version, isManual, onDeleteNic } = this.props; + return ( + <ListEditorItemView + key={id} + isReadOnlyMode={isReadOnlyMode} + onSelect={() => onEditNicClick(nic, version, isReadOnlyMode)} + onDelete={isManual ? () => onDeleteNic(nic, version) : null}> + <ListEditorItemViewField> + <div className="name">{name}</div> + </ListEditorItemViewField> + <ListEditorItemViewField> + <div className={isManual ? 'details-col' : 'details'}> + <div className={isManual ? 'manual-title' : 'title'}> + {i18n('Purpose of NIC')} + </div> + {description && ( + <div className={isManual ? 'description' : ''}> + {description} + </div> + )} + </div> + {!isManual && ( + <div className="details"> + <div className="title">{i18n('Network')}</div> + <div className="artifact-name">{networkName}</div> + </div> + )} + </ListEditorItemViewField> + </ListEditorItemView> + ); + } - filterList() { - let {nicList} = this.props; - let {localFilter} = this.state; - if (localFilter.trim()) { - const filter = new RegExp(escape(localFilter), 'i'); - return nicList.filter(({name = '', description = ''}) => { - return escape(name).match(filter) || escape(description).match(filter); - }); - } - else { - return nicList; - } - } + filterList() { + let { nicList } = this.props; + let { localFilter } = this.state; + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return nicList.filter(({ name = '', description = '' }) => { + return ( + escape(name).match(filter) || + escape(description).match(filter) + ); + }); + } else { + return nicList; + } + } - save() { - let {onSubmit, qdata, version} = this.props; - return onSubmit({qdata, version}); - } + save() { + let { onSubmit, qdata, version } = this.props; + return onSubmit({ qdata, version }); + } } export default SoftwareProductComponentsNetworkView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Acceptable.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Acceptable.jsx index 0fc7404c56..0b2783ebe7 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Acceptable.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Acceptable.jsx @@ -19,57 +19,97 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const Acceptable = ({qgenericFieldInfo, dataMap, onQDataChanged}) => { - return( - <GridSection hasLastColSet> - <GridItem colSpan={3}> - <div className='part-title-small packets'>{i18n('Acceptable Jitter')}</div> - </GridItem> - <GridItem lastColInRow> - <div className='part-title-small bytes'>{i18n('Allow Packet Loss')}</div> - </GridItem> - <GridItem> - <Input - label={i18n('Mean')} - type='number' - data-test-id='acceptableJitter-mean' - isValid={qgenericFieldInfo['sizing/acceptableJitter/mean'].isValid} - errorText={qgenericFieldInfo['sizing/acceptableJitter/mean'].errorText} - value={dataMap['sizing/acceptableJitter/mean']} - onChange={val => onQDataChanged({'sizing/acceptableJitter/mean' : val})} /> - </GridItem> - <GridItem> - <Input - label={i18n('Max')} - type='number' - data-test-id='acceptableJitter-max' - isValid={qgenericFieldInfo['sizing/acceptableJitter/max'].isValid} - errorText={qgenericFieldInfo['sizing/acceptableJitter/max'].errorText} - value={dataMap['sizing/acceptableJitter/max']} - onChange={val => onQDataChanged({'sizing/acceptableJitter/max' : val})} /> - </GridItem> - <GridItem> - <Input - label={i18n('Var')} - type='number' - data-test-id='acceptableJitter-variable' - isValid={qgenericFieldInfo['sizing/acceptableJitter/variable'].isValid} - errorText={qgenericFieldInfo['sizing/acceptableJitter/variable'].errorText} - value={dataMap['sizing/acceptableJitter/variable']} - onChange={val => onQDataChanged({'sizing/acceptableJitter/variable' : val})} /> - </GridItem> - <GridItem lastColInRow> - <Input - label={i18n('In Percent')} - type='number' - data-test-id='acceptableJitter-acceptablePacketLoss' - isValid={qgenericFieldInfo['sizing/acceptablePacketLoss'].isValid} - errorText={qgenericFieldInfo['sizing/acceptablePacketLoss'].errorText} - value={dataMap['sizing/acceptablePacketLoss']} - onChange={val => onQDataChanged({'sizing/acceptablePacketLoss' : val})} /> - </GridItem> - </GridSection> - ); +const Acceptable = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => { + return ( + <GridSection hasLastColSet> + <GridItem colSpan={3}> + <div className="part-title-small packets"> + {i18n('Acceptable Jitter')} + </div> + </GridItem> + <GridItem lastColInRow> + <div className="part-title-small bytes"> + {i18n('Allow Packet Loss')} + </div> + </GridItem> + <GridItem> + <Input + label={i18n('Mean')} + type="number" + data-test-id="acceptableJitter-mean" + isValid={ + qgenericFieldInfo['sizing/acceptableJitter/mean'] + .isValid + } + errorText={ + qgenericFieldInfo['sizing/acceptableJitter/mean'] + .errorText + } + value={dataMap['sizing/acceptableJitter/mean']} + onChange={val => + onQDataChanged({ 'sizing/acceptableJitter/mean': val }) + } + /> + </GridItem> + <GridItem> + <Input + label={i18n('Max')} + type="number" + data-test-id="acceptableJitter-max" + isValid={ + qgenericFieldInfo['sizing/acceptableJitter/max'].isValid + } + errorText={ + qgenericFieldInfo['sizing/acceptableJitter/max'] + .errorText + } + value={dataMap['sizing/acceptableJitter/max']} + onChange={val => + onQDataChanged({ 'sizing/acceptableJitter/max': val }) + } + /> + </GridItem> + <GridItem> + <Input + label={i18n('Var')} + type="number" + data-test-id="acceptableJitter-variable" + isValid={ + qgenericFieldInfo['sizing/acceptableJitter/variable'] + .isValid + } + errorText={ + qgenericFieldInfo['sizing/acceptableJitter/variable'] + .errorText + } + value={dataMap['sizing/acceptableJitter/variable']} + onChange={val => + onQDataChanged({ + 'sizing/acceptableJitter/variable': val + }) + } + /> + </GridItem> + <GridItem lastColInRow> + <Input + label={i18n('In Percent')} + type="number" + data-test-id="acceptableJitter-acceptablePacketLoss" + isValid={ + qgenericFieldInfo['sizing/acceptablePacketLoss'].isValid + } + errorText={ + qgenericFieldInfo['sizing/acceptablePacketLoss'] + .errorText + } + value={dataMap['sizing/acceptablePacketLoss']} + onChange={val => + onQDataChanged({ 'sizing/acceptablePacketLoss': val }) + } + /> + </GridItem> + </GridSection> + ); }; export default Acceptable; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/FlowLength.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/FlowLength.jsx index 3745fc7c2e..32a5516eb4 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/FlowLength.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/FlowLength.jsx @@ -18,18 +18,20 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import PacketsBytes from './PacketsBytes.jsx'; const pointers = [ - {label: 'Peak', value: 'sizing/flowLength/packets/peak'}, - {label: 'Avg', value: 'sizing/flowLength/packets/avg'}, - {label: 'Peak', value: 'sizing/flowLength/bytes/peak'}, - {label: 'Avg', value: 'sizing/flowLength/bytes/avg'}, + { label: 'Peak', value: 'sizing/flowLength/packets/peak' }, + { label: 'Avg', value: 'sizing/flowLength/packets/avg' }, + { label: 'Peak', value: 'sizing/flowLength/bytes/peak' }, + { label: 'Avg', value: 'sizing/flowLength/bytes/avg' } ]; -const FlowLength = (props) => { - return( - <PacketsBytes {...props} title={i18n('Flow Length')} pointers={pointers}/> - ); +const FlowLength = props => { + return ( + <PacketsBytes + {...props} + title={i18n('Flow Length')} + pointers={pointers} + /> + ); }; export default FlowLength; - - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/InFlowTraffic.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/InFlowTraffic.jsx index 5476ed90e6..150e58af52 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/InFlowTraffic.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/InFlowTraffic.jsx @@ -18,18 +18,20 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import PacketsBytes from './PacketsBytes.jsx'; const pointers = [ - {label: 'Peak', value: 'sizing/inflowTrafficPerSecond/packets/peak'}, - {label: 'Avg', value: 'sizing/inflowTrafficPerSecond/packets/avg'}, - {label: 'Peak', value: 'sizing/inflowTrafficPerSecond/bytes/peak'}, - {label: 'Avg', value: 'sizing/inflowTrafficPerSecond/bytes/avg'}, + { label: 'Peak', value: 'sizing/inflowTrafficPerSecond/packets/peak' }, + { label: 'Avg', value: 'sizing/inflowTrafficPerSecond/packets/avg' }, + { label: 'Peak', value: 'sizing/inflowTrafficPerSecond/bytes/peak' }, + { label: 'Avg', value: 'sizing/inflowTrafficPerSecond/bytes/avg' } ]; -const InFlowTraffic = (props) => { - return( - <PacketsBytes {...props} title={i18n('Inflow Traffic per second')} pointers={pointers}/> - ); +const InFlowTraffic = props => { + return ( + <PacketsBytes + {...props} + title={i18n('Inflow Traffic per second')} + pointers={pointers} + /> + ); }; export default InFlowTraffic; - - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/IpConfig.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/IpConfig.jsx index b3a5d21625..695835606b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/IpConfig.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/IpConfig.jsx @@ -19,27 +19,37 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const IpConfig = ({dataMap, onQDataChanged}) => { - return ( - <GridSection title={i18n('IP Configuration')}> - <GridItem> - <Input - label={i18n('IPv4 Required')} - type='checkbox' - onChange={value => onQDataChanged({'ipConfiguration/ipv4Required' : value})} - data-test-id='ipConfiguration-ipv4Required' - value={dataMap['ipConfiguration/ipv4Required']} /> - </GridItem> - <GridItem> - <Input - label={i18n('IPv6 Required')} - type='checkbox' - data-test-id='ipConfiguration-ipv6Required' - onChange={value => onQDataChanged({'ipConfiguration/ipv6Required' : value})} - value={dataMap['ipConfiguration/ipv6Required']} /> - </GridItem> - </GridSection> - ); +const IpConfig = ({ dataMap, onQDataChanged }) => { + return ( + <GridSection title={i18n('IP Configuration')}> + <GridItem> + <Input + label={i18n('IPv4 Required')} + type="checkbox" + onChange={value => + onQDataChanged({ + 'ipConfiguration/ipv4Required': value + }) + } + data-test-id="ipConfiguration-ipv4Required" + value={dataMap['ipConfiguration/ipv4Required']} + /> + </GridItem> + <GridItem> + <Input + label={i18n('IPv6 Required')} + type="checkbox" + data-test-id="ipConfiguration-ipv6Required" + onChange={value => + onQDataChanged({ + 'ipConfiguration/ipv6Required': value + }) + } + value={dataMap['ipConfiguration/ipv6Required']} + /> + </GridItem> + </GridSection> + ); }; export default IpConfig; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx index 06a2bb445c..5a89239dc6 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx @@ -20,40 +20,48 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const NameAndPurpose = ({onDataChanged, genericFieldInfo, isReadOnlyMode, name, description, isManual}) => { - - return ( - <GridSection hastLastColSet> - <GridItem colSpan={2}> - <Input - label={i18n('Name')} - value={name} - data-test-id='nic-name' - disabled={!isManual} - isRequired={true} - onChange={name => onDataChanged({name})} - isValid={genericFieldInfo['name'].isValid} - errorText={genericFieldInfo['name'].errorText} - type='text' /> - </GridItem> - <GridItem colSpan={2} lastColInRow> - <Input - label={i18n('Purpose of NIC')} - value={description} - data-test-id='nic-description' - onChange={description => onDataChanged({description})} - disabled={isReadOnlyMode} - type='textarea' /> - </GridItem> - </GridSection> - ); +const NameAndPurpose = ({ + onDataChanged, + genericFieldInfo, + isReadOnlyMode, + name, + description, + isManual +}) => { + return ( + <GridSection hastLastColSet> + <GridItem colSpan={2}> + <Input + label={i18n('Name')} + value={name} + data-test-id="nic-name" + disabled={!isManual} + isRequired={true} + onChange={name => onDataChanged({ name })} + isValid={genericFieldInfo['name'].isValid} + errorText={genericFieldInfo['name'].errorText} + type="text" + /> + </GridItem> + <GridItem colSpan={2} lastColInRow> + <Input + label={i18n('Purpose of NIC')} + value={description} + data-test-id="nic-description" + onChange={description => onDataChanged({ description })} + disabled={isReadOnlyMode} + type="textarea" + /> + </GridItem> + </GridSection> + ); }; NameAndPurpose.PropTypes = { - name: PropTypes.string, - description: PropTypes.array, - onDataChanged: PropTypes.func, - isReadOnlyMode: PropTypes.bool, + name: PropTypes.string, + description: PropTypes.array, + onDataChanged: PropTypes.func, + isReadOnlyMode: PropTypes.bool }; export default NameAndPurpose; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx index 7e6712cb5e..c440d2fbd3 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx @@ -21,56 +21,70 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; import { networkTypes } from '../SoftwareProductComponentsNetworkConstants.js'; -const Network = ({networkValues, networkType, networkDescription, onDataChanged, isReadOnlyMode}) => { - const isExternal = networkType === networkTypes.EXTERNAL; - return ( - <GridSection title={i18n('Network')} hasLastColSet> - <GridItem> - <Input - label={i18n('Internal')} - disabled - checked={!isExternal} - data-test-id='nic-internal' - className='network-radio disabled' - type='radio' /> - </GridItem> - <GridItem> - <Input - label={i18n('External')} - disabled - checked={isExternal} - data-test-id='nic-external' - className='network-radio disabled' - type='radio' /> - </GridItem> - <GridItem colSpan={2} lastColInRow> - { - isExternal ? - <Input - label={i18n('Network Description')} - value={networkDescription} - data-test-id='nic-network-description' - onChange={networkDescription => onDataChanged({networkDescription})} - disabled={isReadOnlyMode} - type='text' /> - : - <Input - label={i18n('Network')} - data-test-id='nic-network' - type='select' - className='input-options-select' - groupClassName='bootstrap-input-options' - disabled={true}> - {networkValues.map(val => <option key={val.enum} value={val.enum}>{val.title}</option>)} - </Input> - } - </GridItem> - </GridSection> - ); +const Network = ({ + networkValues, + networkType, + networkDescription, + onDataChanged, + isReadOnlyMode +}) => { + const isExternal = networkType === networkTypes.EXTERNAL; + return ( + <GridSection title={i18n('Network')} hasLastColSet> + <GridItem> + <Input + label={i18n('Internal')} + disabled + checked={!isExternal} + data-test-id="nic-internal" + className="network-radio disabled" + type="radio" + /> + </GridItem> + <GridItem> + <Input + label={i18n('External')} + disabled + checked={isExternal} + data-test-id="nic-external" + className="network-radio disabled" + type="radio" + /> + </GridItem> + <GridItem colSpan={2} lastColInRow> + {isExternal ? ( + <Input + label={i18n('Network Description')} + value={networkDescription} + data-test-id="nic-network-description" + onChange={networkDescription => + onDataChanged({ networkDescription }) + } + disabled={isReadOnlyMode} + type="text" + /> + ) : ( + <Input + label={i18n('Network')} + data-test-id="nic-network" + type="select" + className="input-options-select" + groupClassName="bootstrap-input-options" + disabled={true}> + {networkValues.map(val => ( + <option key={val.enum} value={val.enum}> + {val.title} + </option> + ))} + </Input> + )} + </GridItem> + </GridSection> + ); }; Network.PropTypes = { - networkValues: PropTypes.array + networkValues: PropTypes.array }; -export default Network; +export default Network; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/OutFlowTraffic.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/OutFlowTraffic.jsx index 80a3d1579b..7173294536 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/OutFlowTraffic.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/OutFlowTraffic.jsx @@ -18,18 +18,20 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import PacketsBytes from './PacketsBytes.jsx'; const pointers = [ - {label: 'Peak', value: 'sizing/outflowTrafficPerSecond/packets/peak'}, - {label: 'Avg', value: 'sizing/outflowTrafficPerSecond/packets/avg'}, - {label: 'Peak', value: 'sizing/outflowTrafficPerSecond/bytes/peak'}, - {label: 'Avg', value: 'sizing/outflowTrafficPerSecond/bytes/avg'}, + { label: 'Peak', value: 'sizing/outflowTrafficPerSecond/packets/peak' }, + { label: 'Avg', value: 'sizing/outflowTrafficPerSecond/packets/avg' }, + { label: 'Peak', value: 'sizing/outflowTrafficPerSecond/bytes/peak' }, + { label: 'Avg', value: 'sizing/outflowTrafficPerSecond/bytes/avg' } ]; -const OutFlowTraffic = (props) => { - return( - <PacketsBytes {...props} title={i18n('Outflow Traffic per second')} pointers={pointers}/> - ); +const OutFlowTraffic = props => { + return ( + <PacketsBytes + {...props} + title={i18n('Outflow Traffic per second')} + pointers={pointers} + /> + ); }; export default OutFlowTraffic; - - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/PacketsBytes.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/PacketsBytes.jsx index f5f28aea59..070ac816ad 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/PacketsBytes.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/PacketsBytes.jsx @@ -20,47 +20,74 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const PointerInput = ({label, value, onQDataChanged, qgenericFieldInfo, dataMap, lastColInRow}) => { - return ( - <GridItem lastColInRow={lastColInRow}> - <Input - label={i18n(label)} - type='number' - data-test-id={`${value}`} - isValid={qgenericFieldInfo[value].isValid} - errorText={qgenericFieldInfo[value].errorText} - value={dataMap[value]} - onChange={val => onQDataChanged({[value]: val})} /> - </GridItem> - ); +const PointerInput = ({ + label, + value, + onQDataChanged, + qgenericFieldInfo, + dataMap, + lastColInRow +}) => { + return ( + <GridItem lastColInRow={lastColInRow}> + <Input + label={i18n(label)} + type="number" + data-test-id={`${value}`} + isValid={qgenericFieldInfo[value].isValid} + errorText={qgenericFieldInfo[value].errorText} + value={dataMap[value]} + onChange={val => onQDataChanged({ [value]: val })} + /> + </GridItem> + ); }; PointerInput.PropTypes = { - label: PropTypes.string, - value: PropTypes.string + label: PropTypes.string, + value: PropTypes.string }; -const PacketsBytes = ({title, pointers = [], qgenericFieldInfo, dataMap, onQDataChanged}) => { - return( - <GridSection title={title} hasLastColSet> - <GridItem colSpan={2}> - <div className='part-title-small packets'>{i18n('Packets')}</div> - </GridItem> - <GridItem colSpan={2} lastColInRow> - <div className='part-title-small bytes'>{i18n('Bytes')}</div> - </GridItem> - {pointers.map((pointer, i) => {return (<PointerInput key={i} label={pointer.label} value={pointer.value} - qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged} dataMap={dataMap} lastColInRow={i === 3} />);})} - </GridSection> - ); +const PacketsBytes = ({ + title, + pointers = [], + qgenericFieldInfo, + dataMap, + onQDataChanged +}) => { + return ( + <GridSection title={title} hasLastColSet> + <GridItem colSpan={2}> + <div className="part-title-small packets"> + {i18n('Packets')} + </div> + </GridItem> + <GridItem colSpan={2} lastColInRow> + <div className="part-title-small bytes">{i18n('Bytes')}</div> + </GridItem> + {pointers.map((pointer, i) => { + return ( + <PointerInput + key={i} + label={pointer.label} + value={pointer.value} + qgenericFieldInfo={qgenericFieldInfo} + onQDataChanged={onQDataChanged} + dataMap={dataMap} + lastColInRow={i === 3} + /> + ); + })} + </GridSection> + ); }; PacketsBytes.PropTypes = { - title: PropTypes.string, - pointers: PropTypes.array, - onQDataChanged: PropTypes.function, - dataMap: PropTypes.object, - qgenericFieldInfo: PropTypes.object + title: PropTypes.string, + pointers: PropTypes.array, + onQDataChanged: PropTypes.function, + dataMap: PropTypes.object, + qgenericFieldInfo: PropTypes.object }; export default PacketsBytes; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Protocols.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Protocols.jsx index be4093da59..eb762b11b2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Protocols.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Protocols.jsx @@ -21,55 +21,83 @@ import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const Protocols = ({protocols, qgenericFieldInfo, dataMap, onQDataChanged}) => { - return ( - <GridSection title={i18n('Protocols')} hasLastColSet> - <GridItem colSpan={2}> - <InputOptions - data-test-id='nic-protocols' - label={i18n('Protocols')} - type='select' - isMultiSelect={true} - isValid={qgenericFieldInfo['protocols/protocols'].isValid} - errorText={qgenericFieldInfo['protocols/protocols'].errorText} - onInputChange={()=>{}} - onEnumChange={protocols => { - onQDataChanged({'protocols/protocols' : protocols});} - } - multiSelectedEnum={dataMap['protocols/protocols']} - clearable={false} - values={qgenericFieldInfo['protocols/protocols'].enum}/> - </GridItem> - <GridItem colSpan={2} lastColInRow> - <Input - data-test-id='nic-protocolWithHighestTrafficProfile' - label={i18n('Protocol with Highest Traffic Profile')} - type='select' - groupClassName='bootstrap-input-options' - className='input-options-select' - isValid={qgenericFieldInfo['protocols/protocolWithHighestTrafficProfile'].isValid} - errorText={qgenericFieldInfo['protocols/protocolWithHighestTrafficProfile'].errorText} - value={dataMap['protocols/protocolWithHighestTrafficProfile']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'protocols/protocolWithHighestTrafficProfile' : val});} - }> - {(protocols.length === 0) && - <option key={'You must select protocols first...'} value=''>{i18n('You must select protocols first...')}</option> - } - {protocols.map(protocol => <option key={protocol} value={protocol}>{protocol}</option>)} - </Input> - </GridItem> - </GridSection> - ); +const Protocols = ({ + protocols, + qgenericFieldInfo, + dataMap, + onQDataChanged +}) => { + return ( + <GridSection title={i18n('Protocols')} hasLastColSet> + <GridItem colSpan={2}> + <InputOptions + data-test-id="nic-protocols" + label={i18n('Protocols')} + type="select" + isMultiSelect={true} + isValid={qgenericFieldInfo['protocols/protocols'].isValid} + errorText={ + qgenericFieldInfo['protocols/protocols'].errorText + } + onInputChange={() => {}} + onEnumChange={protocols => { + onQDataChanged({ 'protocols/protocols': protocols }); + }} + multiSelectedEnum={dataMap['protocols/protocols']} + clearable={false} + values={qgenericFieldInfo['protocols/protocols'].enum} + /> + </GridItem> + <GridItem colSpan={2} lastColInRow> + <Input + data-test-id="nic-protocolWithHighestTrafficProfile" + label={i18n('Protocol with Highest Traffic Profile')} + type="select" + groupClassName="bootstrap-input-options" + className="input-options-select" + isValid={ + qgenericFieldInfo[ + 'protocols/protocolWithHighestTrafficProfile' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'protocols/protocolWithHighestTrafficProfile' + ].errorText + } + value={ + dataMap['protocols/protocolWithHighestTrafficProfile'] + } + onChange={e => { + const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onQDataChanged({ + 'protocols/protocolWithHighestTrafficProfile': val + }); + }}> + {protocols.length === 0 && ( + <option + key={'You must select protocols first...'} + value=""> + {i18n('You must select protocols first...')} + </option> + )} + {protocols.map(protocol => ( + <option key={protocol} value={protocol}> + {protocol} + </option> + ))} + </Input> + </GridItem> + </GridSection> + ); }; Protocols.PropTypes = { - protocols: PropTypes.array, - onQDataChanged: PropTypes.function, - dataMap: PropTypes.object, - qgenericFieldInfo: PropTypes.object + protocols: PropTypes.array, + onQDataChanged: PropTypes.function, + dataMap: PropTypes.object, + qgenericFieldInfo: PropTypes.object }; export default Protocols; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Sizing.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Sizing.jsx index 202d458f25..f9ec7261ac 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Sizing.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Sizing.jsx @@ -19,21 +19,32 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; -const Sizing = ({qgenericFieldInfo, dataMap, onQDataChanged}) => { - return( - <GridSection title={i18n('Sizing')} hasLastColSet> - <GridItem colSpan={4} lastColInRow> - <Input - label={i18n('Describe Quality of Service')} - type='textarea' - data-test-id='sizing-describeQualityOfService' - isValid={qgenericFieldInfo['sizing/describeQualityOfService'].isValid} - errorText={qgenericFieldInfo['sizing/describeQualityOfService'].errorText} - value={dataMap['sizing/describeQualityOfService']} - onChange={val => onQDataChanged({'sizing/describeQualityOfService' : val}) }/> - </GridItem> - </GridSection> - ); +const Sizing = ({ qgenericFieldInfo, dataMap, onQDataChanged }) => { + return ( + <GridSection title={i18n('Sizing')} hasLastColSet> + <GridItem colSpan={4} lastColInRow> + <Input + label={i18n('Describe Quality of Service')} + type="textarea" + data-test-id="sizing-describeQualityOfService" + isValid={ + qgenericFieldInfo['sizing/describeQualityOfService'] + .isValid + } + errorText={ + qgenericFieldInfo['sizing/describeQualityOfService'] + .errorText + } + value={dataMap['sizing/describeQualityOfService']} + onChange={val => + onQDataChanged({ + 'sizing/describeQualityOfService': val + }) + } + /> + </GridItem> + </GridSection> + ); }; export default Sizing; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesActionHelper.js index b2133ad5d8..52c5cdde3d 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesActionHelper.js @@ -15,121 +15,184 @@ */ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; -import {actionTypes} from './SoftwareProductComponentProcessesConstants.js'; +import { actionTypes } from './SoftwareProductComponentProcessesConstants.js'; function baseUrl(softwareProductId, version, componentId) { - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${version.id}/components/${componentId}/processes`; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${ + version.id + }/components/${componentId}/processes`; } -function fetchProcessesList({softwareProductId, version, componentId}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`); +function fetchProcessesList({ softwareProductId, version, componentId }) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version, componentId)}` + ); } -function deleteProcess({softwareProductId, version, componentId, processId}) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${processId}`); +function deleteProcess({ softwareProductId, version, componentId, processId }) { + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version, componentId)}/${processId}` + ); } -function putProcess({softwareProductId, version, componentId, process}) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${process.id}`, { - name: process.name, - description: process.description, - type: process.type === '' ? null : process.type - }); +function putProcess({ softwareProductId, version, componentId, process }) { + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version, componentId)}/${process.id}`, + { + name: process.name, + description: process.description, + type: process.type === '' ? null : process.type + } + ); } -function postProcess({softwareProductId, version, componentId, process}) { - return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}`, { - name: process.name, - description: process.description, - type: process.type === '' ? null : process.type - }); +function postProcess({ softwareProductId, version, componentId, process }) { + return RestAPIUtil.post( + `${baseUrl(softwareProductId, version, componentId)}`, + { + name: process.name, + description: process.description, + type: process.type === '' ? null : process.type + } + ); } -function uploadFileToProcess({softwareProductId, version, processId, componentId, formData}) { - return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}/${processId}/upload`, formData); +function uploadFileToProcess({ + softwareProductId, + version, + processId, + componentId, + formData +}) { + return RestAPIUtil.post( + `${baseUrl( + softwareProductId, + version, + componentId + )}/${processId}/upload`, + formData + ); } - - const SoftwareProductComponentProcessesActionHelper = { - fetchProcessesList(dispatch, {softwareProductId, version, componentId}) { - dispatch({ - type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES, - processesList: [] - }); - - return fetchProcessesList({softwareProductId, version, componentId}).then(response => { - dispatch({ - type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES, - processesList: response.results - }); - }); - }, - - deleteProcess(dispatch, {process, softwareProductId, version, componentId}) { - return deleteProcess({softwareProductId, version, processId:process.id, componentId}).then(() => { - dispatch({ - type: actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS, - processId: process.id - }); - }); - - }, - - saveProcess(dispatch, {softwareProductId, version, componentId, previousProcess, process}) { - if (previousProcess) { - return putProcess({softwareProductId, version, componentId, process}).then(() => { - if (process.formData && process.formData.name !== previousProcess.artifactName){ - uploadFileToProcess({softwareProductId, version, processId: process.id, formData: process.formData, componentId}); - } - dispatch({ - type: actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS, - process - }); - }); - } - else { - return postProcess({softwareProductId, version, componentId, process}).then(response => { - if (process.formData) { - uploadFileToProcess({softwareProductId, version, processId: response.value, formData: process.formData, componentId}); - } - dispatch({ - type: actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS, - process: { - ...process, - id: response.value - } - }); - }); - } - }, - - hideDeleteConfirm(dispatch) { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM, - processToDelete: false - }); - }, - - openDeleteProcessesConfirm(dispatch, {process} ) { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM, - processToDelete: process - }); - }, - - openEditor(dispatch, process = {}) { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN, - process - }); - }, - closeEditor(dispatch) { - dispatch({ - type:actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE - }); - } + fetchProcessesList(dispatch, { softwareProductId, version, componentId }) { + dispatch({ + type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES, + processesList: [] + }); + + return fetchProcessesList({ + softwareProductId, + version, + componentId + }).then(response => { + dispatch({ + type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES, + processesList: response.results + }); + }); + }, + + deleteProcess( + dispatch, + { process, softwareProductId, version, componentId } + ) { + return deleteProcess({ + softwareProductId, + version, + processId: process.id, + componentId + }).then(() => { + dispatch({ + type: actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS, + processId: process.id + }); + }); + }, + + saveProcess( + dispatch, + { softwareProductId, version, componentId, previousProcess, process } + ) { + if (previousProcess) { + return putProcess({ + softwareProductId, + version, + componentId, + process + }).then(() => { + if ( + process.formData && + process.formData.name !== previousProcess.artifactName + ) { + uploadFileToProcess({ + softwareProductId, + version, + processId: process.id, + formData: process.formData, + componentId + }); + } + dispatch({ + type: actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS, + process + }); + }); + } else { + return postProcess({ + softwareProductId, + version, + componentId, + process + }).then(response => { + if (process.formData) { + uploadFileToProcess({ + softwareProductId, + version, + processId: response.value, + formData: process.formData, + componentId + }); + } + dispatch({ + type: actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS, + process: { + ...process, + id: response.value + } + }); + }); + } + }, + + hideDeleteConfirm(dispatch) { + dispatch({ + type: + actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM, + processToDelete: false + }); + }, + + openDeleteProcessesConfirm(dispatch, { process }) { + dispatch({ + type: + actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM, + processToDelete: process + }); + }, + + openEditor(dispatch, process = {}) { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN, + process + }); + }, + closeEditor(dispatch) { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE + }); + } }; export default SoftwareProductComponentProcessesActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js index d15432b3fb..e3ce4f8007 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js @@ -16,21 +16,22 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null, - EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null, - DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null, - SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN: null, - SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE: null, - FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES: null, - SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM: null + ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null, + EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null, + DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: null, + SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN: null, + SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE: null, + FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES: null, + SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM: null }); export const optionsInputValues = { - PROCESS_TYPE: [ - {title: 'Select...', enum: ''}, - {title: 'Lifecycle Operations', enum: 'Lifecycle_Operations'}, - {title: 'Other', enum: 'Other'} - ] + PROCESS_TYPE: [ + { title: 'Select...', enum: '' }, + { title: 'Lifecycle Operations', enum: 'Lifecycle_Operations' }, + { title: 'Other', enum: 'Other' } + ] }; -export const SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM = 'SOFTWAREPRODUCTPROCESSCOMPONENTSEDITORFORM'; +export const SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM = + 'SOFTWAREPRODUCTPROCESSCOMPONENTSEDITORFORM'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditor.js index 9502e24b1a..9d2bf34b78 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditor.js @@ -13,44 +13,68 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; import SoftwareProductComponentProcessesActionHelper from './SoftwareProductComponentProcessesActionHelper'; import SoftwareProductComponentProcessesEditorView from './SoftwareProductComponentProcessesEditorView.jsx'; -import {SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM} from './SoftwareProductComponentProcessesConstants.js'; +import { SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM } from './SoftwareProductComponentProcessesConstants.js'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductComponents: {componentProcesses = {}}} = softwareProduct; - let {processesList = [], processesEditor = {}} = componentProcesses; - let {data, genericFieldInfo, formReady} = processesEditor; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductComponents: { componentProcesses = {} } + } = softwareProduct; + let { processesList = [], processesEditor = {} } = componentProcesses; + let { data, genericFieldInfo, formReady } = processesEditor; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - let previousData; - const processId = data ? data.id : null; - if(processId) { - previousData = processesList.find(process => process.id === processId); - } + let previousData; + const processId = data ? data.id : null; + if (processId) { + previousData = processesList.find(process => process.id === processId); + } - return { - data, - genericFieldInfo, - previousData, - isFormValid, - formReady - }; + return { + data, + genericFieldInfo, + previousData, + isFormValid, + formReady + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => { - - return { - onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM}), - onCancel: () => SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch), - onSubmit: ({previousProcess, process}) => { - SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch); - SoftwareProductComponentProcessesActionHelper.saveProcess(dispatch, {softwareProductId, version, previousProcess, componentId, process}); - }, - onValidateForm: () => ValidationHelper.validateForm(dispatch, SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM) - }; +const mapActionsToProps = ( + dispatch, + { softwareProductId, version, componentId } +) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM + }), + onCancel: () => + SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch), + onSubmit: ({ previousProcess, process }) => { + SoftwareProductComponentProcessesActionHelper.closeEditor(dispatch); + SoftwareProductComponentProcessesActionHelper.saveProcess( + dispatch, + { + softwareProductId, + version, + previousProcess, + componentId, + process + } + ); + }, + onValidateForm: () => + ValidationHelper.validateForm( + dispatch, + SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM + ) + }; }; -export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentProcessesEditorView); +export default connect(mapStateToProps, mapActionsToProps)( + SoftwareProductComponentProcessesEditorView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorReducer.js index 9afaa6d5fd..fd211734df 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorReducer.js @@ -13,42 +13,48 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM} from './SoftwareProductComponentProcessesConstants.js'; +import { + actionTypes, + SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM +} from './SoftwareProductComponentProcessesConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN: - return { - ...state, - formReady: null, - formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM, - genericFieldInfo: { - 'name' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}] - }, - 'description' : { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 1000}] - }, - 'artifactName' : { - isValid: true, - errorText: '', - validations: [] - }, - 'type' : { - isValid: true, - errorText: '', - validations: [] - } - }, - data: action.process - }; - case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE: - return {}; - default: - return state; - } + switch (action.type) { + case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_OPEN: + return { + ...state, + formReady: null, + formName: SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM, + genericFieldInfo: { + name: { + isValid: true, + errorText: '', + validations: [ + { type: 'required', data: true }, + { type: 'maxLength', data: 120 } + ] + }, + description: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 1000 }] + }, + artifactName: { + isValid: true, + errorText: '', + validations: [] + }, + type: { + isValid: true, + errorText: '', + validations: [] + } + }, + data: action.process + }; + case actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE: + return {}; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorView.jsx index 9841ecbae7..132ebe86fb 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorView.jsx @@ -14,17 +14,18 @@ * permissions and limitations under the License. */ import React from 'react'; -import {optionsInputValues as ComponentProcessesOptionsInputValues} from './SoftwareProductComponentProcessesConstants.js'; +import { optionsInputValues as ComponentProcessesOptionsInputValues } from './SoftwareProductComponentProcessesConstants.js'; import SoftwareProductProcessesEditorForm from 'sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorForm.jsx'; - class SoftwareProductProcessesEditorView extends React.Component { - - render() { - return ( - <SoftwareProductProcessesEditorForm optionsInputValues={ComponentProcessesOptionsInputValues} {...this.props}/> - ); - } + render() { + return ( + <SoftwareProductProcessesEditorForm + optionsInputValues={ComponentProcessesOptionsInputValues} + {...this.props} + /> + ); + } } export default SoftwareProductProcessesEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesList.js index 2a7152ef8b..cb6d25a6ac 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesList.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesList.js @@ -13,45 +13,64 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; import SoftwareProductComponentProcessesActionHelper from './SoftwareProductComponentProcessesActionHelper.js'; import SoftwareProductComponentsProcessesListView from './SoftwareProductComponentsProcessesListView.jsx'; -export const mapStateToProps = ({softwareProduct}) => { - - let {softwareProductEditor: {data:currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents: {componentProcesses = {}}} = softwareProduct; - let{processesList = [], processesEditor = {}} = componentProcesses; - let {data} = processesEditor; - - return { - currentSoftwareProduct, - isValidityData, - processesList, - isDisplayModal: Boolean(data), - isModalInEditMode: Boolean(data && data.id) - }; +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductEditor: { + data: currentSoftwareProduct = {}, + isValidityData = true + }, + softwareProductComponents: { componentProcesses = {} } + } = softwareProduct; + let { processesList = [], processesEditor = {} } = componentProcesses; + let { data } = processesEditor; + return { + currentSoftwareProduct, + isValidityData, + processesList, + isDisplayModal: Boolean(data), + isModalInEditMode: Boolean(data && data.id) + }; }; -const mapActionsToProps = (dispatch, {componentId, softwareProductId, version}) => { - - return { - onAddProcess: () => SoftwareProductComponentProcessesActionHelper.openEditor(dispatch), - onEditProcess: (process) => SoftwareProductComponentProcessesActionHelper.openEditor(dispatch, process), - onDeleteProcess: (process) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data:{ - msg: i18n('Are you sure you want to delete "{name}"?', {name: process.name}), - confirmationButtonText: i18n('Delete'), - title: i18n('Delete'), - onConfirmed: ()=> SoftwareProductComponentProcessesActionHelper.deleteProcess(dispatch, - {process, softwareProductId, version, componentId}) - } - }) - }; +const mapActionsToProps = ( + dispatch, + { componentId, softwareProductId, version } +) => { + return { + onAddProcess: () => + SoftwareProductComponentProcessesActionHelper.openEditor(dispatch), + onEditProcess: process => + SoftwareProductComponentProcessesActionHelper.openEditor( + dispatch, + process + ), + onDeleteProcess: process => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + msg: i18n('Are you sure you want to delete "{name}"?', { + name: process.name + }), + confirmationButtonText: i18n('Delete'), + title: i18n('Delete'), + onConfirmed: () => + SoftwareProductComponentProcessesActionHelper.deleteProcess( + dispatch, + { process, softwareProductId, version, componentId } + ) + } + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsProcessesListView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductComponentsProcessesListView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesListReducer.js index 98e24a9c21..d406f02c19 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesListReducer.js @@ -13,20 +13,26 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductComponentProcessesConstants.js'; +import { actionTypes } from './SoftwareProductComponentProcessesConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES: - return [...action.processesList]; - case actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: - const indexForEdit = state.findIndex(process => process.id === action.process.id); - return [...state.slice(0, indexForEdit), action.process, ...state.slice(indexForEdit + 1)]; - case actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: - return [...state, action.process]; - case actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: - return state.filter(process => process.id !== action.processId); - default: - return state; - } + switch (action.type) { + case actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES: + return [...action.processesList]; + case actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: + const indexForEdit = state.findIndex( + process => process.id === action.process.id + ); + return [ + ...state.slice(0, indexForEdit), + action.process, + ...state.slice(indexForEdit + 1) + ]; + case actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: + return [...state, action.process]; + case actionTypes.DELETE_SOFTWARE_PRODUCT_COMPONENTS_PROCESS: + return state.filter(process => process.id !== action.processId); + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesListView.jsx index 27c4b9f429..8fa2bffb27 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesListView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesListView.jsx @@ -21,55 +21,73 @@ import SoftwareProductProcessesEditor from './SoftwareProductComponentProcessesE import SoftwareProductProcessListView from 'sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessListView.jsx'; class SoftwareProductProcessesView extends React.Component { + state = { + localFilter: '' + }; - state = { - localFilter: '' - }; + static propTypes = { + onAddProcess: PropTypes.func, + onEditProcess: PropTypes.func, + onDeleteProcess: PropTypes.func, + isDisplayModal: PropTypes.bool, + isModalInEditMode: PropTypes.bool, + onStorageSelect: PropTypes.func, + componentId: PropTypes.string, + softwareProductId: PropTypes.string, + currentSoftwareProduct: PropTypes.object + }; - static propTypes = { - onAddProcess: PropTypes.func, - onEditProcess: PropTypes.func, - onDeleteProcess: PropTypes.func, - isDisplayModal: PropTypes.bool, - isModalInEditMode: PropTypes.bool, - onStorageSelect: PropTypes.func, - componentId: PropTypes.string, - softwareProductId: PropTypes.string, - currentSoftwareProduct: PropTypes.object - }; - - render() { - return ( - <div className='vsp-processes-page'> - <div className='software-product-view'> - <div className='software-product-landing-view-right-side vsp-components-processes-page flex-column'> - {this.renderEditor()} - <SoftwareProductProcessListView addButtonTitle={i18n('Add Component Process Details')} {...this.props}/> - </div> - </div> - </div> - ); - } - - renderEditor() { - let {softwareProductId, version, componentId, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props; - return ( - <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal'> - <Modal.Header> - <Modal.Title>{isModalInEditMode ? i18n('Edit Process Details') : i18n('Create New Process Details')}</Modal.Title> - </Modal.Header> - <Modal.Body className='edit-process-modal'> - <SoftwareProductProcessesEditor - componentId={componentId} - softwareProductId={softwareProductId} - version={version} - isReadOnlyMode={isReadOnlyMode}/> - </Modal.Body> - </Modal> - - ); - } + render() { + return ( + <div className="vsp-processes-page"> + <div className="software-product-view"> + <div className="software-product-landing-view-right-side vsp-components-processes-page flex-column"> + {this.renderEditor()} + <SoftwareProductProcessListView + addButtonTitle={i18n( + 'Add Component Process Details' + )} + {...this.props} + /> + </div> + </div> + </div> + ); + } + renderEditor() { + let { + softwareProductId, + version, + componentId, + isReadOnlyMode, + isDisplayModal, + isModalInEditMode + } = this.props; + return ( + <Modal + show={isDisplayModal} + bsSize="large" + animation={true} + className="onborading-modal"> + <Modal.Header> + <Modal.Title> + {isModalInEditMode + ? i18n('Edit Process Details') + : i18n('Create New Process Details')} + </Modal.Title> + </Modal.Header> + <Modal.Body className="edit-process-modal"> + <SoftwareProductProcessesEditor + componentId={componentId} + softwareProductId={softwareProductId} + version={version} + isReadOnlyMode={isReadOnlyMode} + /> + </Modal.Body> + </Modal> + ); + } } export default SoftwareProductProcessesView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js index ca27a76a18..8da9b99a33 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js @@ -13,32 +13,57 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js'; import SoftwareProductComponentStorageView from './SoftwareProductComponentStorageView.jsx'; -import {COMPONENTS_QUESTIONNAIRE} from '../SoftwareProductComponentsConstants.js'; +import { COMPONENTS_QUESTIONNAIRE } from '../SoftwareProductComponentsConstants.js'; -const mapStateToProps = ({softwareProduct: {softwareProductComponents}}) => { - let {componentEditor: {qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap}} = softwareProductComponents; +const mapStateToProps = ({ + softwareProduct: { softwareProductComponents } +}) => { + let { + componentEditor: { + qdata, + qgenericFieldInfo: qGenericFieldInfo, + dataMap + } + } = softwareProductComponents; - return { - qdata, - qGenericFieldInfo, - dataMap - }; + return { + qdata, + qGenericFieldInfo, + dataMap + }; }; -const mapActionToProps = (dispatch, {softwareProductId, version, componentId}) => { - return { - onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}), - onSubmit: ({qdata}) => { - return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata}); - } - }; +const mapActionToProps = ( + dispatch, + { softwareProductId, version, componentId } +) => { + return { + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: COMPONENTS_QUESTIONNAIRE + }), + onSubmit: ({ qdata }) => { + return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire( + dispatch, + { + softwareProductId, + version, + vspComponentId: componentId, + qdata + } + ); + } + }; }; -export default connect(mapStateToProps, mapActionToProps, null, {withRef: true}) (SoftwareProductComponentStorageView); +export default connect(mapStateToProps, mapActionToProps, null, { + withRef: true +})(SoftwareProductComponentStorageView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx index 8538dab6bc..ac7e4a8053 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx @@ -22,171 +22,311 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; import classnames from 'classnames'; -const BackupSection = ({isReadOnlyMode,dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('Backup')}> - <GridItem> - <div className='vertical-flex'> - <label key='label' className={classnames('control-label',{'disabled': isReadOnlyMode})}>{i18n('Backup Type')}</label> - <div className='radio-options-content-row'> - {qgenericFieldInfo['storage/backup/backupType'].enum.map(onSite => ( - <Input - data-test-id='backupType' - type='radio' - key={onSite.enum} - name={'compute/guestOS/bitSize'} - className='radio-field' - value={onSite.enum} - label={onSite.title} - onChange={(site) => onQDataChanged({'storage/backup/backupType' : site})} - isValid={qgenericFieldInfo['storage/backup/backupType'].isValid} - errorText={qgenericFieldInfo['storage/backup/backupType'].errorText} - checked={dataMap['storage/backup/backupType'] === onSite.enum} /> )) } - </div> - </div> - </GridItem> - <GridItem> - <Input - className='section-field' - data-test-id='backupSolution' - onChange={(backupSolution) => onQDataChanged({'storage/backup/backupSolution' : backupSolution})} - label={i18n('Backup Solution')} - type='text' - isValid={qgenericFieldInfo['storage/backup/backupSolution'].isValid} - errorText={qgenericFieldInfo['storage/backup/backupSolution'].errorText} - value={dataMap['storage/backup/backupSolution']}/> - </GridItem> - <GridItem> - <Input - className='section-field' - data-test-id='backupStorageSize' - onChange={(backupStorageSize) => onQDataChanged({'storage/backup/backupStorageSize' : backupStorageSize})} - label={i18n('Backup Storage Size (GB)')} - type='number' - isValid={qgenericFieldInfo['storage/backup/backupStorageSize'].isValid} - errorText={qgenericFieldInfo['storage/backup/backupStorageSize'].errorText} - value={dataMap['storage/backup/backupStorageSize']}/> - </GridItem> - <GridItem> - <Input - data-test-id='backupNIC' - label={i18n('Backup NIC')} - type='select' - className='input-options-select section-field' - groupClassName='bootstrap-input-options' - isValid={qgenericFieldInfo['storage/backup/backupNIC'].isValid} - errorText={qgenericFieldInfo['storage/backup/backupNIC'].errorText} - value={dataMap['storage/backup/backupNIC']} - onChange={(e) => { - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onQDataChanged({'storage/backup/backupNIC' : val});} - }> - <option key='placeholder' value=''>{i18n('Select...')}</option> - {qgenericFieldInfo['storage/backup/backupNIC'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)} - </Input> - </GridItem> - </GridSection> +const BackupSection = ({ + isReadOnlyMode, + dataMap, + onQDataChanged, + qgenericFieldInfo +}) => ( + <GridSection title={i18n('Backup')}> + <GridItem> + <div className="vertical-flex"> + <label + key="label" + className={classnames('control-label', { + disabled: isReadOnlyMode + })}> + {i18n('Backup Type')} + </label> + <div className="radio-options-content-row"> + {qgenericFieldInfo['storage/backup/backupType'].enum.map( + onSite => ( + <Input + data-test-id="backupType" + type="radio" + key={onSite.enum} + name={'compute/guestOS/bitSize'} + className="radio-field" + value={onSite.enum} + label={onSite.title} + onChange={site => + onQDataChanged({ + 'storage/backup/backupType': site + }) + } + isValid={ + qgenericFieldInfo[ + 'storage/backup/backupType' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'storage/backup/backupType' + ].errorText + } + checked={ + dataMap['storage/backup/backupType'] === + onSite.enum + } + /> + ) + )} + </div> + </div> + </GridItem> + <GridItem> + <Input + className="section-field" + data-test-id="backupSolution" + onChange={backupSolution => + onQDataChanged({ + 'storage/backup/backupSolution': backupSolution + }) + } + label={i18n('Backup Solution')} + type="text" + isValid={ + qgenericFieldInfo['storage/backup/backupSolution'].isValid + } + errorText={ + qgenericFieldInfo['storage/backup/backupSolution'].errorText + } + value={dataMap['storage/backup/backupSolution']} + /> + </GridItem> + <GridItem> + <Input + className="section-field" + data-test-id="backupStorageSize" + onChange={backupStorageSize => + onQDataChanged({ + 'storage/backup/backupStorageSize': backupStorageSize + }) + } + label={i18n('Backup Storage Size (GB)')} + type="number" + isValid={ + qgenericFieldInfo['storage/backup/backupStorageSize'] + .isValid + } + errorText={ + qgenericFieldInfo['storage/backup/backupStorageSize'] + .errorText + } + value={dataMap['storage/backup/backupStorageSize']} + /> + </GridItem> + <GridItem> + <Input + data-test-id="backupNIC" + label={i18n('Backup NIC')} + type="select" + className="input-options-select section-field" + groupClassName="bootstrap-input-options" + isValid={qgenericFieldInfo['storage/backup/backupNIC'].isValid} + errorText={ + qgenericFieldInfo['storage/backup/backupNIC'].errorText + } + value={dataMap['storage/backup/backupNIC']} + onChange={e => { + const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onQDataChanged({ 'storage/backup/backupNIC': val }); + }}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {qgenericFieldInfo['storage/backup/backupNIC'].enum.map(hv => ( + <option value={hv.enum} key={hv.enum}> + {hv.title} + </option> + ))} + </Input> + </GridItem> + </GridSection> ); -const SnapshotBackupSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('Snapshot Backup')}> - <GridItem> - <Input - className='section-field' - data-test-id='snapshotFrequency' - onChange={(snapshotFrequency) => onQDataChanged({'storage/snapshotBackup/snapshotFrequency' : snapshotFrequency})} - label={i18n('Backup Storage Size (GB)')} - type='number' - isValid={qgenericFieldInfo['storage/snapshotBackup/snapshotFrequency'].isValid} - errorText={qgenericFieldInfo['storage/snapshotBackup/snapshotFrequency'].errorText} - value={dataMap['storage/snapshotBackup/snapshotFrequency']}/> - </GridItem> - </GridSection> +const SnapshotBackupSection = ({ + dataMap, + onQDataChanged, + qgenericFieldInfo +}) => ( + <GridSection title={i18n('Snapshot Backup')}> + <GridItem> + <Input + className="section-field" + data-test-id="snapshotFrequency" + onChange={snapshotFrequency => + onQDataChanged({ + 'storage/snapshotBackup/snapshotFrequency': snapshotFrequency + }) + } + label={i18n('Backup Storage Size (GB)')} + type="number" + isValid={ + qgenericFieldInfo[ + 'storage/snapshotBackup/snapshotFrequency' + ].isValid + } + errorText={ + qgenericFieldInfo[ + 'storage/snapshotBackup/snapshotFrequency' + ].errorText + } + value={dataMap['storage/snapshotBackup/snapshotFrequency']} + /> + </GridItem> + </GridSection> ); -const LogBackupSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => ( - <GridSection title={i18n('Log Backup')}> - <GridItem> - <Input - className='section-field' - data-test-id='sizeOfLogFiles' - onChange={(sizeOfLogFiles) => onQDataChanged({'storage/logBackup/sizeOfLogFiles' : sizeOfLogFiles})} - label={i18n('Backup Storage Size (GB)')} - type='number' - isValid={qgenericFieldInfo['storage/logBackup/sizeOfLogFiles'].isValid} - errorText={qgenericFieldInfo['storage/logBackup/sizeOfLogFiles'].errorText} - value={dataMap['storage/logBackup/sizeOfLogFiles']}/> - </GridItem> - <GridItem> - <Input - className='section-field' - label={i18n('Log Retention Period (days)')} - data-test-id='logRetentionPeriod' - onChange={(logRetentionPeriod) => onQDataChanged({'storage/logBackup/logRetentionPeriod' : logRetentionPeriod})} - type='number' - isValid={qgenericFieldInfo['storage/logBackup/logRetentionPeriod'].isValid} - errorText={qgenericFieldInfo['storage/logBackup/logRetentionPeriod'].errorText} - value={dataMap['storage/logBackup/logRetentionPeriod']}/> - </GridItem> - <GridItem> - <Input - className='section-field' - label={i18n('Log Backup Frequency (days)')} - data-test-id='logBackupFrequency' - onChange={(logBackupFrequency) => onQDataChanged({'storage/logBackup/logBackupFrequency' : logBackupFrequency})} - type='number' - isValid={qgenericFieldInfo['storage/logBackup/logBackupFrequency'].isValid} - errorText={qgenericFieldInfo['storage/logBackup/logBackupFrequency'].errorText} - value={dataMap['storage/logBackup/logBackupFrequency']}/> - </GridItem> - <GridItem> - <Input - className='section-field' - label={i18n('Log File Location')} - data-test-id='logFileLocation' - onChange={(logFileLocation) => onQDataChanged({'storage/logBackup/logFileLocation' : logFileLocation})} - type='text' - isValid={qgenericFieldInfo['storage/logBackup/logFileLocation'].isValid} - errorText={qgenericFieldInfo['storage/logBackup/logFileLocation'].errorText} - value={dataMap['storage/logBackup/logFileLocation']}/> - </GridItem> - </GridSection> +const LogBackupSection = ({ dataMap, onQDataChanged, qgenericFieldInfo }) => ( + <GridSection title={i18n('Log Backup')}> + <GridItem> + <Input + className="section-field" + data-test-id="sizeOfLogFiles" + onChange={sizeOfLogFiles => + onQDataChanged({ + 'storage/logBackup/sizeOfLogFiles': sizeOfLogFiles + }) + } + label={i18n('Backup Storage Size (GB)')} + type="number" + isValid={ + qgenericFieldInfo['storage/logBackup/sizeOfLogFiles'] + .isValid + } + errorText={ + qgenericFieldInfo['storage/logBackup/sizeOfLogFiles'] + .errorText + } + value={dataMap['storage/logBackup/sizeOfLogFiles']} + /> + </GridItem> + <GridItem> + <Input + className="section-field" + label={i18n('Log Retention Period (days)')} + data-test-id="logRetentionPeriod" + onChange={logRetentionPeriod => + onQDataChanged({ + 'storage/logBackup/logRetentionPeriod': logRetentionPeriod + }) + } + type="number" + isValid={ + qgenericFieldInfo['storage/logBackup/logRetentionPeriod'] + .isValid + } + errorText={ + qgenericFieldInfo['storage/logBackup/logRetentionPeriod'] + .errorText + } + value={dataMap['storage/logBackup/logRetentionPeriod']} + /> + </GridItem> + <GridItem> + <Input + className="section-field" + label={i18n('Log Backup Frequency (days)')} + data-test-id="logBackupFrequency" + onChange={logBackupFrequency => + onQDataChanged({ + 'storage/logBackup/logBackupFrequency': logBackupFrequency + }) + } + type="number" + isValid={ + qgenericFieldInfo['storage/logBackup/logBackupFrequency'] + .isValid + } + errorText={ + qgenericFieldInfo['storage/logBackup/logBackupFrequency'] + .errorText + } + value={dataMap['storage/logBackup/logBackupFrequency']} + /> + </GridItem> + <GridItem> + <Input + className="section-field" + label={i18n('Log File Location')} + data-test-id="logFileLocation" + onChange={logFileLocation => + onQDataChanged({ + 'storage/logBackup/logFileLocation': logFileLocation + }) + } + type="text" + isValid={ + qgenericFieldInfo['storage/logBackup/logFileLocation'] + .isValid + } + errorText={ + qgenericFieldInfo['storage/logBackup/logFileLocation'] + .errorText + } + value={dataMap['storage/logBackup/logFileLocation']} + /> + </GridItem> + </GridSection> ); class SoftwareProductComponentStorageView extends React.Component { + static propTypes = { + componentId: PropTypes.string, + onQDataChanged: PropTypes.func, + onSubmit: PropTypes.func, + isReadOnlyMode: PropTypes.bool + }; - static propTypes = { - componentId: PropTypes.string, - onQDataChanged: PropTypes.func, - onSubmit: PropTypes.func, - isReadOnlyMode: PropTypes.bool - }; + render() { + let { + onQDataChanged, + dataMap, + qGenericFieldInfo, + isReadOnlyMode, + onSubmit, + qdata + } = this.props; - render() { - let {onQDataChanged, dataMap, qGenericFieldInfo, isReadOnlyMode, onSubmit, qdata} = this.props; + return ( + <div className="vsp-component-questionnaire-view"> + {qGenericFieldInfo && ( + <Form + ref={form => (this.form = form)} + isValid={true} + formReady={null} + onSubmit={() => onSubmit({ qdata })} + className="component-questionnaire-validation-form" + isReadOnlyMode={isReadOnlyMode} + hasButtons={false}> + <BackupSection + isReadOnlyMode={isReadOnlyMode} + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + <SnapshotBackupSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + <LogBackupSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + qgenericFieldInfo={qGenericFieldInfo} + /> + </Form> + )} + </div> + ); + } - return( - <div className='vsp-component-questionnaire-view'> - {qGenericFieldInfo && <Form - ref={form => this.form = form } - isValid={true} - formReady={null} - onSubmit={() => onSubmit({qdata})} - className='component-questionnaire-validation-form' - isReadOnlyMode={isReadOnlyMode} - hasButtons={false}> - <BackupSection isReadOnlyMode={isReadOnlyMode} onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - <SnapshotBackupSection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - <LogBackupSection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/> - </Form> } - </div> - ); - } - - save(){ - const {qdata, onSubmit} = this.props; - return onSubmit({qdata}); - } + save() { + const { qdata, onSubmit } = this.props; + return onSubmit({ qdata }); + } } export default SoftwareProductComponentStorageView; 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 569b33f999..41584d94e2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js @@ -13,64 +13,96 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductCreationActionHelper from './SoftwareProductCreationActionHelper.js'; import SoftwareProductCreationView from './SoftwareProductCreationView.jsx'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import SoftwareProductActionHelper from '../SoftwareProductActionHelper.js'; +import SoftwareProductActionHelper from '../SoftwareProductActionHelper.js'; import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js'; -import {itemTypes as versionItemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js'; +import { itemTypes as versionItemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js'; import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js'; -import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js'; +import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js'; import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js'; -export const mapStateToProps = ({finalizedLicenseModelList, users: {usersList}, archivedSoftwareProductList, - softwareProductList, finalizedSoftwareProductList, softwareProduct: {softwareProductCreation, softwareProductCategories} }) => { - let {genericFieldInfo} = softwareProductCreation; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); +export const mapStateToProps = ({ + finalizedLicenseModelList, + users: { usersList }, + archivedSoftwareProductList, + softwareProductList, + finalizedSoftwareProductList, + softwareProduct: { softwareProductCreation, softwareProductCategories } +}) => { + let { genericFieldInfo } = softwareProductCreation; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - let VSPNames = {}; - const allVspList = [...softwareProductList, ...finalizedSoftwareProductList, ...archivedSoftwareProductList]; - allVspList.map(item => { - VSPNames[item.name.toLowerCase()] = item.id; - }); - + let VSPNames = {}; + const allVspList = [ + ...softwareProductList, + ...finalizedSoftwareProductList, + ...archivedSoftwareProductList + ]; + allVspList.map(item => { + VSPNames[item.name.toLowerCase()] = item.id; + }); - return { - data: softwareProductCreation.data, - selectedVendorId: softwareProductCreation.selectedVendorId, - disableVendor: softwareProductCreation.disableVendor, - softwareProductCategories, - finalizedLicenseModelList, - isFormValid, - formReady: softwareProductCreation.formReady, - genericFieldInfo, - VSPNames, - usersList - }; + return { + data: softwareProductCreation.data, + selectedVendorId: softwareProductCreation.selectedVendorId, + disableVendor: softwareProductCreation.disableVendor, + softwareProductCategories, + finalizedLicenseModelList, + isFormValid, + formReady: softwareProductCreation.formReady, + genericFieldInfo, + VSPNames, + usersList + }; }; -export const mapActionsToProps = (dispatch) => { - return { - onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}), - onCancel: () => SoftwareProductCreationActionHelper.resetData(dispatch), - onSubmit: (softwareProduct, usersList) => { - SoftwareProductCreationActionHelper.resetData(dispatch); - SoftwareProductCreationActionHelper.createSoftwareProduct(dispatch, {softwareProduct}).then(response => { - let {itemId, version} = response; - SoftwareProductActionHelper.fetchSoftwareProductList(dispatch).then(() => - PermissionsActionHelper.fetchItemUsers(dispatch, {itemId, allUsers: usersList}).then(() => - VersionsPageActionHelper.fetchVersions(dispatch, {itemType: versionItemTypes.SOFTWARE_PRODUCT, itemId}).then(() => - ScreensHelper.loadScreen(dispatch, {screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId: itemId, version}}) - ) - ) - ); - }); - }, - onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName) - }; +export const mapActionsToProps = dispatch => { + return { + onDataChanged: (deltaData, formName, customValidations) => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName, + customValidations + }), + onCancel: () => SoftwareProductCreationActionHelper.resetData(dispatch), + onSubmit: (softwareProduct, usersList) => { + SoftwareProductCreationActionHelper.resetData(dispatch); + SoftwareProductCreationActionHelper.createSoftwareProduct( + dispatch, + { softwareProduct } + ).then(response => { + let { itemId, version } = response; + SoftwareProductActionHelper.fetchSoftwareProductList( + dispatch + ).then(() => + PermissionsActionHelper.fetchItemUsers(dispatch, { + itemId, + allUsers: usersList + }).then(() => + VersionsPageActionHelper.fetchVersions(dispatch, { + itemType: versionItemTypes.SOFTWARE_PRODUCT, + itemId + }).then(() => + ScreensHelper.loadScreen(dispatch, { + screen: + enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId: itemId, version } + }) + ) + ) + ); + }); + }, + onValidateForm: formName => + ValidationHelper.validateForm(dispatch, formName) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductCreationView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductCreationView); 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 b19e460497..1b1fd71fef 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js @@ -17,68 +17,68 @@ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; -import {actionTypes as modalActionTypes, modalSizes} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; -import {actionTypes} from './SoftwareProductCreationConstants.js'; +import { + actionTypes as modalActionTypes, + modalSizes +} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; +import { actionTypes } from './SoftwareProductCreationConstants.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; function baseUrl() { - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/`; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/`; } function createSoftwareProduct(softwareProduct) { - return RestAPIUtil.post(baseUrl(), { - ...softwareProduct, - icon: 'icon', - licensingData: {} - }); + return RestAPIUtil.post(baseUrl(), { + ...softwareProduct, + icon: 'icon', + licensingData: {} + }); } const SoftwareProductCreationActionHelper = { + open(dispatch, vendorId) { + SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch); + dispatch({ + type: actionTypes.OPEN, + selectedVendorId: vendorId + }); - open(dispatch, vendorId) { - SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch); - dispatch({ - type: actionTypes.OPEN, - selectedVendorId: vendorId - }); + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: + modalContentMapper.SOFTWARE_PRODUCT_CREATION, + title: i18n('New Software Product'), + modalComponentProps: { + vendorId, + size: modalSizes.LARGE + } + } + }); + }, - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.SOFTWARE_PRODUCT_CREATION, - title: i18n('New Software Product'), - modalComponentProps: { - vendorId, - size: modalSizes.LARGE - } - } - }); + resetData(dispatch) { + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }); - }, - - resetData(dispatch) { - - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_CLOSE - }); - - dispatch({ - type: actionTypes.RESET_DATA - }); - }, - - createSoftwareProduct(dispatch, {softwareProduct}) { - return createSoftwareProduct(softwareProduct).then(result => { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_CREATED, - result - }); - return result; - }); - } + dispatch({ + type: actionTypes.RESET_DATA + }); + }, + createSoftwareProduct(dispatch, { softwareProduct }) { + return createSoftwareProduct(softwareProduct).then(result => { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_CREATED, + result + }); + return result; + }); + } }; export default SoftwareProductCreationActionHelper; 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 b941c849cb..ad1034602a 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js @@ -16,9 +16,9 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - OPEN: null, - RESET_DATA: null, - SOFTWARE_PRODUCT_CREATED: null + OPEN: null, + RESET_DATA: null, + SOFTWARE_PRODUCT_CREATED: 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 a7db2b2357..5f70f18f75 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js @@ -13,56 +13,70 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, SP_CREATION_FORM_NAME} from './SoftwareProductCreationConstants.js'; - +import { + actionTypes, + SP_CREATION_FORM_NAME +} from './SoftwareProductCreationConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.OPEN: - return { - ...state, - formName: SP_CREATION_FORM_NAME, - disableVendor: action.selectedVendorId ? true : false, - data: { - vendorId: action.selectedVendorId ? action.selectedVendorId : undefined - }, - genericFieldInfo: { - 'description' : { - isValid: true, - errorText: '', - validations: [{type: 'freeEnglishText', data: true}, {type: 'maxLength', data: 1000}, {type: 'required', data: true}] - }, - 'vendorId' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}] - }, - 'subCategory' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}] - }, - 'category' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}] - }, - 'name' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}, {type: 'validateName', data: true}] - }, - 'onboardingMethod' : { - isValid: true, - errorText: '', - validations: [{type: 'requiredChooseOption', data: true}] - } - }, - showModal: true - }; - case actionTypes.RESET_DATA: - return {}; - default: - return state; - } + switch (action.type) { + case actionTypes.OPEN: + return { + ...state, + formName: SP_CREATION_FORM_NAME, + disableVendor: action.selectedVendorId ? true : false, + data: { + vendorId: action.selectedVendorId + ? action.selectedVendorId + : undefined + }, + genericFieldInfo: { + description: { + isValid: true, + errorText: '', + validations: [ + { type: 'freeEnglishText', data: true }, + { type: 'maxLength', data: 1000 }, + { type: 'required', data: true } + ] + }, + vendorId: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + }, + subCategory: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + }, + category: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + }, + name: { + isValid: true, + errorText: '', + validations: [ + { type: 'required', data: true }, + { type: 'maxLength', data: 25 }, + { type: 'validateName', data: true } + ] + }, + onboardingMethod: { + isValid: true, + errorText: '', + validations: [ + { type: 'requiredChooseOption', data: true } + ] + } + }, + showModal: true + }; + case actionTypes.RESET_DATA: + return {}; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx index e491491f4d..e94087cc80 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx @@ -22,194 +22,308 @@ 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 { 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'; +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 + 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 + }; - 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, {name: name => this.validateName(name)})} - 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 {finalizedLicenseModelList} = this.props; - - return [{enum: '', title: i18n('please select...')}].concat( - sortByStringProperty(finalizedLicenseModelList, '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')}; - } - - validate() { - this.props.onValidateForm(SP_CREATION_FORM_NAME); - } + 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, + { + name: name => + this.validateName(name) + } + ) + } + 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 { finalizedLicenseModelList } = this.props; + + return [{ enum: '', title: i18n('please select...') }].concat( + sortByStringProperty(finalizedLicenseModelList, '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" + ) + }; + } + + 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> - ); +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; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js index 9888087800..1a0c66d70e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js @@ -13,25 +13,48 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductDependenciesView from './SoftwareProductDependenciesView.jsx'; import SoftwareProductDependenciesActionHelper from './SoftwareProductDependenciesActionHelper.js'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductDependencies, softwareProductComponents: {componentsList}} = softwareProduct; - return { - softwareProductDependencies: softwareProductDependencies, - componentsOptions: componentsList.map(component => ({value: component.id, label: component.displayName})) - }; +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductDependencies, + softwareProductComponents: { componentsList } + } = softwareProduct; + return { + softwareProductDependencies: softwareProductDependencies, + componentsOptions: componentsList.map(component => ({ + value: component.id, + label: component.displayName + })) + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version}) => { - return { - onDataChanged: (item) => SoftwareProductDependenciesActionHelper.updateDependency(dispatch, {softwareProductId, version, item}), - onDeleteDependency: (item) => SoftwareProductDependenciesActionHelper.removeDependency(dispatch, {softwareProductId, version, item}), - onAddDependency: (item) => SoftwareProductDependenciesActionHelper.createDependency(dispatch, {softwareProductId, version, item}) - }; +const mapActionsToProps = (dispatch, { softwareProductId, version }) => { + return { + onDataChanged: item => + SoftwareProductDependenciesActionHelper.updateDependency(dispatch, { + softwareProductId, + version, + item + }), + onDeleteDependency: item => + SoftwareProductDependenciesActionHelper.removeDependency(dispatch, { + softwareProductId, + version, + item + }), + onAddDependency: item => + SoftwareProductDependenciesActionHelper.createDependency(dispatch, { + softwareProductId, + version, + item + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductDependenciesView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductDependenciesView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js index f04f8faf56..4bbcaa13d5 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js @@ -15,83 +15,99 @@ */ import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; -import {actionTypes, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js'; +import { + actionTypes, + NEW_RULE_TEMP_ID +} from './SoftwareProductDependenciesConstants.js'; function baseUrl(softwareProductId, version) { - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/component-dependencies`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/component-dependencies`; } function fetchDependencies(softwareProductId, version) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); + return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); } function addDepencency(softwareProductId, version, item) { - return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { - sourceId: item.sourceId, - targetId: item.targetId, - relationType: item.relationType - }); + return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { + sourceId: item.sourceId, + targetId: item.targetId, + relationType: item.relationType + }); } - function updateDepencency(softwareProductId, version, item) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${item.id}`, - { - sourceId: item.sourceId, - targetId: item.targetId, - relationType: item.relationType - }); + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version)}/${item.id}`, + { + sourceId: item.sourceId, + targetId: item.targetId, + relationType: item.relationType + } + ); } function removeDependency(softwareProductId, version, item) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${item.id}`); + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version)}/${item.id}` + ); } - const SoftwareProductDependenciesActionHelper = { - updateDependency(dispatch, {softwareProductId, version, item}) { - // if change was made on existing item - we will update the server and refresh the list - // if change was made on the 'new' row - we will only fire the event - if (item.id !== NEW_RULE_TEMP_ID) { - return updateDepencency(softwareProductId, version, item).then(() => { - return this.fetchDependencies(dispatch, {softwareProductId, version}); - }); - } else { - dispatch({ - type: actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY, - item: item - }); - } - }, + updateDependency(dispatch, { softwareProductId, version, item }) { + // if change was made on existing item - we will update the server and refresh the list + // if change was made on the 'new' row - we will only fire the event + if (item.id !== NEW_RULE_TEMP_ID) { + return updateDepencency(softwareProductId, version, item).then( + () => { + return this.fetchDependencies(dispatch, { + softwareProductId, + version + }); + } + ); + } else { + dispatch({ + type: actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY, + item: item + }); + } + }, - createDependency(dispatch, {softwareProductId, version, item}) { - // removing the temp id - delete item.id; - // creating the new dependency - return addDepencency(softwareProductId, version, item).then(() => { - dispatch({ - type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY - }); - return this.fetchDependencies(dispatch, {softwareProductId, version}); - }); - }, + createDependency(dispatch, { softwareProductId, version, item }) { + // removing the temp id + delete item.id; + // creating the new dependency + return addDepencency(softwareProductId, version, item).then(() => { + dispatch({ + type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY + }); + return this.fetchDependencies(dispatch, { + softwareProductId, + version + }); + }); + }, - removeDependency(dispatch, {softwareProductId, version, item}) { - return removeDependency(softwareProductId, version, item).then( () => { - return this.fetchDependencies(dispatch, {softwareProductId, version}); - }); - }, + removeDependency(dispatch, { softwareProductId, version, item }) { + return removeDependency(softwareProductId, version, item).then(() => { + return this.fetchDependencies(dispatch, { + softwareProductId, + version + }); + }); + }, - fetchDependencies(dispatch, {softwareProductId, version}) { - return fetchDependencies(softwareProductId, version).then( response => { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE, - dependenciesList : response.results - }); - }); - } + fetchDependencies(dispatch, { softwareProductId, version }) { + return fetchDependencies(softwareProductId, version).then(response => { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE, + dependenciesList: response.results + }); + }); + } }; export default SoftwareProductDependenciesActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js index c25561da17..32c7387ca2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js @@ -16,17 +16,17 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null, - ADD_SOFTWARE_PRODUCT_DEPENDENCY: null, - UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: null + SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null, + ADD_SOFTWARE_PRODUCT_DEPENDENCY: null, + UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: null }); export const relationTypes = { - DEPENDS_ON: 'dependsOn' + DEPENDS_ON: 'dependsOn' }; export const relationTypesOptions = [ - {value: relationTypes.DEPENDS_ON, label: 'Depends On'} + { value: relationTypes.DEPENDS_ON, label: 'Depends On' } ]; -export const NEW_RULE_TEMP_ID = 'newRuleTempId';
\ No newline at end of file +export const NEW_RULE_TEMP_ID = 'newRuleTempId'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js index 3edd3b899a..6e028b1ff2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js @@ -1,4 +1,3 @@ - /*! * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * @@ -15,32 +14,47 @@ * permissions and limitations under the License. */ -import {actionTypes, relationTypes, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js'; -import {checkCyclesAndMarkDependencies} from './SoftwareProductDependenciesUtils.js'; +import { + actionTypes, + relationTypes, + NEW_RULE_TEMP_ID +} from './SoftwareProductDependenciesConstants.js'; +import { checkCyclesAndMarkDependencies } from './SoftwareProductDependenciesUtils.js'; -let newRowObject = {id: NEW_RULE_TEMP_ID, targetId: null, sourceId: null, relationType: relationTypes.DEPENDS_ON}; +let newRowObject = { + id: NEW_RULE_TEMP_ID, + targetId: null, + sourceId: null, + relationType: relationTypes.DEPENDS_ON +}; -export default (state = [Object.assign({}, newRowObject) ], action) => { - switch (action.type) { - case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: - // copying the entity with the data for the row that is in the 'add' mode - let newDependency = state.find(dependency => dependency.id === NEW_RULE_TEMP_ID); - action.dependenciesList.push(newDependency); - // returning list from the server with our 'new entity' row - return checkCyclesAndMarkDependencies(action.dependenciesList); - case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY : - // resetting the entity with the data for the 'add' mode for a new entity - let newArray = state.filter(dependency => dependency.id !== NEW_RULE_TEMP_ID); - newArray.push(Object.assign({}, newRowObject)); - return newArray; - case actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY : - // we really only need this for the 'new' row since we need to change the state to get - // everything updated - let updateArrayIndex = state.findIndex(dependency => dependency.id === NEW_RULE_TEMP_ID); - let updateArray = state.slice(); - updateArray.splice(updateArrayIndex, 1, action.item); - return checkCyclesAndMarkDependencies(updateArray); - default: - return state; - } +export default (state = [Object.assign({}, newRowObject)], action) => { + switch (action.type) { + case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: + // copying the entity with the data for the row that is in the 'add' mode + let newDependency = state.find( + dependency => dependency.id === NEW_RULE_TEMP_ID + ); + action.dependenciesList.push(newDependency); + // returning list from the server with our 'new entity' row + return checkCyclesAndMarkDependencies(action.dependenciesList); + case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY: + // resetting the entity with the data for the 'add' mode for a new entity + let newArray = state.filter( + dependency => dependency.id !== NEW_RULE_TEMP_ID + ); + newArray.push(Object.assign({}, newRowObject)); + return newArray; + case actionTypes.UPDATE_NEW_SOFTWARE_PRODUCT_DEPENDENCY: + // we really only need this for the 'new' row since we need to change the state to get + // everything updated + let updateArrayIndex = state.findIndex( + dependency => dependency.id === NEW_RULE_TEMP_ID + ); + let updateArray = state.slice(); + updateArray.splice(updateArrayIndex, 1, action.item); + return checkCyclesAndMarkDependencies(updateArray); + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js index 94d21bd49d..8d5aaf864e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js @@ -16,49 +16,77 @@ import DirectedGraph from 'nfvo-utils/DirectedGraph.js'; -function findCycles(graph, node, id, visited = {}, visitedConnections = {}, recursionStack = {}, connectionsWithCycle = {}) { - visited[node] = true; - recursionStack[node] = true; - if (id) { - visitedConnections[id] = true; - } - for (let edge of graph.getEdges(node)) { - if (!visited[edge.target]) { - findCycles(graph, edge.target, edge.id, visited, visitedConnections, recursionStack, connectionsWithCycle); - } else if (recursionStack[edge.target]) { - visitedConnections[edge.id] = true; - for (let connection in visitedConnections) { - connectionsWithCycle[connection] = true; - } - } - } - recursionStack[node] = false; - return {visitedNodes: visited, connectionsWithCycle: connectionsWithCycle}; +function findCycles( + graph, + node, + id, + visited = {}, + visitedConnections = {}, + recursionStack = {}, + connectionsWithCycle = {} +) { + visited[node] = true; + recursionStack[node] = true; + if (id) { + visitedConnections[id] = true; + } + for (let edge of graph.getEdges(node)) { + if (!visited[edge.target]) { + findCycles( + graph, + edge.target, + edge.id, + visited, + visitedConnections, + recursionStack, + connectionsWithCycle + ); + } else if (recursionStack[edge.target]) { + visitedConnections[edge.id] = true; + for (let connection in visitedConnections) { + connectionsWithCycle[connection] = true; + } + } + } + recursionStack[node] = false; + return { + visitedNodes: visited, + connectionsWithCycle: connectionsWithCycle + }; } export function checkCyclesAndMarkDependencies(dependenciesList) { - let overallVisitedNodes = {}; - let overallConnectionsWithCycles = {}; + let overallVisitedNodes = {}; + let overallConnectionsWithCycles = {}; - let g = new DirectedGraph(); - for (let dependency of dependenciesList) { - if (dependency.sourceId !== null && dependency.targetId !== null) { - g.addEdge(dependency.sourceId, dependency.targetId, {id: dependency.id}); - } - } + let g = new DirectedGraph(); + for (let dependency of dependenciesList) { + if (dependency.sourceId !== null && dependency.targetId !== null) { + g.addEdge(dependency.sourceId, dependency.targetId, { + id: dependency.id + }); + } + } - for (let node in g.nodes) { - if (!overallVisitedNodes.node) { - let {visitedNodes, connectionsWithCycle} = findCycles(g, node, undefined); - overallVisitedNodes = {...overallVisitedNodes, ...visitedNodes}; - overallConnectionsWithCycles = {...overallConnectionsWithCycles, ...connectionsWithCycle}; - } - } - return dependenciesList.map(dependency => ( - { - ...dependency, - hasCycle: dependency.sourceId && dependency.targetId ? - overallConnectionsWithCycles.hasOwnProperty(dependency.id) - : undefined - })); + for (let node in g.nodes) { + if (!overallVisitedNodes.node) { + let { visitedNodes, connectionsWithCycle } = findCycles( + g, + node, + undefined + ); + overallVisitedNodes = { ...overallVisitedNodes, ...visitedNodes }; + overallConnectionsWithCycles = { + ...overallConnectionsWithCycles, + ...connectionsWithCycle + }; + } + } + return dependenciesList.map(dependency => ({ + ...dependency, + hasCycle: + dependency.sourceId && dependency.targetId + ? overallConnectionsWithCycles.hasOwnProperty(dependency.id) + : undefined + })); } diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx index ed92de7bb1..3ea1f2d5cc 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx @@ -20,111 +20,201 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import SelectActionTable from 'nfvo-components/table/SelectActionTable.jsx'; import SelectActionTableRow from 'nfvo-components/table/SelectActionTableRow.jsx'; import SelectActionTableCell from 'nfvo-components/table/SelectActionTableCell.jsx'; -import {relationTypesOptions, NEW_RULE_TEMP_ID} from './SoftwareProductDependenciesConstants.js'; +import { + relationTypesOptions, + NEW_RULE_TEMP_ID +} from './SoftwareProductDependenciesConstants.js'; - -const TableActionRow = ({onAction, actionIcon, showAction, dependency, sourceOptions, targetOptions, onDataChanged}) => { - return ( - <SelectActionTableRow - key={dependency.id} - onAction={onAction} - overlayMsg={i18n('There is a loop between selections')} - hasError={dependency.hasCycle} - hasErrorIndication - showAction={showAction} - actionIcon={actionIcon}> - <SelectActionTableCell - options={sourceOptions} - selected={dependency.sourceId} - placeholder={i18n('Select VFC...')} - clearable={false} - onChange={newVal => { - dependency.sourceId = newVal; - onDataChanged(dependency); - }} /> - <SelectActionTableCell options={relationTypesOptions} selected={dependency.relationType} clearable={false}/> - <SelectActionTableCell - placeholder={i18n('Select VFC...')} - options={targetOptions} - selected={dependency.targetId} - clearable={false} - onChange={newVal => { - dependency.targetId = newVal; - onDataChanged(dependency); - }} /> - </SelectActionTableRow> - ); +const TableActionRow = ({ + onAction, + actionIcon, + showAction, + dependency, + sourceOptions, + targetOptions, + onDataChanged +}) => { + return ( + <SelectActionTableRow + key={dependency.id} + onAction={onAction} + overlayMsg={i18n('There is a loop between selections')} + hasError={dependency.hasCycle} + hasErrorIndication + showAction={showAction} + actionIcon={actionIcon}> + <SelectActionTableCell + options={sourceOptions} + selected={dependency.sourceId} + placeholder={i18n('Select VFC...')} + clearable={false} + onChange={newVal => { + dependency.sourceId = newVal; + onDataChanged(dependency); + }} + /> + <SelectActionTableCell + options={relationTypesOptions} + selected={dependency.relationType} + clearable={false} + /> + <SelectActionTableCell + placeholder={i18n('Select VFC...')} + options={targetOptions} + selected={dependency.targetId} + clearable={false} + onChange={newVal => { + dependency.targetId = newVal; + onDataChanged(dependency); + }} + /> + </SelectActionTableRow> + ); }; - export default class SoftwareProductDependenciesView extends React.Component { - filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId, selectedTargetId}) { - let isInMap = sourceToTargetMapping.hasOwnProperty(selectedSourceId); - return componentsOptions.filter(component => { - if (component.value === selectedTargetId) { - return true; - } else { - return component.value !== selectedSourceId && (isInMap ? sourceToTargetMapping[selectedSourceId].indexOf(component.value) < 0 : true); - } - }); - } - - filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId, selectedTargetId}) { - return componentsOptions.filter(component => { - if (component.value === selectedSourceId) { - return true; - } else { - let isInMap = sourceToTargetMapping.hasOwnProperty(component.value); - return component.value !== selectedTargetId && (isInMap ? sourceToTargetMapping[component.value].indexOf(selectedTargetId) < 0 : true); - } - }); - } + filterTargets({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId, + selectedTargetId + }) { + let isInMap = sourceToTargetMapping.hasOwnProperty(selectedSourceId); + return componentsOptions.filter(component => { + if (component.value === selectedTargetId) { + return true; + } else { + return ( + component.value !== selectedSourceId && + (isInMap + ? sourceToTargetMapping[selectedSourceId].indexOf( + component.value + ) < 0 + : true) + ); + } + }); + } - render() { - let {componentsOptions, softwareProductDependencies, onDataChanged, onAddDependency, onDeleteDependency, isReadOnlyMode} = this.props; - let sourceToTargetMapping = {}; - softwareProductDependencies.map(dependency => { - let isInMap = sourceToTargetMapping.hasOwnProperty(dependency.sourceId); - if (dependency.targetId) { - sourceToTargetMapping[dependency.sourceId] = isInMap ? [...sourceToTargetMapping[dependency.sourceId], dependency.targetId] : [dependency.targetId]; - } - }); - let depList = softwareProductDependencies.filter(dependency => dependency.id !== NEW_RULE_TEMP_ID); - let newDependency = softwareProductDependencies.find(dependency => dependency.id === NEW_RULE_TEMP_ID); - return ( - <div className='software-product-dependencies'> - <div className='page-title'>{i18n('Dependencies')}</div> - <SelectActionTable - columns={[i18n('Source'), i18n('Relation Type'), i18n('Target')]} - numOfIcons={2} - isReadOnlyMode={isReadOnlyMode}> - {!isReadOnlyMode && <TableActionRow - key={newDependency.id} - actionIcon='plusCircle' - onAction={() => onAddDependency(newDependency)} - dependency={newDependency} - componentsOptions={componentsOptions} - sourceToTargetMapping={sourceToTargetMapping} - onDataChanged={onDataChanged} - sourceOptions={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: newDependency.sourceId, selectedTargetId: newDependency.targetId})} - targetOptions={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: newDependency.sourceId, selectedTargetId: newDependency.targetId})} - showAction={newDependency.targetId !== null && newDependency.relationType !== null && newDependency.sourceId !== null}/> } - {depList.map(dependency => ( - <TableActionRow - key={dependency.id} - actionIcon='trashO' - onAction={() => onDeleteDependency(dependency)} - dependency={dependency} - componentsOptions={componentsOptions} - sourceToTargetMapping={sourceToTargetMapping} - sourceOptions={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})} - targetOptions={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})} - onDataChanged={onDataChanged} - showAction={true}/> - ))} - </SelectActionTable> - </div> - ); - } + filterSources({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId, + selectedTargetId + }) { + return componentsOptions.filter(component => { + if (component.value === selectedSourceId) { + return true; + } else { + let isInMap = sourceToTargetMapping.hasOwnProperty( + component.value + ); + return ( + component.value !== selectedTargetId && + (isInMap + ? sourceToTargetMapping[component.value].indexOf( + selectedTargetId + ) < 0 + : true) + ); + } + }); + } + render() { + let { + componentsOptions, + softwareProductDependencies, + onDataChanged, + onAddDependency, + onDeleteDependency, + isReadOnlyMode + } = this.props; + let sourceToTargetMapping = {}; + softwareProductDependencies.map(dependency => { + let isInMap = sourceToTargetMapping.hasOwnProperty( + dependency.sourceId + ); + if (dependency.targetId) { + sourceToTargetMapping[dependency.sourceId] = isInMap + ? [ + ...sourceToTargetMapping[dependency.sourceId], + dependency.targetId + ] + : [dependency.targetId]; + } + }); + let depList = softwareProductDependencies.filter( + dependency => dependency.id !== NEW_RULE_TEMP_ID + ); + let newDependency = softwareProductDependencies.find( + dependency => dependency.id === NEW_RULE_TEMP_ID + ); + return ( + <div className="software-product-dependencies"> + <div className="page-title">{i18n('Dependencies')}</div> + <SelectActionTable + columns={[ + i18n('Source'), + i18n('Relation Type'), + i18n('Target') + ]} + numOfIcons={2} + isReadOnlyMode={isReadOnlyMode}> + {!isReadOnlyMode && ( + <TableActionRow + key={newDependency.id} + actionIcon="plusCircle" + onAction={() => onAddDependency(newDependency)} + dependency={newDependency} + componentsOptions={componentsOptions} + sourceToTargetMapping={sourceToTargetMapping} + onDataChanged={onDataChanged} + sourceOptions={this.filterSources({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: newDependency.sourceId, + selectedTargetId: newDependency.targetId + })} + targetOptions={this.filterTargets({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: newDependency.sourceId, + selectedTargetId: newDependency.targetId + })} + showAction={ + newDependency.targetId !== null && + newDependency.relationType !== null && + newDependency.sourceId !== null + } + /> + )} + {depList.map(dependency => ( + <TableActionRow + key={dependency.id} + actionIcon="trashO" + onAction={() => onDeleteDependency(dependency)} + dependency={dependency} + componentsOptions={componentsOptions} + sourceToTargetMapping={sourceToTargetMapping} + sourceOptions={this.filterSources({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: dependency.sourceId, + selectedTargetId: dependency.targetId + })} + targetOptions={this.filterTargets({ + componentsOptions, + sourceToTargetMapping, + selectedSourceId: dependency.sourceId, + selectedTargetId: dependency.targetId + })} + onDataChanged={onDataChanged} + showAction={true} + /> + ))} + </SelectActionTable> + </div> + ); + } } diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeployment.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeployment.js index a5c70068b0..4e03926ac5 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeployment.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeployment.js @@ -13,37 +13,70 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductDeploymentView from './SoftwareProductDeploymentView.jsx'; import SoftwareProductDeploymentActionHelper from './SoftwareProductDeploymentActionHelper.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; -export function mapStateToProps({softwareProduct}) { - let {softwareProductComponents: {componentsList}, softwareProductDeployment: {deploymentFlavors}} = softwareProduct; - return { - deploymentFlavors, - componentsList - }; +export function mapStateToProps({ softwareProduct }) { + let { + softwareProductComponents: { componentsList }, + softwareProductDeployment: { deploymentFlavors } + } = softwareProduct; + return { + deploymentFlavors, + componentsList + }; } -function mapActionToProps(dispatch, {softwareProductId, version}) { - let modalClassName = 'deployment-flavor-editor'; - return { - onAddDeployment: componentsList => SoftwareProductDeploymentActionHelper.openDeploymentFlavorEditor(dispatch, {softwareProductId, modalClassName, componentsList, version}), - onDeleteDeployment: ({id, model}) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data:{ - msg: i18n('Are you sure you want to delete "{model}"?', {model: model}), - onConfirmed: () => SoftwareProductDeploymentActionHelper.deleteDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId: id, version}) - } - }), - onEditDeployment: (deploymentFlavor, componentsList) => - SoftwareProductDeploymentActionHelper.fetchDeploymentFlavor({softwareProductId, deploymentFlavorId: deploymentFlavor.id, version}).then(response => - SoftwareProductDeploymentActionHelper - .openDeploymentFlavorEditor(dispatch, {softwareProductId, componentsList, modalClassName, deploymentFlavor: {...response.data, id: response.id}, isEdit: true, version}), - ) - }; +function mapActionToProps(dispatch, { softwareProductId, version }) { + let modalClassName = 'deployment-flavor-editor'; + return { + onAddDeployment: componentsList => + SoftwareProductDeploymentActionHelper.openDeploymentFlavorEditor( + dispatch, + { softwareProductId, modalClassName, componentsList, version } + ), + onDeleteDeployment: ({ id, model }) => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + msg: i18n('Are you sure you want to delete "{model}"?', { + model: model + }), + onConfirmed: () => + SoftwareProductDeploymentActionHelper.deleteDeploymentFlavor( + dispatch, + { + softwareProductId, + deploymentFlavorId: id, + version + } + ) + } + }), + onEditDeployment: (deploymentFlavor, componentsList) => + SoftwareProductDeploymentActionHelper.fetchDeploymentFlavor({ + softwareProductId, + deploymentFlavorId: deploymentFlavor.id, + version + }).then(response => + SoftwareProductDeploymentActionHelper.openDeploymentFlavorEditor( + dispatch, + { + softwareProductId, + componentsList, + modalClassName, + deploymentFlavor: { ...response.data, id: response.id }, + isEdit: true, + version + } + ) + ) + }; } -export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(SoftwareProductDeploymentView); +export default connect(mapStateToProps, mapActionToProps, null, { + withRef: true +})(SoftwareProductDeploymentView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentActionHelper.js index bd802b38f4..44b25311e0 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentActionHelper.js @@ -1,101 +1,183 @@ -import {actionTypes} from './SoftwareProductDeploymentConstants.js'; -import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; +import { actionTypes } from './SoftwareProductDeploymentConstants.js'; +import { actionTypes as GlobalModalActions } from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; import pickBy from 'lodash/pickBy'; function baseUrl(vspId, version) { - const versionId = version.id; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/deployment-flavors`; + const versionId = version.id; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/deployment-flavors`; } -function fetchDeploymentFlavorsList({softwareProductId, version}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); +function fetchDeploymentFlavorsList({ softwareProductId, version }) { + return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); } -function fetchDeploymentFlavor({softwareProductId, deploymentFlavorId, version}) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`); +function fetchDeploymentFlavor({ + softwareProductId, + deploymentFlavorId, + version +}) { + return RestAPIUtil.fetch( + `${baseUrl(softwareProductId, version)}/${deploymentFlavorId}` + ); } -function deleteDeploymentFlavor({softwareProductId, deploymentFlavorId, version}) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`); +function deleteDeploymentFlavor({ + softwareProductId, + deploymentFlavorId, + version +}) { + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version)}/${deploymentFlavorId}` + ); } -function createDeploymentFlavor({softwareProductId, data, version}) { - return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, data); +function createDeploymentFlavor({ softwareProductId, data, version }) { + return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, data); } -function editDeploymentFlavor({softwareProductId, deploymentFlavorId, data, version}) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`, data); +function editDeploymentFlavor({ + softwareProductId, + deploymentFlavorId, + data, + version +}) { + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version)}/${deploymentFlavorId}`, + data + ); } const SoftwareProductDeploymentActionHelper = { - fetchDeploymentFlavorsList(dispatch, {softwareProductId, version}) { - return fetchDeploymentFlavorsList({softwareProductId, version}).then(response => { - dispatch({ - type: actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS, - deploymentFlavors: response.results - }); - }); - }, + fetchDeploymentFlavorsList(dispatch, { softwareProductId, version }) { + return fetchDeploymentFlavorsList({ softwareProductId, version }).then( + response => { + dispatch({ + type: actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS, + deploymentFlavors: response.results + }); + } + ); + }, - fetchDeploymentFlavor({softwareProductId, deploymentFlavorId, version}) { - return fetchDeploymentFlavor({softwareProductId, deploymentFlavorId, version}); - }, + fetchDeploymentFlavor({ softwareProductId, deploymentFlavorId, version }) { + return fetchDeploymentFlavor({ + softwareProductId, + deploymentFlavorId, + version + }); + }, - deleteDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId, version}) { - return deleteDeploymentFlavor({softwareProductId, deploymentFlavorId, version}).then(() => { - return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(dispatch, {softwareProductId, version}); - }); - }, + deleteDeploymentFlavor( + dispatch, + { softwareProductId, deploymentFlavorId, version } + ) { + return deleteDeploymentFlavor({ + softwareProductId, + deploymentFlavorId, + version + }).then(() => { + return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList( + dispatch, + { softwareProductId, version } + ); + }); + }, - createDeploymentFlavor(dispatch, {softwareProductId, data, version}) { - return createDeploymentFlavor({softwareProductId, data, version}).then(() => { - return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(dispatch, {softwareProductId, version}); - }); - }, + createDeploymentFlavor(dispatch, { softwareProductId, data, version }) { + return createDeploymentFlavor({ + softwareProductId, + data, + version + }).then(() => { + return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList( + dispatch, + { softwareProductId, version } + ); + }); + }, - editDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId, data, version}) { - let dataWithoutId = pickBy(data, (val, key) => key !== 'id'); - return editDeploymentFlavor({softwareProductId, deploymentFlavorId, data: dataWithoutId, version}).then(() => { - return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList(dispatch, {softwareProductId, version}); - }); - }, + editDeploymentFlavor( + dispatch, + { softwareProductId, deploymentFlavorId, data, version } + ) { + let dataWithoutId = pickBy(data, (val, key) => key !== 'id'); + return editDeploymentFlavor({ + softwareProductId, + deploymentFlavorId, + data: dataWithoutId, + version + }).then(() => { + return SoftwareProductDeploymentActionHelper.fetchDeploymentFlavorsList( + dispatch, + { softwareProductId, version } + ); + }); + }, - closeDeploymentFlavorEditor(dispatch) { - dispatch({ - type: actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA - }); - dispatch({ - type: GlobalModalActions.GLOBAL_MODAL_CLOSE - }); - }, + closeDeploymentFlavorEditor(dispatch) { + dispatch({ + type: + actionTypes.deploymentFlavorEditor + .SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA + }); + dispatch({ + type: GlobalModalActions.GLOBAL_MODAL_CLOSE + }); + }, - openDeploymentFlavorEditor(dispatch, {softwareProductId, modalClassName, deploymentFlavor = {}, componentsList, isEdit = false, version}) { - let alteredDeploymentFlavor = {...deploymentFlavor}; - if (componentsList.length) { - alteredDeploymentFlavor = {...alteredDeploymentFlavor, componentComputeAssociations: deploymentFlavor.componentComputeAssociations ? - [{...deploymentFlavor.componentComputeAssociations[0], componentId: componentsList[0].id}] - : - [{componentId: componentsList[0].id, computeFlavorId: null}] - }; - } - dispatch({ - type: actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA, - deploymentFlavor: alteredDeploymentFlavor - }); - dispatch({ - type: GlobalModalActions.GLOBAL_MODAL_SHOW, - data: { - modalComponentName: modalContentMapper.DEPLOYMENT_FLAVOR_EDITOR, - modalComponentProps: {softwareProductId, version}, - modalClassName, - title: isEdit ? 'Edit Deployment Flavor' : 'Create a New Deployment Flavor' - } - }); - }, + openDeploymentFlavorEditor( + dispatch, + { + softwareProductId, + modalClassName, + deploymentFlavor = {}, + componentsList, + isEdit = false, + version + } + ) { + let alteredDeploymentFlavor = { ...deploymentFlavor }; + if (componentsList.length) { + alteredDeploymentFlavor = { + ...alteredDeploymentFlavor, + componentComputeAssociations: deploymentFlavor.componentComputeAssociations + ? [ + { + ...deploymentFlavor + .componentComputeAssociations[0], + componentId: componentsList[0].id + } + ] + : [ + { + componentId: componentsList[0].id, + computeFlavorId: null + } + ] + }; + } + dispatch({ + type: + actionTypes.deploymentFlavorEditor + .SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA, + deploymentFlavor: alteredDeploymentFlavor + }); + dispatch({ + type: GlobalModalActions.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: modalContentMapper.DEPLOYMENT_FLAVOR_EDITOR, + modalComponentProps: { softwareProductId, version }, + modalClassName, + title: isEdit + ? 'Edit Deployment Flavor' + : 'Create a New Deployment Flavor' + } + }); + } }; -export default SoftwareProductDeploymentActionHelper; +export default SoftwareProductDeploymentActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentConstants.js index 51469b461c..6c0d3efe38 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentConstants.js @@ -16,13 +16,13 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS: null, + FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS: null, - deploymentFlavorEditor: { - DATA_CHANGED: null, - SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA: null, - SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA: null - } + deploymentFlavorEditor: { + DATA_CHANGED: null, + SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA: null, + SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA: null + } }); export const DEPLOYMENT_FLAVORS_FORM_NAME = 'DEPLOYMENT_FLAVORS_FORM_NAME'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentListReducer.js index 8eb91e8fcb..31bf09e945 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentListReducer.js @@ -13,13 +13,13 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductDeploymentConstants.js'; +import { actionTypes } from './SoftwareProductDeploymentConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS: - return [...action.deploymentFlavors]; - default: - return state; - } + switch (action.type) { + case actionTypes.FETCH_SOFTWARE_PRODUCT_DEPLOYMENT_FLAVORS: + return [...action.deploymentFlavors]; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentView.jsx index 860d02c343..e1bdd553a6 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/SoftwareProductDeploymentView.jsx @@ -22,74 +22,82 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx'; export default class SoftwareProductDeployment extends React.Component { - state = { - localFilter: '' - }; + state = { + localFilter: '' + }; - static propTypes = { - onAddDeployment: PropTypes.func.isRequired, - onDeleteDeployment: PropTypes.func.isRequired, - onEditDeployment: PropTypes.func.isRequired, - isReadOnlyMode: PropTypes.bool.isRequired - }; + static propTypes = { + onAddDeployment: PropTypes.func.isRequired, + onDeleteDeployment: PropTypes.func.isRequired, + onEditDeployment: PropTypes.func.isRequired, + isReadOnlyMode: PropTypes.bool.isRequired + }; - render() { - return ( - <div> - {this.renderList()} - </div> - ); - } + render() { + return <div>{this.renderList()}</div>; + } - renderList() { - let {onAddDeployment, isReadOnlyMode, componentsList} = this.props; - return ( - <ListEditorView - plusButtonTitle={i18n('Add Deployment Flavor')} - filterValue={this.state.localFilter} - placeholder={i18n('Filter Deployment')} - onAdd={() => onAddDeployment(componentsList)} - isReadOnlyMode={isReadOnlyMode} - title={i18n('Deployment Flavors')} - onFilter={value => this.setState({localFilter: value})} - twoColumns> - {this.filterList().map(deploymentFlavor => this.renderListItem(deploymentFlavor, isReadOnlyMode))} - </ListEditorView> - ); - } + renderList() { + let { onAddDeployment, isReadOnlyMode, componentsList } = this.props; + return ( + <ListEditorView + plusButtonTitle={i18n('Add Deployment Flavor')} + filterValue={this.state.localFilter} + placeholder={i18n('Filter Deployment')} + onAdd={() => onAddDeployment(componentsList)} + isReadOnlyMode={isReadOnlyMode} + title={i18n('Deployment Flavors')} + onFilter={value => this.setState({ localFilter: value })} + twoColumns> + {this.filterList().map(deploymentFlavor => + this.renderListItem(deploymentFlavor, isReadOnlyMode) + )} + </ListEditorView> + ); + } - renderListItem(deploymentFlavor, isReadOnlyMode) { - let {id, model, description} = deploymentFlavor; - let {onEditDeployment, onDeleteDeployment, componentsList} = this.props; - return ( - <ListEditorItemView - key={id} - className='list-editor-item-view' - isReadOnlyMode={isReadOnlyMode} - onSelect={() => onEditDeployment(deploymentFlavor, componentsList)} - onDelete={() => onDeleteDeployment(deploymentFlavor)}> - <ListEditorItemViewField> - <div className='model'>{model}</div> - </ListEditorItemViewField> - <ListEditorItemViewField> - <div className='description'>{description}</div> - </ListEditorItemViewField> - </ListEditorItemView> - ); - } + renderListItem(deploymentFlavor, isReadOnlyMode) { + let { id, model, description } = deploymentFlavor; + let { + onEditDeployment, + onDeleteDeployment, + componentsList + } = this.props; + return ( + <ListEditorItemView + key={id} + className="list-editor-item-view" + isReadOnlyMode={isReadOnlyMode} + onSelect={() => + onEditDeployment(deploymentFlavor, componentsList) + } + onDelete={() => onDeleteDeployment(deploymentFlavor)}> + <ListEditorItemViewField> + <div className="model">{model}</div> + </ListEditorItemViewField> + <ListEditorItemViewField> + <div className="description">{description}</div> + </ListEditorItemViewField> + </ListEditorItemView> + ); + } - filterList() { - let {deploymentFlavors} = this.props; - let {localFilter} = this.state; + filterList() { + let { deploymentFlavors } = this.props; + let { localFilter } = this.state; - if (localFilter.trim()) { - const filter = new RegExp(escape(localFilter), 'i'); - return deploymentFlavors.filter(({model = '', description = ''}) => { - return escape(model).match(filter) || escape(description).match(filter); - }); - } - else { - return deploymentFlavors; - } - } + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return deploymentFlavors.filter( + ({ model = '', description = '' }) => { + return ( + escape(model).match(filter) || + escape(description).match(filter) + ); + } + ); + } else { + return deploymentFlavors; + } + } } diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js index c24548b7b9..9392317692 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js @@ -13,77 +13,103 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductDeploymentEditorView from './SoftwareProductDeploymentEditorView.jsx'; import SoftwareProdcutDeploymentActionHelper from '../SoftwareProductDeploymentActionHelper.js'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {DEPLOYMENT_FLAVORS_FORM_NAME} from '../SoftwareProductDeploymentConstants.js'; +import { DEPLOYMENT_FLAVORS_FORM_NAME } from '../SoftwareProductDeploymentConstants.js'; export function mapStateToProps({ - licenseModel, - softwareProduct, - currentScreen: {props: {isReadOnlyMode}} + licenseModel, + softwareProduct, + currentScreen: { props: { isReadOnlyMode } } }) { - let { - softwareProductEditor: { - data: currentSoftwareProduct = {} - }, - softwareProductComponents: { - componentsList, - computeFlavor: { - computesList - } - }, - softwareProductDeployment: { - deploymentFlavors, - deploymentFlavorEditor: { - data = {}, - genericFieldInfo, - formReady - } - } - } = softwareProduct; + let { + softwareProductEditor: { data: currentSoftwareProduct = {} }, + softwareProductComponents: { + componentsList, + computeFlavor: { computesList } + }, + softwareProductDeployment: { + deploymentFlavors, + deploymentFlavorEditor: { data = {}, genericFieldInfo, formReady } + } + } = softwareProduct; - let { - featureGroup: { - featureGroupsList - } - } = licenseModel; + let { featureGroup: { featureGroupsList } } = licenseModel; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - let selectedFeatureGroupsIds = currentSoftwareProduct.licensingData ? currentSoftwareProduct.licensingData.featureGroups || [] : []; - let selectedFeatureGroupsList = featureGroupsList - .filter(featureGroup => selectedFeatureGroupsIds.includes(featureGroup.id)) - .map(featureGroup => ({value: featureGroup.id, label: featureGroup.name})); + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); + let selectedFeatureGroupsIds = currentSoftwareProduct.licensingData + ? currentSoftwareProduct.licensingData.featureGroups || [] + : []; + let selectedFeatureGroupsList = featureGroupsList + .filter(featureGroup => + selectedFeatureGroupsIds.includes(featureGroup.id) + ) + .map(featureGroup => ({ + value: featureGroup.id, + label: featureGroup.name + })); - let DFNames = {}; + let DFNames = {}; - deploymentFlavors.map(deployment => { - DFNames[deployment.model.toLowerCase()] = deployment.id; - }); + deploymentFlavors.map(deployment => { + DFNames[deployment.model.toLowerCase()] = deployment.id; + }); - return { - data, - selectedFeatureGroupsList, - genericFieldInfo, - DFNames, - isFormValid, - formReady, - isReadOnlyMode, - componentsList, - computesList, - isEdit: Boolean(data.id) - }; + return { + data, + selectedFeatureGroupsList, + genericFieldInfo, + DFNames, + isFormValid, + formReady, + isReadOnlyMode, + componentsList, + computesList, + isEdit: Boolean(data.id) + }; } -function mapActionsToProps(dispatch, {softwareProductId, version}) { - return { - onDataChanged: (deltaData, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: DEPLOYMENT_FLAVORS_FORM_NAME, customValidations}), - onClose: () => SoftwareProdcutDeploymentActionHelper.closeDeploymentFlavorEditor(dispatch), - onCreate: data => SoftwareProdcutDeploymentActionHelper.createDeploymentFlavor(dispatch, {softwareProductId, data, version}), - onEdit: data => SoftwareProdcutDeploymentActionHelper.editDeploymentFlavor(dispatch, {softwareProductId, deploymentFlavorId: data.id, data, version}), - onValidateForm: () => ValidationHelper.validateForm(dispatch, DEPLOYMENT_FLAVORS_FORM_NAME) - }; +function mapActionsToProps(dispatch, { softwareProductId, version }) { + return { + onDataChanged: (deltaData, customValidations) => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: DEPLOYMENT_FLAVORS_FORM_NAME, + customValidations + }), + onClose: () => + SoftwareProdcutDeploymentActionHelper.closeDeploymentFlavorEditor( + dispatch + ), + onCreate: data => + SoftwareProdcutDeploymentActionHelper.createDeploymentFlavor( + dispatch, + { + softwareProductId, + data, + version + } + ), + onEdit: data => + SoftwareProdcutDeploymentActionHelper.editDeploymentFlavor( + dispatch, + { + softwareProductId, + deploymentFlavorId: data.id, + data, + version + } + ), + onValidateForm: () => + ValidationHelper.validateForm( + dispatch, + DEPLOYMENT_FLAVORS_FORM_NAME + ) + }; } -export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductDeploymentEditorView); +export default connect(mapStateToProps, mapActionsToProps)( + SoftwareProductDeploymentEditorView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorReducer.js index 70836e8ff9..16e73d2162 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorReducer.js @@ -13,32 +13,37 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, DEPLOYMENT_FLAVORS_FORM_NAME} from '../SoftwareProductDeploymentConstants.js';; +import { + actionTypes, + DEPLOYMENT_FLAVORS_FORM_NAME +} from '../SoftwareProductDeploymentConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA: - return { - ...state, - data: action.deploymentFlavor, - formReady: null, - formName: DEPLOYMENT_FLAVORS_FORM_NAME, - genericFieldInfo: { - 'description' : { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 500}] - }, - 'model' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}] - } - } - }; - case actionTypes.deploymentFlavorEditor.SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA: - return {}; - default: - return state; - } + switch (action.type) { + case actionTypes.deploymentFlavorEditor + .SOFTWARE_PRODUCT_DEPLOYMENT_FILL_DATA: + return { + ...state, + data: action.deploymentFlavor, + formReady: null, + formName: DEPLOYMENT_FLAVORS_FORM_NAME, + genericFieldInfo: { + description: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 500 }] + }, + model: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + } + } + }; + case actionTypes.deploymentFlavorEditor + .SOFTWARE_PRODUCT_DEPLOYMENT_CLEAR_DATA: + return {}; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorView.jsx index 7c9ae438d9..e44d2bd966 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditorView.jsx @@ -11,127 +11,240 @@ import SelectActionTableCell from 'nfvo-components/table/SelectActionTableCell.j import Validator from 'nfvo-utils/Validator.js'; export default class SoftwareProductDeploymentEditorView extends React.Component { - render() { - let {data, isEdit, onClose, onDataChanged, isReadOnlyMode, selectedFeatureGroupsList, componentsList, computesList, genericFieldInfo} = this.props; - let {model, description, featureGroupId, componentComputeAssociations = []} = data; - let featureGroupsExist = selectedFeatureGroupsList.length > 0; - return ( - <div> - {genericFieldInfo && <Form - ref='validationForm' - hasButtons={true} - labledButtons={true} - isReadOnlyMode={isReadOnlyMode} - onSubmit={ () => this.submit() } - submitButtonText={isEdit ? i18n('Save') : i18n('Create')} - onReset={ () => onClose() } - onValidateForm={() => this.validate() } - isValid={this.props.isFormValid} - formReady={this.props.formReady} - className='vsp-deployment-editor'> - <GridSection hasLastColSet> - <GridItem colSpan={1}> - <Input - onChange={model => onDataChanged({model}, {model: model => this.validateName(model)})} - label={i18n('Model')} - value={model} - data-test-id='deployment-model' - isValid={genericFieldInfo.model.isValid} - errorText={genericFieldInfo.model.errorText} - isRequired={true} - type='text'/> - </GridItem> - <GridItem colSpan={3} lastColInRow> - <Input - onChange={description => onDataChanged({description})} - label={i18n('Description')} - value={description} - data-test-id='deployment-description' - isValid={genericFieldInfo.description.isValid} - errorText={genericFieldInfo.description.errorText} - type='text'/> - </GridItem> - </GridSection> - <GridSection className={`deployment-feature-groups-section${!featureGroupsExist ? ' no-feature-groups' : ''}`} title={i18n('License Details')} hasLastColSet> - <GridItem colSpan={1}> - <SelectInput - data-test-id='deployment-feature-groups' - label={i18n('Feature Group')} - value={featureGroupId} - onChange={featureGroup => onDataChanged({featureGroupId: featureGroup ? featureGroup.value : null})} - type='select' - clearable={true} - disabled={isReadOnlyMode || !featureGroupsExist} - className='field-section' - options={selectedFeatureGroupsList}/> - </GridItem> - </GridSection> - {!featureGroupsExist && <GridSection className='deployment-feature-group-warning-section'> - <GridItem colSpan={3}> - <span>{i18n('Please assign Feature Groups in VSP General')}</span> - </GridItem> - </GridSection>} - <GridSection title={i18n('Assign VFCs and Compute Flavors')} className='vfc-table' hasLastColSet> - <GridItem colSpan={4} lastColInRow> - <SelectActionTable - columns={['Virtual Function Components', 'Compute Flavors']} - numOfIcons={0}> - {componentComputeAssociations.map( (association, index) => - <SelectActionTableRow key={association.componentId}> - <SelectActionTableCell - options={ - componentsList - .map(component => ({value: component.id, label: component.displayName}) ) - } - selected={association.componentId} - onChange={componentId => { - let newAssociations = [...componentComputeAssociations]; - newAssociations[index] = {...newAssociations[index], componentId}; - onDataChanged({componentComputeAssociations: newAssociations}); - }} - disabled={true}/> - <SelectActionTableCell - options={ - computesList - .filter(compute => compute.componentId === association.componentId) - .map(compute => ({value: compute.computeFlavorId, label: compute.name}) ) - } - selected={association.computeFlavorId} - onChange={computeFlavorId => { - let newAssociations = [...componentComputeAssociations]; - newAssociations[index] = {...newAssociations[index], computeFlavorId}; - onDataChanged({componentComputeAssociations: newAssociations}); - }} - disabled={isReadOnlyMode}/> - </SelectActionTableRow> - )} - </SelectActionTable> - </GridItem> - </GridSection> - </Form>} - </div> - ); - } + render() { + let { + data, + isEdit, + onClose, + onDataChanged, + isReadOnlyMode, + selectedFeatureGroupsList, + componentsList, + computesList, + genericFieldInfo + } = this.props; + let { + model, + description, + featureGroupId, + componentComputeAssociations = [] + } = data; + let featureGroupsExist = selectedFeatureGroupsList.length > 0; + return ( + <div> + {genericFieldInfo && ( + <Form + ref="validationForm" + hasButtons={true} + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + onSubmit={() => this.submit()} + submitButtonText={ + isEdit ? i18n('Save') : i18n('Create') + } + onReset={() => onClose()} + onValidateForm={() => this.validate()} + isValid={this.props.isFormValid} + formReady={this.props.formReady} + className="vsp-deployment-editor"> + <GridSection hasLastColSet> + <GridItem colSpan={1}> + <Input + onChange={model => + onDataChanged( + { model }, + { + model: model => + this.validateName(model) + } + ) + } + label={i18n('Model')} + value={model} + data-test-id="deployment-model" + isValid={genericFieldInfo.model.isValid} + errorText={genericFieldInfo.model.errorText} + isRequired={true} + type="text" + /> + </GridItem> + <GridItem colSpan={3} lastColInRow> + <Input + onChange={description => + onDataChanged({ description }) + } + label={i18n('Description')} + value={description} + data-test-id="deployment-description" + isValid={ + genericFieldInfo.description.isValid + } + errorText={ + genericFieldInfo.description.errorText + } + type="text" + /> + </GridItem> + </GridSection> + <GridSection + className={`deployment-feature-groups-section${ + !featureGroupsExist ? ' no-feature-groups' : '' + }`} + title={i18n('License Details')} + hasLastColSet> + <GridItem colSpan={1}> + <SelectInput + data-test-id="deployment-feature-groups" + label={i18n('Feature Group')} + value={featureGroupId} + onChange={featureGroup => + onDataChanged({ + featureGroupId: featureGroup + ? featureGroup.value + : null + }) + } + type="select" + clearable={true} + disabled={ + isReadOnlyMode || !featureGroupsExist + } + className="field-section" + options={selectedFeatureGroupsList} + /> + </GridItem> + </GridSection> + {!featureGroupsExist && ( + <GridSection className="deployment-feature-group-warning-section"> + <GridItem colSpan={3}> + <span> + {i18n( + 'Please assign Feature Groups in VSP General' + )} + </span> + </GridItem> + </GridSection> + )} + <GridSection + title={i18n('Assign VFCs and Compute Flavors')} + className="vfc-table" + hasLastColSet> + <GridItem colSpan={4} lastColInRow> + <SelectActionTable + columns={[ + 'Virtual Function Components', + 'Compute Flavors' + ]} + numOfIcons={0}> + {componentComputeAssociations.map( + (association, index) => ( + <SelectActionTableRow + key={association.componentId}> + <SelectActionTableCell + options={componentsList.map( + component => ({ + value: component.id, + label: + component.displayName + }) + )} + selected={ + association.componentId + } + onChange={componentId => { + let newAssociations = [ + ...componentComputeAssociations + ]; + newAssociations[ + index + ] = { + ...newAssociations[ + index + ], + componentId + }; + onDataChanged({ + componentComputeAssociations: newAssociations + }); + }} + disabled={true} + /> + <SelectActionTableCell + options={computesList + .filter( + compute => + compute.componentId === + association.componentId + ) + .map(compute => ({ + value: + compute.computeFlavorId, + label: compute.name + }))} + selected={ + association.computeFlavorId + } + onChange={computeFlavorId => { + let newAssociations = [ + ...componentComputeAssociations + ]; + newAssociations[ + index + ] = { + ...newAssociations[ + index + ], + computeFlavorId + }; + onDataChanged({ + componentComputeAssociations: newAssociations + }); + }} + disabled={isReadOnlyMode} + /> + </SelectActionTableRow> + ) + )} + </SelectActionTable> + </GridItem> + </GridSection> + </Form> + )} + </div> + ); + } - validateName(value) { - const {data: {id = ''}, DFNames} = this.props; - const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: DFNames}); + validateName(value) { + const { data: { id = '' }, DFNames } = this.props; + const isExists = Validator.isItemNameAlreadyExistsInList({ + itemId: id, + itemName: value, + list: DFNames + }); - return !isExists ? {isValid: true, errorText: ''} : - {isValid: false, errorText: i18n('Deployment flavor by the name \'' + value + '\' already exists. Deployment flavor name must be unique')}; - } + return !isExists + ? { isValid: true, errorText: '' } + : { + isValid: false, + errorText: i18n( + "Deployment flavor by the name '" + + value + + "' already exists. Deployment flavor name must be unique" + ) + }; + } - submit(){ - let {isEdit, onCreate, onEdit, onClose, data} = this.props; - if (isEdit) { - onEdit(data); - } else { - onCreate(data); - } - onClose(); - } + submit() { + let { isEdit, onCreate, onEdit, onClose, data } = this.props; + if (isEdit) { + onEdit(data); + } else { + onCreate(data); + } + onClose(); + } - validate() { - this.props.onValidateForm(); - } + validate() { + this.props.onValidateForm(); + } } diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js index 0973537d43..8a3279a02c 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js @@ -13,80 +13,140 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; import SoftwareProductDetailsView from './SoftwareProductDetailsView.jsx'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -import {PRODUCT_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; -import {actionTypes as modalActionTypes, modalSizes} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; -import {forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { PRODUCT_QUESTIONNAIRE } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { + actionTypes as modalActionTypes, + modalSizes +} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js'; +import { forms } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; export const mapStateToProps = ({ - finalizedLicenseModelList, - archivedLicenseModelList, - softwareProduct, - licenseModel: {licenseAgreement, featureGroup} + finalizedLicenseModelList, + archivedLicenseModelList, + softwareProduct, + licenseModel: { licenseAgreement, featureGroup } }) => { + let { + softwareProductEditor: { + data: currentSoftwareProduct, + licensingVersionsList = [], + genericFieldInfo + }, + softwareProductCategories, + softwareProductQuestionnaire + } = softwareProduct; + let { licensingData = {}, licensingVersion } = currentSoftwareProduct; + let licenseAgreementList = [], + filteredFeatureGroupsList = []; + licenseAgreementList = licensingVersion + ? licenseAgreement.licenseAgreementList + : []; + if (licensingVersion && licensingData && licensingData.licenseAgreement) { + let selectedLicenseAgreement = licenseAgreementList.find( + la => la.id === licensingData.licenseAgreement + ); + if (selectedLicenseAgreement) { + let featureGroupsList = featureGroup.featureGroupsList.filter( + ({ referencingLicenseAgreements }) => + referencingLicenseAgreements.includes( + selectedLicenseAgreement.id + ) + ); + if (featureGroupsList.length) { + filteredFeatureGroupsList = featureGroupsList.map( + featureGroup => ({ + enum: featureGroup.id, + title: featureGroup.name + }) + ); + } + } + } + let { + qdata, + qgenericFieldInfo: qGenericFieldInfo, + dataMap + } = softwareProductQuestionnaire; - let {softwareProductEditor: {data: currentSoftwareProduct, licensingVersionsList = [], genericFieldInfo}, softwareProductCategories, softwareProductQuestionnaire} = softwareProduct; - let {licensingData = {}, licensingVersion} = currentSoftwareProduct; - let licenseAgreementList = [], filteredFeatureGroupsList = []; - licenseAgreementList = licensingVersion ? - licenseAgreement.licenseAgreementList : []; - if(licensingVersion && licensingData && licensingData.licenseAgreement) { - let selectedLicenseAgreement = licenseAgreementList.find(la => la.id === licensingData.licenseAgreement); - if (selectedLicenseAgreement) { - let featureGroupsList = featureGroup.featureGroupsList.filter(({referencingLicenseAgreements}) => referencingLicenseAgreements.includes(selectedLicenseAgreement.id)); - if (featureGroupsList.length) { - filteredFeatureGroupsList = featureGroupsList.map(featureGroup => ({enum: featureGroup.id, title: featureGroup.name})); - } - } - } - let {qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap} = softwareProductQuestionnaire; - - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - const isVendorArchived = archivedLicenseModelList.find(item => item.id === currentSoftwareProduct.vendorId); - return { - currentSoftwareProduct, - softwareProductCategories, - licenseAgreementList, - licensingVersionsList, - featureGroupsList: filteredFeatureGroupsList, - finalizedLicenseModelList, - qdata, - isFormValid, - genericFieldInfo, - qGenericFieldInfo, - dataMap, - isVendorArchived: !!isVendorArchived - }; - + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); + const isVendorArchived = archivedLicenseModelList.find( + item => item.id === currentSoftwareProduct.vendorId + ); + return { + currentSoftwareProduct, + softwareProductCategories, + licenseAgreementList, + licensingVersionsList, + featureGroupsList: filteredFeatureGroupsList, + finalizedLicenseModelList, + qdata, + isFormValid, + genericFieldInfo, + qGenericFieldInfo, + dataMap, + isVendorArchived: !!isVendorArchived + }; }; -export const mapActionsToProps = (dispatch, {version}) => { - return { - onDataChanged: (deltaData, formName) => ValidationHelper.dataChanged(dispatch, {deltaData, formName}), - onVendorParamChanged: (deltaData, formName) => SoftwareProductActionHelper.softwareProductEditorVendorChanged(dispatch, {deltaData, formName}), - onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: PRODUCT_QUESTIONNAIRE}), - onValidityChanged: isValidityData => SoftwareProductActionHelper.setIsValidityData(dispatch, {isValidityData}), - onSubmit: (softwareProduct, qdata) => SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, qdata, version}), - onArchivedVendorRemove: ({onVendorParamChanged, finalizedLicenseModelList, vendorName}) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_SHOW, - data:{ - title: i18n('Change Archived VLM'), - modalComponentName: modalContentMapper.VENDOR_SELECTOR, - modalComponentProps: { - size: modalSizes.MEDIUM, - finalizedLicenseModelList, - vendorName, - onClose: () => dispatch({type: modalActionTypes.GLOBAL_MODAL_CLOSE}), - onConfirm: (vendorId) => onVendorParamChanged({vendorId}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS) - } - } - }) - }; +export const mapActionsToProps = (dispatch, { version }) => { + return { + onDataChanged: (deltaData, formName) => + ValidationHelper.dataChanged(dispatch, { deltaData, formName }), + onVendorParamChanged: (deltaData, formName) => + SoftwareProductActionHelper.softwareProductEditorVendorChanged( + dispatch, + { deltaData, formName } + ), + onQDataChanged: deltaData => + ValidationHelper.qDataChanged(dispatch, { + deltaData, + qName: PRODUCT_QUESTIONNAIRE + }), + onValidityChanged: isValidityData => + SoftwareProductActionHelper.setIsValidityData(dispatch, { + isValidityData + }), + onSubmit: (softwareProduct, qdata) => + SoftwareProductActionHelper.updateSoftwareProduct(dispatch, { + softwareProduct, + qdata, + version + }), + onArchivedVendorRemove: ({ + onVendorParamChanged, + finalizedLicenseModelList, + vendorName + }) => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + title: i18n('Change Archived VLM'), + modalComponentName: modalContentMapper.VENDOR_SELECTOR, + modalComponentProps: { + size: modalSizes.MEDIUM, + finalizedLicenseModelList, + vendorName, + onClose: () => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }), + onConfirm: vendorId => + onVendorParamChanged( + { vendorId }, + forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + ) + } + } + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductDetailsView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductDetailsView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js index 1a293264c3..1e4a0df787 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js @@ -13,49 +13,56 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { + actionTypes, + forms +} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED: - return { - ...state, - isValidityData: action.isValidityData - }; - case actionTypes.SOFTWARE_PRODUCT_LOADED: - return { - ...state, - formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS, - genericFieldInfo: { - 'name' : { - isValid: true, - errorText: '', - validations: [{type: 'validateName', data: true}, {type: 'maxLength', data: 25}, {type: 'required', data: true}] - }, - 'description' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}] - } - }, - data: action.response - }; - case actionTypes.TOGGLE_NAVIGATION_ITEM: - return { - ...state, - mapOfExpandedIds: action.mapOfExpandedIds - }; - case actionTypes.LOAD_LICENSING_VERSIONS_LIST: - return { - ...state, - licensingVersionsList: action.licensingVersionsList - }; - case actionTypes.CANDIDATE_IN_PROCESS: - return { - ...state, - data: {...state.data, candidateOnboardingOrigin: true} - }; - default: - return state; - } + switch (action.type) { + case actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED: + return { + ...state, + isValidityData: action.isValidityData + }; + case actionTypes.SOFTWARE_PRODUCT_LOADED: + return { + ...state, + formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS, + genericFieldInfo: { + name: { + isValid: true, + errorText: '', + validations: [ + { type: 'validateName', data: true }, + { type: 'maxLength', data: 25 }, + { type: 'required', data: true } + ] + }, + description: { + isValid: true, + errorText: '', + validations: [{ type: 'required', data: true }] + } + }, + data: action.response + }; + case actionTypes.TOGGLE_NAVIGATION_ITEM: + return { + ...state, + mapOfExpandedIds: action.mapOfExpandedIds + }; + case actionTypes.LOAD_LICENSING_VERSIONS_LIST: + return { + ...state, + licensingVersionsList: action.licensingVersionsList + }; + case actionTypes.CANDIDATE_IN_PROCESS: + return { + ...state, + data: { ...state.data, candidateOnboardingOrigin: true } + }; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsVendorSelector.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsVendorSelector.jsx index c2a3e0bd02..9c20723689 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsVendorSelector.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsVendorSelector.jsx @@ -22,57 +22,77 @@ import Input from 'nfvo-components/input/validation/Input.jsx'; import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js'; class VendorSelector extends React.Component { - static propTypes = { - finalizedLicenseModelList: PropTypes.array, - vendorName: PropTypes.string, - onClose: PropTypes.func.isRequired, - onConfirm: PropTypes.func.isRequired - } - constructor(props){ - super(props); - const selectedValue = props.finalizedLicenseModelList.length ? props.finalizedLicenseModelList[0].id : ''; - this.state = { - selectedValue - }; - } - submit() { - const vendor = this.props.finalizedLicenseModelList.find(item => item.id === this.state.selectedValue); - this.props.onConfirm(vendor.id); - this.props.onClose(); - } - render() { - const {finalizedLicenseModelList, vendorName, onClose} = this.props; - const {selectedValue} = this.state; - return ( - <div className='vsp-details-vendor-select'> - <Form - onSubmit={() => this.submit()} - onReset={() => onClose()} - isValid = {!!selectedValue} - submitButtonText={i18n('Save')} - hasButtons={true}> - <div className='vendor-selector-modal-title'>{`${i18n('The VLM')} '${vendorName}' ${i18n('assigned to this VSP is archived')}.`}</div> - <div className='vendor-selector-modal-additional-text'>{i18n('If you select a different VLM you will not be able to reselect the archived VLM.')}</div> - <Input - data-test-id='vsp-vendor-name-select' - label={i18n('Vendor')} - type='select' - onChange={e => {this.setState({ - selectedValue: e.target.options[e.target.selectedIndex].value - });}} - value={selectedValue}> - <option key='emtyVendor' value=''>{i18n('please select...')}</option> - {sortByStringProperty( - finalizedLicenseModelList, - 'name' - ).map(lm => <option key={lm.id} value={lm.id}>{lm.name}</option>) - } - </Input> - </Form> - </div> - ); - } + static propTypes = { + finalizedLicenseModelList: PropTypes.array, + vendorName: PropTypes.string, + onClose: PropTypes.func.isRequired, + onConfirm: PropTypes.func.isRequired + }; + constructor(props) { + super(props); + const selectedValue = props.finalizedLicenseModelList.length + ? props.finalizedLicenseModelList[0].id + : ''; + this.state = { + selectedValue + }; + } + submit() { + const vendor = this.props.finalizedLicenseModelList.find( + item => item.id === this.state.selectedValue + ); + this.props.onConfirm(vendor.id); + this.props.onClose(); + } + render() { + const { finalizedLicenseModelList, vendorName, onClose } = this.props; + const { selectedValue } = this.state; + return ( + <div className="vsp-details-vendor-select"> + <Form + onSubmit={() => this.submit()} + onReset={() => onClose()} + isValid={!!selectedValue} + submitButtonText={i18n('Save')} + hasButtons={true}> + <div className="vendor-selector-modal-title">{`${i18n( + 'The VLM' + )} '${vendorName}' ${i18n( + 'assigned to this VSP is archived' + )}.`}</div> + <div className="vendor-selector-modal-additional-text"> + {i18n( + 'If you select a different VLM you will not be able to reselect the archived VLM.' + )} + </div> + <Input + data-test-id="vsp-vendor-name-select" + label={i18n('Vendor')} + type="select" + onChange={e => { + this.setState({ + selectedValue: + e.target.options[e.target.selectedIndex] + .value + }); + }} + value={selectedValue}> + <option key="emtyVendor" value=""> + {i18n('please select...')} + </option> + {sortByStringProperty( + finalizedLicenseModelList, + 'name' + ).map(lm => ( + <option key={lm.id} value={lm.id}> + {lm.name} + </option> + ))} + </Input> + </Form> + </div> + ); + } } export default VendorSelector; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx index 24aa319c24..12b1eadc86 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx @@ -13,7 +13,7 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import i18n from 'nfvo-utils/i18n/i18n.js'; @@ -24,427 +24,642 @@ import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx'; import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js'; -import {forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; +import { forms } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js'; -const DeprecatedVlmInfo = ({vendorName, onVendorRemove}) => { - return ( - <div className='depricated-vlm-info'> - <Input - data-test-id='vsp-vendor-name' - isRequired={true} - onClick={() => onVendorRemove()} - label={i18n('Vendor')} - type='select' - value={`${vendorName} (Archived)`}> - <option key={vendorName} value={`${vendorName} (Archived)`}>{`${vendorName} (Archived)`}</option> - </Input> - </div> - ); +const DeprecatedVlmInfo = ({ vendorName, onVendorRemove }) => { + return ( + <div className="depricated-vlm-info"> + <Input + data-test-id="vsp-vendor-name" + isRequired={true} + onClick={() => onVendorRemove()} + label={i18n('Vendor')} + type="select" + value={`${vendorName} (Archived)`}> + <option + key={vendorName} + value={`${vendorName} (Archived)`}>{`${vendorName} (Archived)`}</option> + </Input> + </div> + ); }; class GeneralSection extends React.Component { - static propTypes = { - vendorId: PropTypes.string, - name: PropTypes.string, - description: PropTypes.string, - subCategory: PropTypes.string, - softwareProductCategories: PropTypes.array, - finalizedLicenseModelList: PropTypes.array, - onDataChanged: PropTypes.func.isRequired, - onVendorParamChanged: PropTypes.func.isRequired, - onSelectSubCategory: PropTypes.func.isRequired, - isVendorArchived: PropTypes.bool, - onArchivedVendorRemove: PropTypes.func - }; + static propTypes = { + vendorId: PropTypes.string, + name: PropTypes.string, + description: PropTypes.string, + subCategory: PropTypes.string, + softwareProductCategories: PropTypes.array, + finalizedLicenseModelList: PropTypes.array, + onDataChanged: PropTypes.func.isRequired, + onVendorParamChanged: PropTypes.func.isRequired, + onSelectSubCategory: PropTypes.func.isRequired, + isVendorArchived: PropTypes.bool, + onArchivedVendorRemove: PropTypes.func + }; - onVendorParamChanged(e) { - const selectedIndex = e.target.selectedIndex; - const vendorId = e.target.options[selectedIndex].value; - this.props.onVendorParamChanged({vendorId}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS); + onVendorParamChanged(e) { + const selectedIndex = e.target.selectedIndex; + const vendorId = e.target.options[selectedIndex].value; + this.props.onVendorParamChanged( + { vendorId }, + forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + ); + } - } + onSelectSubCategory(e) { + const selectedIndex = e.target.selectedIndex; + const subCategory = e.target.options[selectedIndex].value; + this.props.onSelectSubCategory(subCategory); + } + onVendorRemove() { + const { + finalizedLicenseModelList, + vendorName, + onVendorParamChanged + } = this.props; + this.props.onArchivedVendorRemove({ + finalizedLicenseModelList, + onVendorParamChanged, + vendorName + }); + } - onSelectSubCategory(e) { - const selectedIndex = e.target.selectedIndex; - const subCategory = e.target.options[selectedIndex].value; - this.props.onSelectSubCategory(subCategory); - } - onVendorRemove() { - const {finalizedLicenseModelList, vendorName, onVendorParamChanged} = this.props; - this.props.onArchivedVendorRemove({finalizedLicenseModelList, onVendorParamChanged, vendorName}); - } - - render (){ - let {genericFieldInfo} = this.props; - return ( - <div> - {genericFieldInfo && <GridSection title={i18n('General')} className='grid-section-general'> - <GridItem> - <Input - data-test-id='vsp-name' - label={i18n('Name')} - type='text' - value={this.props.name} - isRequired={true} - errorText={genericFieldInfo.name.errorText} - isValid={genericFieldInfo.name.isValid} - onChange={name => name.length <= 25 && this.props.onDataChanged({name}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)}/> - {this.props.isVendorArchived ? - <DeprecatedVlmInfo onVendorRemove={()=>this.onVendorRemove()} vendorName={this.props.vendorName} /> : - <Input - data-test-id='vsp-vendor-name' - label={i18n('Vendor')} - type='select' - value={this.props.vendorId} - onChange={e => this.onVendorParamChanged(e)}> - {sortByStringProperty( - this.props.finalizedLicenseModelList, - 'name' - ).map(lm => <option key={lm.id} value={lm.id}>{lm.name}</option>) - } - </Input> - } - <Input - data-test-id='vsp-category-name' - label={i18n('Category')} - type='select' - value={this.props.subCategory} - onChange={e => this.onSelectSubCategory(e)}> - { - this.props.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> - <Input - data-test-id='vsp-description' - label={i18n('Description')} - type='textarea' - isRequired={true} - isValid={genericFieldInfo.description.isValid} - errorText={genericFieldInfo.description.errorText} - value={this.props.description} - onChange={description => this.props.onDataChanged({description}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)}/> - </GridItem> - </GridSection>} - </div>); - } + render() { + let { genericFieldInfo } = this.props; + return ( + <div> + {genericFieldInfo && ( + <GridSection + title={i18n('General')} + className="grid-section-general"> + <GridItem> + <Input + data-test-id="vsp-name" + label={i18n('Name')} + type="text" + value={this.props.name} + isRequired={true} + errorText={genericFieldInfo.name.errorText} + isValid={genericFieldInfo.name.isValid} + onChange={name => + name.length <= 25 && + this.props.onDataChanged( + { name }, + forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + ) + } + /> + {this.props.isVendorArchived ? ( + <DeprecatedVlmInfo + onVendorRemove={() => this.onVendorRemove()} + vendorName={this.props.vendorName} + /> + ) : ( + <Input + data-test-id="vsp-vendor-name" + label={i18n('Vendor')} + type="select" + value={this.props.vendorId} + onChange={e => + this.onVendorParamChanged(e) + }> + {sortByStringProperty( + this.props.finalizedLicenseModelList, + 'name' + ).map(lm => ( + <option key={lm.id} value={lm.id}> + {lm.name} + </option> + ))} + </Input> + )} + <Input + data-test-id="vsp-category-name" + label={i18n('Category')} + type="select" + value={this.props.subCategory} + onChange={e => this.onSelectSubCategory(e)}> + {this.props.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> + <Input + data-test-id="vsp-description" + label={i18n('Description')} + type="textarea" + isRequired={true} + isValid={genericFieldInfo.description.isValid} + errorText={ + genericFieldInfo.description.errorText + } + value={this.props.description} + onChange={description => + this.props.onDataChanged( + { description }, + forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + ) + } + /> + </GridItem> + </GridSection> + )} + </div> + ); + } } class LicensesSection extends React.Component { - static propTypes = { - onVendorParamChanged: PropTypes.func.isRequired, - vendorId: PropTypes.string, - licensingVersion: PropTypes.string, - licensingVersionsList: PropTypes.array, - licensingData: PropTypes.shape({ - licenceAgreement: PropTypes.string, - featureGroups: PropTypes.array - }), - onFeatureGroupsChanged: PropTypes.func.isRequired, - onLicensingDataChanged: PropTypes.func.isRequired, - featureGroupsList: PropTypes.array, - licenseAgreementList: PropTypes.array, - isVendorArchived: PropTypes.bool - }; + static propTypes = { + onVendorParamChanged: PropTypes.func.isRequired, + vendorId: PropTypes.string, + licensingVersion: PropTypes.string, + licensingVersionsList: PropTypes.array, + licensingData: PropTypes.shape({ + licenceAgreement: PropTypes.string, + featureGroups: PropTypes.array + }), + onFeatureGroupsChanged: PropTypes.func.isRequired, + onLicensingDataChanged: PropTypes.func.isRequired, + featureGroupsList: PropTypes.array, + licenseAgreementList: PropTypes.array, + isVendorArchived: PropTypes.bool + }; - onVendorParamChanged(e) { - const selectedIndex = e.target.selectedIndex; - const licensingVersion = e.target.options[selectedIndex].value; - this.props.onVendorParamChanged({vendorId: this.props.vendorId, licensingVersion}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS); - } + onVendorParamChanged(e) { + const selectedIndex = e.target.selectedIndex; + const licensingVersion = e.target.options[selectedIndex].value; + this.props.onVendorParamChanged( + { vendorId: this.props.vendorId, licensingVersion }, + forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + ); + } - onLicensingDataChanged(e) { - const selectedIndex = e.target.selectedIndex; - const licenseAgreement = e.target.options[selectedIndex].value; - this.props.onLicensingDataChanged({licenseAgreement, featureGroups: []}); - } + onLicensingDataChanged(e) { + const selectedIndex = e.target.selectedIndex; + const licenseAgreement = e.target.options[selectedIndex].value; + this.props.onLicensingDataChanged({ + licenseAgreement, + featureGroups: [] + }); + } - render(){ - return ( - <GridSection title={i18n('Licenses')}> - <GridItem> - <Input - data-test-id='vsp-licensing-version' - onChange={e => this.onVendorParamChanged(e)} - value={this.props.licensingVersion || ''} - label={i18n('Licensing Version')} - disabled={this.props.isVendorArchived} - type='select'> - {this.props.licensingVersionsList.map(version => - <option - key={version.enum} - value={version.enum}>{version.title} - </option> - )} - </Input> - </GridItem> - <GridItem> - <Input - data-test-id='vsp-license-agreement' - label={i18n('License Agreement')} - type='select' - disabled={this.props.isVendorArchived} - value={this.props.licensingData.licenseAgreement ? this.props.licensingData.licenseAgreement : '' } - onChange={(e) => this.onLicensingDataChanged(e)}> - <option key='placeholder' value=''>{i18n('Select...')}</option> - {this.props.licenseAgreementList.map(la => <option value={la.id} key={la.id}>{la.name}</option>)} - </Input> - </GridItem> - <GridItem> - {this.props.licensingData.licenseAgreement && ( - <InputOptions - data-test-id='vsp-feature-group' - type='select' - isMultiSelect={true} - onInputChange={()=>{}} - disabled={this.props.isVendorArchived} - onEnumChange={featureGroups => this.props.onFeatureGroupsChanged({featureGroups})} - multiSelectedEnum={this.props.licensingData.featureGroups} - name='feature-groups' - label={i18n('Feature Groups')} - clearable={false} - values={this.props.featureGroupsList}/>) - } - </GridItem> - </GridSection> - ); - } + render() { + return ( + <GridSection title={i18n('Licenses')}> + <GridItem> + <Input + data-test-id="vsp-licensing-version" + onChange={e => this.onVendorParamChanged(e)} + value={this.props.licensingVersion || ''} + label={i18n('Licensing Version')} + disabled={this.props.isVendorArchived} + type="select"> + {this.props.licensingVersionsList.map(version => ( + <option key={version.enum} value={version.enum}> + {version.title} + </option> + ))} + </Input> + </GridItem> + <GridItem> + <Input + data-test-id="vsp-license-agreement" + label={i18n('License Agreement')} + type="select" + disabled={this.props.isVendorArchived} + value={ + this.props.licensingData.licenseAgreement + ? this.props.licensingData.licenseAgreement + : '' + } + onChange={e => this.onLicensingDataChanged(e)}> + <option key="placeholder" value=""> + {i18n('Select...')} + </option> + {this.props.licenseAgreementList.map(la => ( + <option value={la.id} key={la.id}> + {la.name} + </option> + ))} + </Input> + </GridItem> + <GridItem> + {this.props.licensingData.licenseAgreement && ( + <InputOptions + data-test-id="vsp-feature-group" + type="select" + isMultiSelect={true} + onInputChange={() => {}} + disabled={this.props.isVendorArchived} + onEnumChange={featureGroups => + this.props.onFeatureGroupsChanged({ + featureGroups + }) + } + multiSelectedEnum={ + this.props.licensingData.featureGroups + } + name="feature-groups" + label={i18n('Feature Groups')} + clearable={false} + values={this.props.featureGroupsList} + /> + )} + </GridItem> + </GridSection> + ); + } } -const AvailabilitySection = (props) => ( - <GridSection title={i18n('Availability')}> - <GridItem colSpan={2}> - <Input - data-test-id='vsp-use-availability-zone' - label={i18n('Use Availability Zones for High Availability')} - type='checkbox' - checked={props.dataMap['general/availability/useAvailabilityZonesForHighAvailability']} - value={props.dataMap['general/availability/useAvailabilityZonesForHighAvailability']} - onChange={(aZone) => props.onQDataChanged({'general/availability/useAvailabilityZonesForHighAvailability' : aZone})} /> - </GridItem> - </GridSection> +const AvailabilitySection = props => ( + <GridSection title={i18n('Availability')}> + <GridItem colSpan={2}> + <Input + data-test-id="vsp-use-availability-zone" + label={i18n('Use Availability Zones for High Availability')} + type="checkbox" + checked={ + props.dataMap[ + 'general/availability/useAvailabilityZonesForHighAvailability' + ] + } + value={ + props.dataMap[ + 'general/availability/useAvailabilityZonesForHighAvailability' + ] + } + onChange={aZone => + props.onQDataChanged({ + 'general/availability/useAvailabilityZonesForHighAvailability': aZone + }) + } + /> + </GridItem> + </GridSection> ); -const RegionsSection = (props) => ( - <GridSection title={i18n('Regions')}> - <GridItem> - <InputOptions - data-test-id='vsp-regions' - type='select' - isMultiSelect={true} - onInputChange={()=>{}} - onEnumChange={(regions) => props.onQDataChanged({'general/regionsData/regions' : regions})} - multiSelectedEnum={props.dataMap['general/regionsData/regions']} - name='vsp-regions' - clearable={false} - values={props.genericFieldInfo['general/regionsData/regions'].enum} /> - </GridItem> - </GridSection> +const RegionsSection = props => ( + <GridSection title={i18n('Regions')}> + <GridItem> + <InputOptions + data-test-id="vsp-regions" + type="select" + isMultiSelect={true} + onInputChange={() => {}} + onEnumChange={regions => + props.onQDataChanged({ + 'general/regionsData/regions': regions + }) + } + multiSelectedEnum={props.dataMap['general/regionsData/regions']} + name="vsp-regions" + clearable={false} + values={ + props.genericFieldInfo['general/regionsData/regions'].enum + } + /> + </GridItem> + </GridSection> ); -const StorageDataReplicationSection = (props) => ( - <GridSection title={i18n('Storage Data Replication')}> - <GridItem> - <Input - data-test-id='vsp-storage-rep-size' - label={i18n('Storage Replication Size (GB)')} - type='number' - isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationSize'].isValid} - errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationSize'].errorText} - value={props.dataMap['general/storageDataReplication/storageReplicationSize']} - onChange={(sRep) => props.onQDataChanged({'general/storageDataReplication/storageReplicationSize' : sRep})} /> - </GridItem> - <GridItem> - <Input - data-test-id='vsp-storage-rep-source' - label={i18n('Storage Replication Source')} - type='text' - isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationSource'].isValid} - errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationSource'].errorText} - value={props.dataMap['general/storageDataReplication/storageReplicationSource']} - onChange={(sRepSource) => props.onQDataChanged({'general/storageDataReplication/storageReplicationSource' : sRepSource})} /> - </GridItem> - <GridItem> - <Input - data-test-id='vsp-storage-rep-freq' - label={i18n('Storage Replication Freq. (min)')} - type='number' - isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationFrequency'].isValid} - errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationFrequency'].errorText} - value={props.dataMap['general/storageDataReplication/storageReplicationFrequency']} - onChange={(sRepFreq) => props.onQDataChanged({'general/storageDataReplication/storageReplicationFrequency' : sRepFreq})} /> - </GridItem> - <GridItem> - <Input - data-test-id='vsp-storage-rep-dest' - label={i18n('Storage Replication Destination')} - type='text' - isValid={props.genericFieldInfo['general/storageDataReplication/storageReplicationDestination'].isValid} - errorText={props.genericFieldInfo['general/storageDataReplication/storageReplicationDestination'].errorText} - value={props.dataMap['general/storageDataReplication/storageReplicationDestination']} - onChange={(sRepDest) => props.onQDataChanged({'general/storageDataReplication/storageReplicationDestination' : sRepDest})} /> - </GridItem> - </GridSection> +const StorageDataReplicationSection = props => ( + <GridSection title={i18n('Storage Data Replication')}> + <GridItem> + <Input + data-test-id="vsp-storage-rep-size" + label={i18n('Storage Replication Size (GB)')} + type="number" + isValid={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationSize' + ].isValid + } + errorText={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationSize' + ].errorText + } + value={ + props.dataMap[ + 'general/storageDataReplication/storageReplicationSize' + ] + } + onChange={sRep => + props.onQDataChanged({ + 'general/storageDataReplication/storageReplicationSize': sRep + }) + } + /> + </GridItem> + <GridItem> + <Input + data-test-id="vsp-storage-rep-source" + label={i18n('Storage Replication Source')} + type="text" + isValid={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationSource' + ].isValid + } + errorText={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationSource' + ].errorText + } + value={ + props.dataMap[ + 'general/storageDataReplication/storageReplicationSource' + ] + } + onChange={sRepSource => + props.onQDataChanged({ + 'general/storageDataReplication/storageReplicationSource': sRepSource + }) + } + /> + </GridItem> + <GridItem> + <Input + data-test-id="vsp-storage-rep-freq" + label={i18n('Storage Replication Freq. (min)')} + type="number" + isValid={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationFrequency' + ].isValid + } + errorText={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationFrequency' + ].errorText + } + value={ + props.dataMap[ + 'general/storageDataReplication/storageReplicationFrequency' + ] + } + onChange={sRepFreq => + props.onQDataChanged({ + 'general/storageDataReplication/storageReplicationFrequency': sRepFreq + }) + } + /> + </GridItem> + <GridItem> + <Input + data-test-id="vsp-storage-rep-dest" + label={i18n('Storage Replication Destination')} + type="text" + isValid={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationDestination' + ].isValid + } + errorText={ + props.genericFieldInfo[ + 'general/storageDataReplication/storageReplicationDestination' + ].errorText + } + value={ + props.dataMap[ + 'general/storageDataReplication/storageReplicationDestination' + ] + } + onChange={sRepDest => + props.onQDataChanged({ + 'general/storageDataReplication/storageReplicationDestination': sRepDest + }) + } + /> + </GridItem> + </GridSection> ); class SoftwareProductDetails extends Component { + static propTypes = { + vendorName: PropTypes.string, + currentSoftwareProduct: PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + description: PropTypes.string, + category: PropTypes.string, + subCategory: PropTypes.string, + vendorId: PropTypes.string, + vendorName: PropTypes.string, + licensingVersion: PropTypes.string, + licensingData: PropTypes.shape({ + licenceAgreement: PropTypes.string, + featureGroups: PropTypes.array + }) + }), + softwareProductCategories: PropTypes.array, + finalizedLicenseModelList: PropTypes.array, + licenseAgreementList: PropTypes.array, + featureGroupsList: PropTypes.array, + onSubmit: PropTypes.func.isRequired, + onDataChanged: PropTypes.func.isRequired, + onValidityChanged: PropTypes.func.isRequired, + qdata: PropTypes.object.isRequired, + onQDataChanged: PropTypes.func.isRequired, + onVendorParamChanged: PropTypes.func.isRequired + }; - static propTypes = { - vendorName: PropTypes.string, - currentSoftwareProduct: PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string, - description: PropTypes.string, - category: PropTypes.string, - subCategory: PropTypes.string, - vendorId: PropTypes.string, - vendorName: PropTypes.string, - licensingVersion: PropTypes.string, - licensingData: PropTypes.shape({ - licenceAgreement: PropTypes.string, - featureGroups: PropTypes.array - }) - }), - softwareProductCategories: PropTypes.array, - finalizedLicenseModelList: PropTypes.array, - licenseAgreementList: PropTypes.array, - featureGroupsList: PropTypes.array, - onSubmit: PropTypes.func.isRequired, - onDataChanged: PropTypes.func.isRequired, - onValidityChanged: PropTypes.func.isRequired, - qdata: PropTypes.object.isRequired, - onQDataChanged: PropTypes.func.isRequired, - onVendorParamChanged: PropTypes.func.isRequired - }; - - prepareDataForGeneralSection(){ - let {softwareProductCategories, finalizedLicenseModelList, onDataChanged, currentSoftwareProduct, genericFieldInfo, isVendorArchived, onArchivedVendorRemove} = this.props; - let {name, description, vendorId, subCategory, vendorName} = currentSoftwareProduct; - return { - name, - description, - vendorId, - subCategory, - softwareProductCategories, - finalizedLicenseModelList, - onDataChanged, - onVendorParamChanged: args => this.onVendorParamChanged(args), - onSelectSubCategory: args => this.onSelectSubCategory(args), - genericFieldInfo, - vendorName, - isVendorArchived, - onArchivedVendorRemove - }; - - } + prepareDataForGeneralSection() { + let { + softwareProductCategories, + finalizedLicenseModelList, + onDataChanged, + currentSoftwareProduct, + genericFieldInfo, + isVendorArchived, + onArchivedVendorRemove + } = this.props; + let { + name, + description, + vendorId, + subCategory, + vendorName + } = currentSoftwareProduct; + return { + name, + description, + vendorId, + subCategory, + softwareProductCategories, + finalizedLicenseModelList, + onDataChanged, + onVendorParamChanged: args => this.onVendorParamChanged(args), + onSelectSubCategory: args => this.onSelectSubCategory(args), + genericFieldInfo, + vendorName, + isVendorArchived, + onArchivedVendorRemove + }; + } - prepareDataForLicensesSection(){ - let { featureGroupsList, licenseAgreementList, currentSoftwareProduct, isVendorArchived} = this.props; - let {vendorId, licensingVersion, licensingData = {}} = currentSoftwareProduct; - return { - onVendorParamChanged: args => this.onVendorParamChanged(args), - vendorId, - licensingVersion, - licensingVersionsList: this.buildLicensingVersionsListItems(), - licensingData, - onFeatureGroupsChanged: args => this.onFeatureGroupsChanged(args), - onLicensingDataChanged: args => this.onLicensingDataChanged(args), - featureGroupsList, - licenseAgreementList, - isVendorArchived - }; + prepareDataForLicensesSection() { + let { + featureGroupsList, + licenseAgreementList, + currentSoftwareProduct, + isVendorArchived + } = this.props; + let { + vendorId, + licensingVersion, + licensingData = {} + } = currentSoftwareProduct; + return { + onVendorParamChanged: args => this.onVendorParamChanged(args), + vendorId, + licensingVersion, + licensingVersionsList: this.buildLicensingVersionsListItems(), + licensingData, + onFeatureGroupsChanged: args => this.onFeatureGroupsChanged(args), + onLicensingDataChanged: args => this.onLicensingDataChanged(args), + featureGroupsList, + licenseAgreementList, + isVendorArchived + }; + } - } + render() { + let { currentSoftwareProduct } = this.props; + let { qdata, onQDataChanged, dataMap, qGenericFieldInfo } = this.props; + let { isReadOnlyMode } = this.props; - render() { - let {currentSoftwareProduct} = this.props; - let {qdata, onQDataChanged, dataMap, qGenericFieldInfo} = this.props; - let {isReadOnlyMode} = this.props; + return ( + <div className="vsp-details-page"> + <Form + ref={validationForm => + (this.validationForm = validationForm) + } + className="vsp-general-tab" + hasButtons={false} + formReady={null} + isValid={this.props.isFormValid} + onSubmit={() => + this.props.onSubmit(currentSoftwareProduct, qdata) + } + onValidityChanged={isValidityData => + this.props.onValidityChanged(isValidityData) + } + isReadOnlyMode={isReadOnlyMode}> + <GeneralSection {...this.prepareDataForGeneralSection()} /> + <LicensesSection + {...this.prepareDataForLicensesSection()} + /> + <AvailabilitySection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + /> + <RegionsSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + genericFieldInfo={qGenericFieldInfo} + /> + <StorageDataReplicationSection + onQDataChanged={onQDataChanged} + dataMap={dataMap} + genericFieldInfo={qGenericFieldInfo} + /> + </Form> + </div> + ); + } - return ( - <div className='vsp-details-page'> - <Form - ref={(validationForm) => this.validationForm = validationForm} - className='vsp-general-tab' - hasButtons={false} - formReady={null} - isValid={this.props.isFormValid} - onSubmit={() => this.props.onSubmit(currentSoftwareProduct, qdata)} - onValidityChanged={(isValidityData) => this.props.onValidityChanged(isValidityData)} - isReadOnlyMode={isReadOnlyMode}> - <GeneralSection {...this.prepareDataForGeneralSection()}/> - <LicensesSection {...this.prepareDataForLicensesSection()}/> - <AvailabilitySection onQDataChanged={onQDataChanged} dataMap={dataMap} /> - <RegionsSection onQDataChanged={onQDataChanged} dataMap={dataMap} genericFieldInfo={qGenericFieldInfo} /> - <StorageDataReplicationSection onQDataChanged={onQDataChanged} dataMap={dataMap} genericFieldInfo={qGenericFieldInfo} /> - </Form> - </div> - ); - } + onVendorParamChanged({ vendorId, licensingVersion }) { + let { finalizedLicenseModelList, onVendorParamChanged } = this.props; + if (!licensingVersion) { + const licensingVersionsList = this.buildLicensingVersionsListItems(); + licensingVersion = licensingVersionsList[0].enum; + } - onVendorParamChanged({vendorId, licensingVersion}) { - - let {finalizedLicenseModelList, onVendorParamChanged} = this.props; - if(!licensingVersion) { - const licensingVersionsList = this.buildLicensingVersionsListItems(); - licensingVersion = licensingVersionsList[0].enum; - } - - if (!vendorId) { - vendorId = finalizedLicenseModelList[0].id; - } - - let vendorName = finalizedLicenseModelList.find(licenseModelItem => licenseModelItem.id === vendorId).name || ''; - let deltaData = { - vendorId, - vendorName, - licensingVersion, - licensingData: {} - }; + if (!vendorId) { + vendorId = finalizedLicenseModelList[0].id; + } - onVendorParamChanged(deltaData, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS); + let vendorName = + finalizedLicenseModelList.find( + licenseModelItem => licenseModelItem.id === vendorId + ).name || ''; + let deltaData = { + vendorId, + vendorName, + licensingVersion, + licensingData: {} + }; - } + onVendorParamChanged(deltaData, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS); + } - buildLicensingVersionsListItems() { - let {licensingVersionsList} = this.props; + buildLicensingVersionsListItems() { + let { licensingVersionsList } = this.props; - let licensingVersionsListItems = [{ - enum: '', - title: i18n('Select...') - }]; + let licensingVersionsListItems = [ + { + enum: '', + title: i18n('Select...') + } + ]; - return licensingVersionsListItems.concat(licensingVersionsList.map(version => ({enum: version.id, title: version.name}))); - } + return licensingVersionsListItems.concat( + licensingVersionsList.map(version => ({ + enum: version.id, + title: version.name + })) + ); + } - onFeatureGroupsChanged({featureGroups}) { - this.onLicensingDataChanged({featureGroups}); - } + onFeatureGroupsChanged({ featureGroups }) { + this.onLicensingDataChanged({ featureGroups }); + } - onLicensingDataChanged(deltaData) { - this.props.onDataChanged({ - licensingData: { - ...this.props.currentSoftwareProduct.licensingData, - ...deltaData - } - }, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS); - } + onLicensingDataChanged(deltaData) { + this.props.onDataChanged( + { + licensingData: { + ...this.props.currentSoftwareProduct.licensingData, + ...deltaData + } + }, + forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + ); + } - onSelectSubCategory(subCategory) { - let {softwareProductCategories, onDataChanged} = this.props; - let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(subCategory, softwareProductCategories); - onDataChanged({category, subCategory}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS); - } + onSelectSubCategory(subCategory) { + let { softwareProductCategories, onDataChanged } = this.props; + let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory( + subCategory, + softwareProductCategories + ); + onDataChanged( + { category, subCategory }, + forms.VENDOR_SOFTWARE_PRODUCT_DETAILS + ); + } - save(){ - return this.validationForm.handleFormSubmit(new Event('dummy')); - } + save() { + return this.validationForm.handleFormSubmit(new Event('dummy')); + } } export default SoftwareProductDetails; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js index 64e0d562ce..34bfceec24 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js @@ -13,106 +13,134 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js'; import LandingPageView from './SoftwareProductLandingPageView.jsx'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; -import {onboardingMethod} from '../SoftwareProductConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; +import { onboardingMethod } from '../SoftwareProductConstants.js'; import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js'; -import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js'; - +import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js'; export const mapStateToProps = ({ - softwareProduct, - licenseModel: {licenseAgreement}, + softwareProduct, + licenseModel: { licenseAgreement } }) => { - let {softwareProductEditor: {data:currentSoftwareProduct = {}}, softwareProductComponents, softwareProductCategories = [], } = softwareProduct; - let {licensingData = {}} = currentSoftwareProduct; - let {licenseAgreementList} = licenseAgreement; - let {componentsList} = softwareProductComponents; - let licenseAgreementName = licenseAgreementList.find(la => la.id === licensingData.licenseAgreement); - if (licenseAgreementName) { - licenseAgreementName = licenseAgreementName.name; - } else if (licenseAgreementList.length === 0) { // otherwise the state of traingle svgicon will be updated post unmounting - licenseAgreementName = null; - } - - let categoryName = '', subCategoryName = '', fullCategoryDisplayName = ''; - const category = softwareProductCategories.find(ca => ca.uniqueId === currentSoftwareProduct.category); - if (category) { - categoryName = category.name; - const subcategories = category.subcategories || []; - const subcat = subcategories.find(sc => sc.uniqueId === currentSoftwareProduct.subCategory); - subCategoryName = subcat && subcat.name ? subcat.name : ''; - } - fullCategoryDisplayName = `${subCategoryName} (${categoryName})`; + let { + softwareProductEditor: { data: currentSoftwareProduct = {} }, + softwareProductComponents, + softwareProductCategories = [] + } = softwareProduct; + let { licensingData = {} } = currentSoftwareProduct; + let { licenseAgreementList } = licenseAgreement; + let { componentsList } = softwareProductComponents; + let licenseAgreementName = licenseAgreementList.find( + la => la.id === licensingData.licenseAgreement + ); + if (licenseAgreementName) { + licenseAgreementName = licenseAgreementName.name; + } else if (licenseAgreementList.length === 0) { + // otherwise the state of traingle svgicon will be updated post unmounting + licenseAgreementName = null; + } + let categoryName = '', + subCategoryName = '', + fullCategoryDisplayName = ''; + const category = softwareProductCategories.find( + ca => ca.uniqueId === currentSoftwareProduct.category + ); + if (category) { + categoryName = category.name; + const subcategories = category.subcategories || []; + const subcat = subcategories.find( + sc => sc.uniqueId === currentSoftwareProduct.subCategory + ); + subCategoryName = subcat && subcat.name ? subcat.name : ''; + } + fullCategoryDisplayName = `${subCategoryName} (${categoryName})`; - return { - currentSoftwareProduct: { - ...currentSoftwareProduct, - licenseAgreementName, - fullCategoryDisplayName - }, - componentsList, - isManual: currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL - }; + return { + currentSoftwareProduct: { + ...currentSoftwareProduct, + licenseAgreementName, + fullCategoryDisplayName + }, + componentsList, + isManual: + currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL + }; }; -const mapActionsToProps = (dispatch, {version}) => { - return { - onDetailsSelect: ({id: softwareProductId}) => - ScreensHelper.loadScreen(dispatch, { - screen: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version} - }), - onCandidateInProcess: (softwareProductId) => ScreensHelper.loadScreen(dispatch, { - screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version} - }), - onUpload: (softwareProductId, formData) => - SoftwareProductActionHelper.uploadFile(dispatch, { - softwareProductId, - formData, - failedNotificationTitle: i18n('Upload validation failed'), - version - }), +const mapActionsToProps = (dispatch, { version }) => { + return { + onDetailsSelect: ({ id: softwareProductId }) => + ScreensHelper.loadScreen(dispatch, { + screen: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version } + }), + onCandidateInProcess: softwareProductId => + ScreensHelper.loadScreen(dispatch, { + screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version } + }), + onUpload: (softwareProductId, formData) => + SoftwareProductActionHelper.uploadFile(dispatch, { + softwareProductId, + formData, + failedNotificationTitle: i18n('Upload validation failed'), + version + }), - onUploadConfirmation: (softwareProductId, formData) => - dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data:{ - msg: i18n('Upload will erase existing data. Do you want to continue?'), - confirmationButtonText: i18n('Continue'), - title: i18n('Warning'), - onConfirmed: ()=>SoftwareProductActionHelper.uploadFile(dispatch, { - softwareProductId, - formData, - failedNotificationTitle: i18n('Upload validation failed'), - version - }), - onDeclined: () => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_CLOSE - }) - } - }), + onUploadConfirmation: (softwareProductId, formData) => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + msg: i18n( + 'Upload will erase existing data. Do you want to continue?' + ), + confirmationButtonText: i18n('Continue'), + title: i18n('Warning'), + onConfirmed: () => + SoftwareProductActionHelper.uploadFile(dispatch, { + softwareProductId, + formData, + failedNotificationTitle: i18n( + 'Upload validation failed' + ), + version + }), + onDeclined: () => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_CLOSE + }) + } + }), - onInvalidFileSizeUpload: () => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_ERROR, - data: { - title: i18n('Upload Failed'), - confirmationButtonText: i18n('Continue'), - msg: i18n('no zip or csar file was uploaded or expected file doesn\'t exist') - } - }), - onComponentSelect: ({id: softwareProductId, componentId}) => ScreensHelper.loadScreen(dispatch, { - screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL, screenType: screenTypes.SOFTWARE_PRODUCT, - props: {softwareProductId, version, componentId} - }), - /** for the next version */ - onAddComponent: () => SoftwareProductActionHelper.addComponent(dispatch) - }; + onInvalidFileSizeUpload: () => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_ERROR, + data: { + title: i18n('Upload Failed'), + confirmationButtonText: i18n('Continue'), + msg: i18n( + "no zip or csar file was uploaded or expected file doesn't exist" + ) + } + }), + onComponentSelect: ({ id: softwareProductId, componentId }) => + ScreensHelper.loadScreen(dispatch, { + screen: screenTypes.SOFTWARE_PRODUCT_COMPONENT_DEFAULT_GENERAL, + screenType: screenTypes.SOFTWARE_PRODUCT, + props: { softwareProductId, version, componentId } + }), + /** for the next version */ + onAddComponent: () => SoftwareProductActionHelper.addComponent(dispatch) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(LandingPageView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(LandingPageView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx index a73a849a08..bc8a2be646 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx @@ -18,7 +18,6 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import Dropzone from 'react-dropzone'; - import i18n from 'nfvo-utils/i18n/i18n.js'; import DraggableUploadFileBox from 'nfvo-components/fileupload/DraggableUploadFileBox.jsx'; @@ -26,192 +25,237 @@ import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js'; import SoftwareProductComponentsList from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js'; const SoftwareProductPropType = PropTypes.shape({ - name: PropTypes.string, - description: PropTypes.string, - version: PropTypes.string, - id: PropTypes.string, - categoryId: PropTypes.string, - vendorId: PropTypes.string, - status: PropTypes.string, - licensingData: PropTypes.object, - validationData: PropTypes.object + name: PropTypes.string, + description: PropTypes.string, + version: PropTypes.string, + id: PropTypes.string, + categoryId: PropTypes.string, + vendorId: PropTypes.string, + status: PropTypes.string, + licensingData: PropTypes.object, + validationData: PropTypes.object }); const ComponentPropType = PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string, - displayName: PropTypes.string, - description: PropTypes.string + id: PropTypes.string, + name: PropTypes.string, + displayName: PropTypes.string, + description: PropTypes.string }); class SoftwareProductLandingPageView extends React.Component { + state = { + fileName: '', + dragging: false, + files: [] + }; + + static propTypes = { + currentSoftwareProduct: SoftwareProductPropType, + isReadOnlyMode: PropTypes.bool, + componentsList: PropTypes.arrayOf(ComponentPropType), + version: PropTypes.object, + onDetailsSelect: PropTypes.func, + onUpload: PropTypes.func, + onUploadConfirmation: PropTypes.func, + onInvalidFileSizeUpload: PropTypes.func, + onComponentSelect: PropTypes.func, + onAddComponent: PropTypes.func + }; + componentDidMount() { + const { onCandidateInProcess, currentSoftwareProduct } = this.props; + if (currentSoftwareProduct.candidateOnboardingOrigin) { + onCandidateInProcess(currentSoftwareProduct.id); + } + } + render() { + let { + currentSoftwareProduct, + isReadOnlyMode, + isManual, + onDetailsSelect + } = this.props; + return ( + <div className="software-product-landing-wrapper"> + <Dropzone + className={classnames('software-product-landing-view', { + 'active-dragging': this.state.dragging + })} + onDrop={files => + this.handleImportSubmit(files, isReadOnlyMode, isManual) + } + onDragEnter={() => + this.handleOnDragEnter(isReadOnlyMode, isManual) + } + onDragLeave={() => this.setState({ dragging: false })} + multiple={false} + disableClick={true} + ref="fileInput" + name="fileInput" + accept=".zip, .csar"> + <div className="draggable-wrapper"> + <div className="software-product-landing-view-top"> + <div className="row"> + <ProductSummary + currentSoftwareProduct={ + currentSoftwareProduct + } + onDetailsSelect={onDetailsSelect} + /> + {this.renderProductDetails( + isManual, + isReadOnlyMode + )} + </div> + </div> + </div> + </Dropzone> + <SoftwareProductComponentsList /> + </div> + ); + } + + handleOnDragEnter(isReadOnlyMode, isManual) { + if (!isReadOnlyMode && !isManual) { + this.setState({ dragging: true }); + } + } + + renderProductDetails(isManual, isReadOnlyMode) { + return ( + <div className="details-panel"> + {!isManual && ( + <div> + <div className="software-product-landing-view-heading-title"> + {i18n('Software Product Attachments')} + </div> + <DraggableUploadFileBox + dataTestId="upload-btn" + isReadOnlyMode={isReadOnlyMode} + className={classnames( + 'software-product-landing-view-top-block-col-upl', + { disabled: isReadOnlyMode } + )} + onClick={() => this.refs.fileInput.open()} + /> + </div> + )} + </div> + ); + } + + handleImportSubmit(files, isReadOnlyMode, isManual) { + if (isReadOnlyMode || isManual) { + return; + } + if (files[0] && files[0].size) { + this.setState({ + fileName: files[0].name, + dragging: false, + complete: '0' + }); + this.startUploading(files); + } else { + this.setState({ + dragging: false + }); + this.props.onInvalidFileSizeUpload(); + } + } - state = { - - fileName: '', - dragging: false, - files: [] - }; - - static propTypes = { - currentSoftwareProduct: SoftwareProductPropType, - isReadOnlyMode: PropTypes.bool, - componentsList: PropTypes.arrayOf(ComponentPropType), - version: PropTypes.object, - onDetailsSelect: PropTypes.func, - onUpload: PropTypes.func, - onUploadConfirmation: PropTypes.func, - onInvalidFileSizeUpload: PropTypes.func, - onComponentSelect: PropTypes.func, - onAddComponent: PropTypes.func - }; - componentDidMount() { - const {onCandidateInProcess, currentSoftwareProduct} = this.props; - if (currentSoftwareProduct.candidateOnboardingOrigin) { - onCandidateInProcess(currentSoftwareProduct.id); - } - } - render() { - let {currentSoftwareProduct, isReadOnlyMode, isManual, onDetailsSelect} = this.props; - return ( - <div className='software-product-landing-wrapper'> - <Dropzone - className={classnames('software-product-landing-view', {'active-dragging': this.state.dragging})} - onDrop={files => this.handleImportSubmit(files, isReadOnlyMode, isManual)} - onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode, isManual)} - onDragLeave={() => this.setState({dragging:false})} - multiple={false} - disableClick={true} - ref='fileInput' - name='fileInput' - accept='.zip, .csar'> - <div className='draggable-wrapper'> - <div className='software-product-landing-view-top'> - <div className='row'> - <ProductSummary currentSoftwareProduct={currentSoftwareProduct} onDetailsSelect={onDetailsSelect} /> - {this.renderProductDetails(isManual, isReadOnlyMode)} - </div> - </div> - </div> - </Dropzone> - <SoftwareProductComponentsList/> - </div> - ); - } - - handleOnDragEnter(isReadOnlyMode, isManual) { - if (!isReadOnlyMode && !isManual) { - this.setState({dragging: true}); - } - } - - renderProductDetails(isManual, isReadOnlyMode) { - return ( - <div className='details-panel'> - { !isManual && <div> - <div className='software-product-landing-view-heading-title'>{i18n('Software Product Attachments')}</div> - <DraggableUploadFileBox - dataTestId='upload-btn' - isReadOnlyMode={isReadOnlyMode} - className={classnames('software-product-landing-view-top-block-col-upl', {'disabled': isReadOnlyMode})} - onClick={() => this.refs.fileInput.open()}/> - </div> - } - </div> - ); - } - - handleImportSubmit(files, isReadOnlyMode, isManual) { - if (isReadOnlyMode || isManual) { - return; - } - if (files[0] && files[0].size) { - this.setState({ - fileName: files[0].name, - dragging: false, - complete: '0', - }); - this.startUploading(files); - } - else { - this.setState({ - dragging: false - }); - this.props.onInvalidFileSizeUpload(); - } - - } - - startUploading(files) { - let {onUpload, currentSoftwareProduct, onUploadConfirmation} = this.props; - - let {validationData} = currentSoftwareProduct; - - if (!(files && files.length)) { - return; - } - let file = files[0]; - let formData = new FormData(); - formData.append('upload', file); - this.refs.fileInput.value = ''; - - if (validationData) { - onUploadConfirmation(currentSoftwareProduct.id, formData); - }else { - onUpload(currentSoftwareProduct.id, formData); - } - - } + startUploading(files) { + let { + onUpload, + currentSoftwareProduct, + onUploadConfirmation + } = this.props; + + let { validationData } = currentSoftwareProduct; + + if (!(files && files.length)) { + return; + } + let file = files[0]; + let formData = new FormData(); + formData.append('upload', file); + this.refs.fileInput.value = ''; + + if (validationData) { + onUploadConfirmation(currentSoftwareProduct.id, formData); + } else { + onUpload(currentSoftwareProduct.id, formData); + } + } } -const ProductSummary = ({currentSoftwareProduct, onDetailsSelect}) => { - let {name = '', description = '', vendorName = '', fullCategoryDisplayName = '', licenseAgreementName = ''} = currentSoftwareProduct; - return ( - <div className='details-panel'> - <div className='software-product-landing-view-heading-title'>{i18n('Software Product Details')}</div> - <div - className='software-product-landing-view-top-block clickable' - onClick={() => onDetailsSelect(currentSoftwareProduct)}> - <div className='details-container'> - <div className='single-detail-section title-section'> - <div className='single-detail-section title-text'> - {name} - </div> - </div> - <div className='details-section'> - <div className='multiple-details-section'> - <div className='detail-col' > - <div className='title'>{i18n('Vendor')}</div> - <div className='description'>{vendorName}</div> - </div> - <div className='detail-col'> - <div className='title'>{i18n('Category')}</div> - <div className='description'>{fullCategoryDisplayName}</div> - </div> - <div className='detail-col'> - <div className='title extra-large'>{i18n('License Agreement')}</div> - <div className='description'> - <LicenseAgreement licenseAgreementName={licenseAgreementName}/> - </div> - </div> - </div> - <div className='single-detail-section'> - <div className='title'>{i18n('Description')}</div> - <div className='description'>{description}</div> - </div> - </div> - </div> - </div> - </div> - ); +const ProductSummary = ({ currentSoftwareProduct, onDetailsSelect }) => { + let { + name = '', + description = '', + vendorName = '', + fullCategoryDisplayName = '', + licenseAgreementName = '' + } = currentSoftwareProduct; + return ( + <div className="details-panel"> + <div className="software-product-landing-view-heading-title"> + {i18n('Software Product Details')} + </div> + <div + className="software-product-landing-view-top-block clickable" + onClick={() => onDetailsSelect(currentSoftwareProduct)}> + <div className="details-container"> + <div className="single-detail-section title-section"> + <div className="single-detail-section title-text"> + {name} + </div> + </div> + <div className="details-section"> + <div className="multiple-details-section"> + <div className="detail-col"> + <div className="title">{i18n('Vendor')}</div> + <div className="description">{vendorName}</div> + </div> + <div className="detail-col"> + <div className="title">{i18n('Category')}</div> + <div className="description"> + {fullCategoryDisplayName} + </div> + </div> + <div className="detail-col"> + <div className="title extra-large"> + {i18n('License Agreement')} + </div> + <div className="description"> + <LicenseAgreement + licenseAgreementName={ + licenseAgreementName + } + /> + </div> + </div> + </div> + <div className="single-detail-section"> + <div className="title">{i18n('Description')}</div> + <div className="description">{description}</div> + </div> + </div> + </div> + </div> + </div> + ); }; - -const LicenseAgreement = ({licenseAgreementName}) => { - if (!licenseAgreementName) { - return (<div className='missing-license'><SVGIcon color='warning' name='exclamationTriangleFull'/><div className='warning-text'>{i18n('Missing')}</div></div>); - } - return <div>{licenseAgreementName}</div>; +const LicenseAgreement = ({ licenseAgreementName }) => { + if (!licenseAgreementName) { + return ( + <div className="missing-license"> + <SVGIcon color="warning" name="exclamationTriangleFull" /> + <div className="warning-text">{i18n('Missing')}</div> + </div> + ); + } + return <div>{licenseAgreementName}</div>; }; export default SoftwareProductLandingPageView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js index 6161eadba9..27dd471a00 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js @@ -13,13 +13,14 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import SoftwareProductNetworksView from './SoftwareProductNetworksView.jsx'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductNetworks: {networksList = []}} = softwareProduct; - return {networksList}; +export const mapStateToProps = ({ softwareProduct }) => { + let { softwareProductNetworks: { networksList = [] } } = softwareProduct; + return { networksList }; }; -export default connect(mapStateToProps, null, null, {withRef: true})(SoftwareProductNetworksView); - +export default connect(mapStateToProps, null, null, { withRef: true })( + SoftwareProductNetworksView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js index 4cb460ecc6..388c641b46 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js @@ -13,30 +13,29 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductNetworksConstants.js'; +import { actionTypes } from './SoftwareProductNetworksConstants.js'; import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; function baseUrl(vspId, version) { - let {id: versionId} = version; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/networks`; + let { id: versionId } = version; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/networks`; } - function fetchNetworksList(softwareProductId, version) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); + return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); } const SoftwareProductNetworksActionHelper = { - fetchNetworksList(dispatch, {softwareProductId, version}) { - return fetchNetworksList(softwareProductId, version).then(response => { - dispatch({ - type: actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS, - networksList: response.results - }); - }); - } + fetchNetworksList(dispatch, { softwareProductId, version }) { + return fetchNetworksList(softwareProductId, version).then(response => { + dispatch({ + type: actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS, + networksList: response.results + }); + }); + } }; -export default SoftwareProductNetworksActionHelper; +export default SoftwareProductNetworksActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js index a3d5578dc4..17e4bdfe8d 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js @@ -16,5 +16,5 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - FETCH_SOFTWARE_PRODUCT_NETWORKS: null, + FETCH_SOFTWARE_PRODUCT_NETWORKS: null }); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js index e7c2fcb045..796de822df 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js @@ -13,13 +13,13 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductNetworksConstants.js'; +import { actionTypes } from './SoftwareProductNetworksConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS: - return [...action.networksList]; - default: - return state; - } + switch (action.type) { + case actionTypes.FETCH_SOFTWARE_PRODUCT_NETWORKS: + return [...action.networksList]; + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx index e8c365f124..458f3192f4 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx @@ -22,73 +22,76 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx'; class SoftwareProductNetworksView extends React.Component { + static propTypes = { + networksList: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + dhcp: PropTypes.bool.isRequired + }) + ).isRequired, + isReadOnlyMode: PropTypes.bool.isRequired + }; - static propTypes = { - networksList: PropTypes.arrayOf(PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - dhcp: PropTypes.bool.isRequired - })).isRequired, - isReadOnlyMode: PropTypes.bool.isRequired - }; + state = { + localFilter: '' + }; - state = { - localFilter: '' - }; + render() { + const { localFilter } = this.state; + const { isReadOnlyMode } = this.props; - render() { - const {localFilter} = this.state; - const {isReadOnlyMode} = this.props; + return ( + <div className="vsp-networks-page"> + <ListEditorView + title={i18n('Networks')} + filterValue={localFilter} + placeholder={i18n('Filter Networks')} + onFilter={value => this.setState({ localFilter: value })} + twoColumns> + {this.filterList().map(network => + this.renderNetworksListItem({ network, isReadOnlyMode }) + )} + </ListEditorView> + </div> + ); + } - return ( - <div className='vsp-networks-page'> - <ListEditorView - title={i18n('Networks')} - filterValue={localFilter} - placeholder={i18n('Filter Networks')} - onFilter={value => this.setState({localFilter: value})} - twoColumns> - {this.filterList().map(network => this.renderNetworksListItem({network, isReadOnlyMode}))} - </ListEditorView> - </div> - ); - } + renderNetworksListItem({ network, isReadOnlyMode }) { + let { id, name, dhcp } = network; + return ( + <ListEditorItemView + key={id} + className="list-editor-item-view" + isReadOnlyMode={isReadOnlyMode}> + <ListEditorItemViewField> + <div className="name">{name}</div> + </ListEditorItemViewField> + <ListEditorItemViewField> + <div className="details"> + <div className="title">{i18n('DHCP')}</div> + <div className="artifact-name"> + {dhcp ? i18n('YES') : i18n('NO')} + </div> + </div> + </ListEditorItemViewField> + </ListEditorItemView> + ); + } - renderNetworksListItem({network, isReadOnlyMode}) { - let {id, name, dhcp} = network; - return ( - <ListEditorItemView - key={id} - className='list-editor-item-view' - isReadOnlyMode={isReadOnlyMode}> + filterList() { + let { networksList } = this.props; - <ListEditorItemViewField> - <div className='name'>{name}</div> - </ListEditorItemViewField> - <ListEditorItemViewField> - <div className='details'> - <div className='title'>{i18n('DHCP')}</div> - <div className='artifact-name'>{dhcp ? i18n('YES') : i18n('NO')}</div> - </div> - </ListEditorItemViewField> - </ListEditorItemView> - ); - } - - filterList() { - let {networksList} = this.props; - - let {localFilter} = this.state; - if (localFilter.trim()) { - const filter = new RegExp(escape(localFilter), 'i'); - return networksList.filter(({name = ''}) => { - return escape(name).match(filter); - }); - } - else { - return networksList; - } - } + let { localFilter } = this.state; + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return networksList.filter(({ name = '' }) => { + return escape(name).match(filter); + }); + } else { + return networksList; + } + } } export default SoftwareProductNetworksView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessListView.jsx index aa39c87dd0..cee46abc69 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessListView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessListView.jsx @@ -20,80 +20,86 @@ import i18n from 'nfvo-utils/i18n/i18n.js'; import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx'; - class SoftwareProductProcessesListView extends React.Component { + state = { + localFilter: '' + }; - state = { - localFilter: '' - }; - - static propTypes = { - onAddProcess: PropTypes.func.isRequired, - onEditProcess: PropTypes.func.isRequired, - onDeleteProcess: PropTypes.func.isRequired, - isReadOnlyMode: PropTypes.bool.isRequired, - currentSoftwareProduct:PropTypes.object, - addButtonTitle: PropTypes.string - }; - - render() { - const {localFilter} = this.state; - let {onAddProcess, isReadOnlyMode, addButtonTitle} = this.props; + static propTypes = { + onAddProcess: PropTypes.func.isRequired, + onEditProcess: PropTypes.func.isRequired, + onDeleteProcess: PropTypes.func.isRequired, + isReadOnlyMode: PropTypes.bool.isRequired, + currentSoftwareProduct: PropTypes.object, + addButtonTitle: PropTypes.string + }; - return ( - <ListEditorView - plusButtonTitle={addButtonTitle} - filterValue={localFilter} - placeholder={i18n('Filter Process')} - onAdd={onAddProcess} - isReadOnlyMode={isReadOnlyMode} - title={i18n('Process Details')} - onFilter={value => this.setState({localFilter: value})}> - {this.filterList().map(processes => this.renderProcessListItem(processes, isReadOnlyMode))} - </ListEditorView>); - } + render() { + const { localFilter } = this.state; + let { onAddProcess, isReadOnlyMode, addButtonTitle } = this.props; - renderProcessListItem(process, isReadOnlyMode) { - let {id, name, description, artifactName = ''} = process; - let {currentSoftwareProduct: {version}, onEditProcess, onDeleteProcess} = this.props; - return ( - <ListEditorItemView - key={id} - className='list-editor-item-view' - isReadOnlyMode={isReadOnlyMode} - onSelect={() => onEditProcess(process)} - onDelete={() => onDeleteProcess(process, version)}> + return ( + <ListEditorView + plusButtonTitle={addButtonTitle} + filterValue={localFilter} + placeholder={i18n('Filter Process')} + onAdd={onAddProcess} + isReadOnlyMode={isReadOnlyMode} + title={i18n('Process Details')} + onFilter={value => this.setState({ localFilter: value })}> + {this.filterList().map(processes => + this.renderProcessListItem(processes, isReadOnlyMode) + )} + </ListEditorView> + ); + } - <div className='list-editor-item-view-field'> - <div className='title'>{i18n('Name')}</div> - <div className='name'>{name}</div> - </div> - <div className='list-editor-item-view-field'> - <div className='title'>{i18n('Artifact name')}</div> - <div className='artifact-name'>{artifactName}</div> - </div> - <div className='list-editor-item-view-field'> - <div className='title'>{i18n('Notes')}</div> - <div className='description'>{description}</div> - </div> - </ListEditorItemView> - ); - } + renderProcessListItem(process, isReadOnlyMode) { + let { id, name, description, artifactName = '' } = process; + let { + currentSoftwareProduct: { version }, + onEditProcess, + onDeleteProcess + } = this.props; + return ( + <ListEditorItemView + key={id} + className="list-editor-item-view" + isReadOnlyMode={isReadOnlyMode} + onSelect={() => onEditProcess(process)} + onDelete={() => onDeleteProcess(process, version)}> + <div className="list-editor-item-view-field"> + <div className="title">{i18n('Name')}</div> + <div className="name">{name}</div> + </div> + <div className="list-editor-item-view-field"> + <div className="title">{i18n('Artifact name')}</div> + <div className="artifact-name">{artifactName}</div> + </div> + <div className="list-editor-item-view-field"> + <div className="title">{i18n('Notes')}</div> + <div className="description">{description}</div> + </div> + </ListEditorItemView> + ); + } - filterList() { - let {processesList} = this.props; - let {localFilter} = this.state; + filterList() { + let { processesList } = this.props; + let { localFilter } = this.state; - if (localFilter.trim()) { - const filter = new RegExp(escape(localFilter), 'i'); - return processesList.filter(({name = '', description = ''}) => { - return escape(name).match(filter) || escape(description).match(filter); - }); - } - else { - return processesList; - } - } + if (localFilter.trim()) { + const filter = new RegExp(escape(localFilter), 'i'); + return processesList.filter(({ name = '', description = '' }) => { + return ( + escape(name).match(filter) || + escape(description).match(filter) + ); + }); + } else { + return processesList; + } + } } export default SoftwareProductProcessesListView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js index b0403abde5..fb44530dae 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js @@ -13,40 +13,57 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js'; import SoftwareProductProcessesActionHelper from './SoftwareProductProcessesActionHelper.js'; import SoftwareProductProcessesView from './SoftwareProductProcessesView.jsx'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductEditor: {data: currentSoftwareProduct = {}}, softwareProductProcesses: {processesList, processesEditor}} = softwareProduct; - let {data} = processesEditor; +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductEditor: { data: currentSoftwareProduct = {} }, + softwareProductProcesses: { processesList, processesEditor } + } = softwareProduct; + let { data } = processesEditor; - return { - currentSoftwareProduct, - processesList, - isDisplayEditor: Boolean(data), - isModalInEditMode: Boolean(data && data.id) - }; + return { + currentSoftwareProduct, + processesList, + isDisplayEditor: Boolean(data), + isModalInEditMode: Boolean(data && data.id) + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version}) => { - return { - onAddProcess: () => SoftwareProductProcessesActionHelper.openEditor(dispatch), - onEditProcess: (process) => SoftwareProductProcessesActionHelper.openEditor(dispatch, process), - onDeleteProcess: (process) => dispatch({ - type: modalActionTypes.GLOBAL_MODAL_WARNING, - data:{ - msg: i18n('Are you sure you want to delete "{name}"?', {name: process.name}), - confirmationButtonText: i18n('Delete'), - title: i18n('Delete'), - onConfirmed: ()=> SoftwareProductProcessesActionHelper.deleteProcess(dispatch, - {process, softwareProductId, version}) - } - }) - }; +const mapActionsToProps = (dispatch, { softwareProductId, version }) => { + return { + onAddProcess: () => + SoftwareProductProcessesActionHelper.openEditor(dispatch), + onEditProcess: process => + SoftwareProductProcessesActionHelper.openEditor(dispatch, process), + onDeleteProcess: process => + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_WARNING, + data: { + msg: i18n('Are you sure you want to delete "{name}"?', { + name: process.name + }), + confirmationButtonText: i18n('Delete'), + title: i18n('Delete'), + onConfirmed: () => + SoftwareProductProcessesActionHelper.deleteProcess( + dispatch, + { + process, + softwareProductId, + version + } + ) + } + }) + }; }; -export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductProcessesView); +export default connect(mapStateToProps, mapActionsToProps, null, { + withRef: true +})(SoftwareProductProcessesView); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js index 8fd370b6cc..7c72c5b892 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js @@ -13,127 +13,145 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductProcessesConstants.js'; +import { actionTypes } from './SoftwareProductProcessesConstants.js'; import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; function baseUrl(vspId, version) { - let {id: versionId} = version; - const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/processes`; + let { id: versionId } = version; + const restPrefix = Configuration.get('restPrefix'); + return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/processes`; } function putProcess(softwareProductId, version, process) { - return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${process.id}`, { - name: process.name, - description: process.description, - type: process.type === '' ? null : process.type - }); + return RestAPIUtil.put( + `${baseUrl(softwareProductId, version)}/${process.id}`, + { + name: process.name, + description: process.description, + type: process.type === '' ? null : process.type + } + ); } function postProcess(softwareProductId, version, process) { - return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { - name: process.name, - description: process.description, - type: process.type === '' ? null : process.type - }); + return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, { + name: process.name, + description: process.description, + type: process.type === '' ? null : process.type + }); } function deleteProcess(softwareProductId, version, processId) { - return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${processId}`); + return RestAPIUtil.destroy( + `${baseUrl(softwareProductId, version)}/${processId}` + ); } -function uploadFileToProcess(softwareProductId, version, processId, formData) -{ - return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}/${processId}/upload`, formData); +function uploadFileToProcess(softwareProductId, version, processId, formData) { + return RestAPIUtil.post( + `${baseUrl(softwareProductId, version)}/${processId}/upload`, + formData + ); } function fetchProcesses(softwareProductId, version) { - return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); + return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`); } const SoftwareProductActionHelper = { - - fetchProcessesList(dispatch, {softwareProductId, version}) { - - dispatch({ - type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES, - processesList: [] - }); - - return fetchProcesses(softwareProductId, version).then(response => { - dispatch({ - type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES, - processesList: response.results - }); - }); - }, - openEditor(dispatch, process = {}) { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN, - process - }); - }, - - deleteProcess(dispatch, {process, softwareProductId, version}) { - return deleteProcess(softwareProductId, version, process.id).then(() => { - dispatch({ - type: actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS, - processId: process.id - }); - }); - - }, - - closeEditor(dispatch) { - dispatch({ - type:actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE - }); - }, - - saveProcess(dispatch, {softwareProductId, version, previousProcess, process}) { - if (previousProcess) { - return putProcess(softwareProductId, version, process).then(() => { - if (process.formData){ - uploadFileToProcess(softwareProductId, version, process.id, process.formData); - } - dispatch({ - type: actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS, - process - }); - }); - } - else { - return postProcess(softwareProductId, version, process).then(response => { - if (process.formData) { - uploadFileToProcess(softwareProductId, version, response.value, process.formData); - } - dispatch({ - type: actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS, - process: { - ...process, - id: response.value - } - }); - }); - } - }, - - hideDeleteConfirm(dispatch) { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM, - processToDelete: false - }); - }, - - openDeleteProcessesConfirm(dispatch, {process} ) { - dispatch({ - type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM, - processToDelete: process - }); - } - + fetchProcessesList(dispatch, { softwareProductId, version }) { + dispatch({ + type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES, + processesList: [] + }); + + return fetchProcesses(softwareProductId, version).then(response => { + dispatch({ + type: actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES, + processesList: response.results + }); + }); + }, + openEditor(dispatch, process = {}) { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN, + process + }); + }, + + deleteProcess(dispatch, { process, softwareProductId, version }) { + return deleteProcess(softwareProductId, version, process.id).then( + () => { + dispatch({ + type: actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS, + processId: process.id + }); + } + ); + }, + + closeEditor(dispatch) { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE + }); + }, + + saveProcess( + dispatch, + { softwareProductId, version, previousProcess, process } + ) { + if (previousProcess) { + return putProcess(softwareProductId, version, process).then(() => { + if (process.formData) { + uploadFileToProcess( + softwareProductId, + version, + process.id, + process.formData + ); + } + dispatch({ + type: actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS, + process + }); + }); + } else { + return postProcess(softwareProductId, version, process).then( + response => { + if (process.formData) { + uploadFileToProcess( + softwareProductId, + version, + response.value, + process.formData + ); + } + dispatch({ + type: actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS, + process: { + ...process, + id: response.value + } + }); + } + ); + } + }, + + hideDeleteConfirm(dispatch) { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM, + processToDelete: false + }); + }, + + openDeleteProcessesConfirm(dispatch, { process }) { + dispatch({ + type: actionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM, + processToDelete: process + }); + } }; export default SoftwareProductActionHelper; - diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js index 6eee24cdde..7f09ea8e73 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js @@ -16,20 +16,20 @@ import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ - ADD_SOFTWARE_PRODUCT_PROCESS: null, - EDIT_SOFTWARE_PRODUCT_PROCESS: null, - DELETE_SOFTWARE_PRODUCT_PROCESS: null, - SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN: null, - SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE: null, - FETCH_SOFTWARE_PRODUCT_PROCESSES: null, - SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM: null + ADD_SOFTWARE_PRODUCT_PROCESS: null, + EDIT_SOFTWARE_PRODUCT_PROCESS: null, + DELETE_SOFTWARE_PRODUCT_PROCESS: null, + SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN: null, + SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE: null, + FETCH_SOFTWARE_PRODUCT_PROCESSES: null, + SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM: null }); export const optionsInputValues = { - PROCESS_TYPE: [ - {title: 'Select...', enum: ''}, - {title: 'Other', enum: 'Other'} - ] + PROCESS_TYPE: [ + { title: 'Select...', enum: '' }, + { title: 'Other', enum: 'Other' } + ] }; export const VSP_PROCESS_FORM = 'VSPPROCESSFORM'; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js index fc194fac13..58cc894a21 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js @@ -13,41 +13,56 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {connect} from 'react-redux'; +import { connect } from 'react-redux'; import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; import SoftwareProductProcessesActionHelper from './SoftwareProductProcessesActionHelper'; import SoftwareProductProcessesEditorView from './SoftwareProductProcessesEditorView.jsx'; -import {VSP_PROCESS_FORM} from './SoftwareProductProcessesConstants.js'; +import { VSP_PROCESS_FORM } from './SoftwareProductProcessesConstants.js'; -export const mapStateToProps = ({softwareProduct}) => { - let {softwareProductProcesses: {processesList, processesEditor}} = softwareProduct; - let {data, genericFieldInfo, formReady} = processesEditor; - let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); - let previousData; - const processId = data ? data.id : null; - if(processId) { - previousData = processesList.find(process => process.id === processId); - } +export const mapStateToProps = ({ softwareProduct }) => { + let { + softwareProductProcesses: { processesList, processesEditor } + } = softwareProduct; + let { data, genericFieldInfo, formReady } = processesEditor; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); + let previousData; + const processId = data ? data.id : null; + if (processId) { + previousData = processesList.find(process => process.id === processId); + } - return { - data, - genericFieldInfo, - previousData, - isFormValid, - formReady - }; + return { + data, + genericFieldInfo, + previousData, + isFormValid, + formReady + }; }; -const mapActionsToProps = (dispatch, {softwareProductId, version}) => { - return { - onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: VSP_PROCESS_FORM}), - onSubmit: ({previousProcess, process}) => { - SoftwareProductProcessesActionHelper.closeEditor(dispatch); - SoftwareProductProcessesActionHelper.saveProcess(dispatch, {softwareProductId, version, previousProcess, process}); - }, - onCancel: () => SoftwareProductProcessesActionHelper.closeEditor(dispatch), - onValidateForm: () => ValidationHelper.validateForm(dispatch, VSP_PROCESS_FORM) - }; +const mapActionsToProps = (dispatch, { softwareProductId, version }) => { + return { + onDataChanged: deltaData => + ValidationHelper.dataChanged(dispatch, { + deltaData, + formName: VSP_PROCESS_FORM + }), + onSubmit: ({ previousProcess, process }) => { + SoftwareProductProcessesActionHelper.closeEditor(dispatch); + SoftwareProductProcessesActionHelper.saveProcess(dispatch, { + softwareProductId, + version, + previousProcess, + process + }); + }, + onCancel: () => + SoftwareProductProcessesActionHelper.closeEditor(dispatch), + onValidateForm: () => + ValidationHelper.validateForm(dispatch, VSP_PROCESS_FORM) + }; }; -export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductProcessesEditorView); +export default connect(mapStateToProps, mapActionsToProps)( + SoftwareProductProcessesEditorView +); diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorForm.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorForm.jsx index d1bd602683..6e8254f65b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorForm.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorForm.jsx @@ -25,157 +25,212 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx'; import GridItem from 'nfvo-components/grid/GridItem.jsx'; const SoftwareProductProcessEditorPropType = PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string, - description: PropTypes.string, - artifactName: PropTypes.string, - type: PropTypes.string + id: PropTypes.string, + name: PropTypes.string, + description: PropTypes.string, + artifactName: PropTypes.string, + type: PropTypes.string }); - - class SoftwareProductProcessesEditorForm extends React.Component { + static propTypes = { + data: SoftwareProductProcessEditorPropType, + previousData: SoftwareProductProcessEditorPropType, + isReadOnlyMode: PropTypes.bool, + onDataChanged: PropTypes.func, + onSubmit: PropTypes.func, + onCancel: PropTypes.func + }; + state = { + dragging: false, + files: [] + }; + render() { + let { + data = {}, + isReadOnlyMode, + onDataChanged, + onCancel, + genericFieldInfo, + optionsInputValues + } = this.props; + let { name, description, artifactName, type } = data; - static propTypes = { - data: SoftwareProductProcessEditorPropType, - previousData: SoftwareProductProcessEditorPropType, - isReadOnlyMode: PropTypes.bool, - onDataChanged: PropTypes.func, - onSubmit: PropTypes.func, - onCancel: PropTypes.func - }; - state = { - dragging: false, - files: [] - }; - - render() { - let {data = {}, isReadOnlyMode, onDataChanged, onCancel, genericFieldInfo, optionsInputValues} = this.props; - let {name, description, artifactName, type} = data; - - return ( - <div> - {genericFieldInfo && <Form - ref='validationForm' - hasButtons={true} - labledButtons={true} - isReadOnlyMode={isReadOnlyMode} - onSubmit={ () => this.submit() } - onReset={ () => onCancel() } - isValid={this.props.isFormValid} - formReady={this.props.formReady} - onValidateForm={() => this.props.onValidateForm() } - className='vsp-processes-editor'> - <div className={`vsp-processes-editor-data${isReadOnlyMode ? ' disabled' : '' }`}> - <Dropzone - className={`vsp-process-dropzone-view ${this.state.dragging ? 'active-dragging' : ''}`} - onDrop={(acceptedFiles, rejectedFiles) => this.handleImportSubmit(acceptedFiles, rejectedFiles)} - onDragEnter={() => this.setState({dragging: true})} - onDragLeave={() => this.setState({dragging: false})} - multiple={false} - disableClick={true} - ref='processEditorFileInput' - name='processEditorFileInput'> - <GridSection hasLastColSet={true}> - <GridItem colSpan={2}> - <Input - onChange={name => onDataChanged({name})} - isValid={genericFieldInfo.name.isValid} - isRequired={true} - data-test-id='name' - errorText={genericFieldInfo.name.errorText} - label={i18n('Name')} - value={name} - type='text'/> - </GridItem> - <GridItem colSpan={2} lastColInRow={true}> - <label> </label> - <DraggableUploadFileBox className='process-editor-file-box' isReadOnlyMode={isReadOnlyMode} onClick={() => this.refs.processEditorFileInput.open()}/> - </GridItem> - </GridSection> - <GridSection hasLastColSet={true}> - <GridItem colSpan={2}> - <Input - name='vsp-process-description' - groupClassName='vsp-process-description' - onChange={description => onDataChanged({description})} - isValid={genericFieldInfo.description.isValid} - errorText={genericFieldInfo.description.errorText} - label={i18n('Notes')} - value={description} - data-test-id='vsp-process-description' - type='textarea'/> - </GridItem> - <GridItem colSpan={2} lastColInRow={true}> - <Input - label={i18n('Artifacts')} - value={artifactName} - type='text' - disabled/> - <Input - onChange={e => { - // setting the unit to the correct value - const selectedIndex = e.target.selectedIndex; - const val = e.target.options[selectedIndex].value; - onDataChanged({type: val});} - } - value={type} - label={i18n('Process Type')} - className='process-type' - data-test-id='process-type' - isValid={genericFieldInfo.type.isValid} - errorText={genericFieldInfo.type.errorText} - type='select'> - {optionsInputValues.PROCESS_TYPE.map(mtype => - <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)} - </Input> - </GridItem> - </GridSection> - </Dropzone> - </div> - </Form>} - </div> - ); - } - - submit() { - const {data: process, previousData: previousProcess} = this.props; - let {files} = this.state; - let formData = false; - if (files.length) { - let file = files[0]; - formData = new FormData(); - formData.append('upload', file); - } + return ( + <div> + {genericFieldInfo && ( + <Form + ref="validationForm" + hasButtons={true} + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + onSubmit={() => this.submit()} + onReset={() => onCancel()} + isValid={this.props.isFormValid} + formReady={this.props.formReady} + onValidateForm={() => this.props.onValidateForm()} + className="vsp-processes-editor"> + <div + className={`vsp-processes-editor-data${ + isReadOnlyMode ? ' disabled' : '' + }`}> + <Dropzone + className={`vsp-process-dropzone-view ${ + this.state.dragging ? 'active-dragging' : '' + }`} + onDrop={(acceptedFiles, rejectedFiles) => + this.handleImportSubmit( + acceptedFiles, + rejectedFiles + ) + } + onDragEnter={() => + this.setState({ dragging: true }) + } + onDragLeave={() => + this.setState({ dragging: false }) + } + multiple={false} + disableClick={true} + ref="processEditorFileInput" + name="processEditorFileInput"> + <GridSection hasLastColSet={true}> + <GridItem colSpan={2}> + <Input + onChange={name => + onDataChanged({ name }) + } + isValid={ + genericFieldInfo.name.isValid + } + isRequired={true} + data-test-id="name" + errorText={ + genericFieldInfo.name.errorText + } + label={i18n('Name')} + value={name} + type="text" + /> + </GridItem> + <GridItem colSpan={2} lastColInRow={true}> + <label> </label> + <DraggableUploadFileBox + className="process-editor-file-box" + isReadOnlyMode={isReadOnlyMode} + onClick={() => + this.refs.processEditorFileInput.open() + } + /> + </GridItem> + </GridSection> + <GridSection hasLastColSet={true}> + <GridItem colSpan={2}> + <Input + name="vsp-process-description" + groupClassName="vsp-process-description" + onChange={description => + onDataChanged({ description }) + } + isValid={ + genericFieldInfo.description + .isValid + } + errorText={ + genericFieldInfo.description + .errorText + } + label={i18n('Notes')} + value={description} + data-test-id="vsp-process-description" + type="textarea" + /> + </GridItem> + <GridItem colSpan={2} lastColInRow={true}> + <Input + label={i18n('Artifacts')} + value={artifactName} + type="text" + disabled + /> + <Input + onChange={e => { + // setting the unit to the correct value + const selectedIndex = + e.target.selectedIndex; + const val = + e.target.options[ + selectedIndex + ].value; + onDataChanged({ type: val }); + }} + value={type} + label={i18n('Process Type')} + className="process-type" + data-test-id="process-type" + isValid={ + genericFieldInfo.type.isValid + } + errorText={ + genericFieldInfo.type.errorText + } + type="select"> + {optionsInputValues.PROCESS_TYPE.map( + mtype => ( + <option + key={mtype.enum} + value={mtype.enum}>{`${ + mtype.title + }`}</option> + ) + )} + </Input> + </GridItem> + </GridSection> + </Dropzone> + </div> + </Form> + )} + </div> + ); + } - let updatedProcess = { - ...process, - formData - }; - this.props.onSubmit({process: updatedProcess, previousProcess}); - } + submit() { + const { data: process, previousData: previousProcess } = this.props; + let { files } = this.state; + let formData = false; + if (files.length) { + let file = files[0]; + formData = new FormData(); + formData.append('upload', file); + } + let updatedProcess = { + ...process, + formData + }; + this.props.onSubmit({ process: updatedProcess, previousProcess }); + } - handleImportSubmit(files, rejectedFiles) { - if (files.length > 0) { - let {onDataChanged} = this.props; - this.setState({ - dragging: false, - complete: '0', - files - }); - onDataChanged({artifactName: files[0].name}); - } - else if (rejectedFiles.length > 0) { - this.setState({ - dragging: false - }); - if (DEBUG) { - console.log('file was rejected.' + rejectedFiles[0].name); - } - } - } + handleImportSubmit(files, rejectedFiles) { + if (files.length > 0) { + let { onDataChanged } = this.props; + this.setState({ + dragging: false, + complete: '0', + files + }); + onDataChanged({ artifactName: files[0].name }); + } else if (rejectedFiles.length > 0) { + this.setState({ + dragging: false + }); + if (DEBUG) { + console.log('file was rejected.' + rejectedFiles[0].name); + } + } + } } export default SoftwareProductProcessesEditorForm; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js index 11b89b17c2..a8731fd163 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js @@ -13,43 +13,49 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes, VSP_PROCESS_FORM} from './SoftwareProductProcessesConstants.js'; +import { + actionTypes, + VSP_PROCESS_FORM +} from './SoftwareProductProcessesConstants.js'; export default (state = {}, action) => { - switch (action.type) { - case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN: - return { - ...state, - formReady: null, - formName: VSP_PROCESS_FORM, - genericFieldInfo: { - 'name' : { - isValid: true, - errorText: '', - validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}] - }, - 'description' : { - isValid: true, - errorText: '', - validations: [{type: 'maxLength', data: 1000}] - }, - 'artifactName' : { - isValid: true, - errorText: '', - validations: [] - }, - 'type' : { - isValid: true, - errorText: '', - validations: [] - } - }, - data: action.process - }; - case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE: - return {}; + switch (action.type) { + case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN: + return { + ...state, + formReady: null, + formName: VSP_PROCESS_FORM, + genericFieldInfo: { + name: { + isValid: true, + errorText: '', + validations: [ + { type: 'required', data: true }, + { type: 'maxLength', data: 120 } + ] + }, + description: { + isValid: true, + errorText: '', + validations: [{ type: 'maxLength', data: 1000 }] + }, + artifactName: { + isValid: true, + errorText: '', + validations: [] + }, + type: { + isValid: true, + errorText: '', + validations: [] + } + }, + data: action.process + }; + case actionTypes.SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE: + return {}; - default: - return state; - } + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx index 9ce690a1ca..867090bb31 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx @@ -15,16 +15,18 @@ */ import React from 'react'; -import {optionsInputValues as ProcessesOptionsInputValues} from './SoftwareProductProcessesConstants.js'; +import { optionsInputValues as ProcessesOptionsInputValues } from './SoftwareProductProcessesConstants.js'; import SoftwareProductProcessesEditorForm from './SoftwareProductProcessesEditorForm.jsx'; - class SoftwareProductProcessesEditorView extends React.Component { - render() { - return ( - <SoftwareProductProcessesEditorForm optionsInputValues={ProcessesOptionsInputValues} {...this.props}/> - ); - } + render() { + return ( + <SoftwareProductProcessesEditorForm + optionsInputValues={ProcessesOptionsInputValues} + {...this.props} + /> + ); + } } export default SoftwareProductProcessesEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js index 20390d1f60..0e4d94650e 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js @@ -13,20 +13,26 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {actionTypes} from './SoftwareProductProcessesConstants.js'; +import { actionTypes } from './SoftwareProductProcessesConstants.js'; export default (state = [], action) => { - switch (action.type) { - case actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES: - return [...action.processesList]; - case actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS: - const indexForEdit = state.findIndex(process => process.id === action.process.id); - return [...state.slice(0, indexForEdit), action.process, ...state.slice(indexForEdit + 1)]; - case actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS: - return [...state, action.process]; - case actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS: - return state.filter(process => process.id !== action.processId); - default: - return state; - } + switch (action.type) { + case actionTypes.FETCH_SOFTWARE_PRODUCT_PROCESSES: + return [...action.processesList]; + case actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS: + const indexForEdit = state.findIndex( + process => process.id === action.process.id + ); + return [ + ...state.slice(0, indexForEdit), + action.process, + ...state.slice(indexForEdit + 1) + ]; + case actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS: + return [...state, action.process]; + case actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS: + return state.filter(process => process.id !== action.processId); + default: + return state; + } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx index b0da767a2b..1357c31e12 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx @@ -20,45 +20,63 @@ import Modal from 'nfvo-components/modal/Modal.jsx'; import SoftwareProductProcessesEditor from './SoftwareProductProcessesEditor.js'; import SoftwareProductProcessListView from './SoftwareProductProcessListView.jsx'; - class SoftwareProductProcessesView extends React.Component { + state = { + localFilter: '' + }; - state = { - localFilter: '' - }; - - static propTypes = { - onAddProcess: PropTypes.func.isRequired, - onEditProcess: PropTypes.func.isRequired, - onDeleteProcess: PropTypes.func.isRequired, - isDisplayEditor: PropTypes.bool.isRequired, - isReadOnlyMode: PropTypes.bool.isRequired, - currentSoftwareProduct:PropTypes.object - }; - - render() { - return ( - <div className='software-product-landing-view-right-side vsp-processes-page'> - {this.renderEditor()} - <SoftwareProductProcessListView addButtonTitle={i18n('Add Process Details')} {...this.props}/> - </div> - ); - } + static propTypes = { + onAddProcess: PropTypes.func.isRequired, + onEditProcess: PropTypes.func.isRequired, + onDeleteProcess: PropTypes.func.isRequired, + isDisplayEditor: PropTypes.bool.isRequired, + isReadOnlyMode: PropTypes.bool.isRequired, + currentSoftwareProduct: PropTypes.object + }; - renderEditor() { - let {currentSoftwareProduct: {id}, version, isModalInEditMode, isReadOnlyMode, isDisplayEditor} = this.props; - return ( + render() { + return ( + <div className="software-product-landing-view-right-side vsp-processes-page"> + {this.renderEditor()} + <SoftwareProductProcessListView + addButtonTitle={i18n('Add Process Details')} + {...this.props} + /> + </div> + ); + } - <Modal show={isDisplayEditor} bsSize='large' animation={true} className='onborading-modal'> - <Modal.Header> - <Modal.Title>{isModalInEditMode ? i18n('Edit Process Details') : i18n('Create New Process Details')}</Modal.Title> - </Modal.Header> - <Modal.Body className='edit-process-modal'> - <SoftwareProductProcessesEditor softwareProductId={id} version={version} isReadOnlyMode={isReadOnlyMode}/> - </Modal.Body> - </Modal> - ); - } + renderEditor() { + let { + currentSoftwareProduct: { id }, + version, + isModalInEditMode, + isReadOnlyMode, + isDisplayEditor + } = this.props; + return ( + <Modal + show={isDisplayEditor} + bsSize="large" + animation={true} + className="onborading-modal"> + <Modal.Header> + <Modal.Title> + {isModalInEditMode + ? i18n('Edit Process Details') + : i18n('Create New Process Details')} + </Modal.Title> + </Modal.Header> + <Modal.Body className="edit-process-modal"> + <SoftwareProductProcessesEditor + softwareProductId={id} + version={version} + isReadOnlyMode={isReadOnlyMode} + /> + </Modal.Body> + </Modal> + ); + } } export default SoftwareProductProcessesView; |