summaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src
diff options
context:
space:
mode:
Diffstat (limited to 'openecomp-ui/src')
-rw-r--r--openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx175
-rw-r--r--openecomp-ui/src/nfvo-components/activity-log/ActivityLog.js27
-rw-r--r--openecomp-ui/src/nfvo-components/activity-log/ActivityLogActionHelper.js31
-rw-r--r--openecomp-ui/src/nfvo-components/activity-log/ActivityLogConstants.js23
-rw-r--r--openecomp-ui/src/nfvo-components/activity-log/ActivityLogReducer.js25
-rw-r--r--openecomp-ui/src/nfvo-components/activity-log/ActivityLogView.jsx124
-rw-r--r--openecomp-ui/src/nfvo-components/confirmations/ConfirmationModalView.jsx53
-rw-r--r--openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx31
-rw-r--r--openecomp-ui/src/nfvo-components/grid/GridItem.jsx26
-rw-r--r--openecomp-ui/src/nfvo-components/grid/GridSection.jsx33
-rw-r--r--openecomp-ui/src/nfvo-components/icon/Icon.jsx45
-rw-r--r--openecomp-ui/src/nfvo-components/icon/SVGIcon.jsx54
-rw-r--r--openecomp-ui/src/nfvo-components/icon/SVGIcon.stories.js50
-rw-r--r--openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx140
-rw-r--r--openecomp-ui/src/nfvo-components/input/SelectInput.jsx18
-rw-r--r--openecomp-ui/src/nfvo-components/input/ToggleInput.jsx15
-rw-r--r--openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx67
-rw-r--r--openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx55
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/Form.jsx114
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/Input.jsx180
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx279
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx134
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx79
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx21
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/ValidationForm.jsx200
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/ValidationInput.jsx509
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/ValidationTab.jsx107
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/ValidationTabs.jsx72
-rw-r--r--openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx38
-rw-r--r--openecomp-ui/src/nfvo-components/listEditor/ListEditorItemViewField.jsx24
-rw-r--r--openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx99
-rw-r--r--openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js60
-rw-r--r--openecomp-ui/src/nfvo-components/loader/Loader.jsx15
-rw-r--r--openecomp-ui/src/nfvo-components/loader/LoaderConstants.js21
-rw-r--r--openecomp-ui/src/nfvo-components/loader/LoaderReducer.js21
-rw-r--r--openecomp-ui/src/nfvo-components/modal/GlobalModal.js120
-rw-r--r--openecomp-ui/src/nfvo-components/modal/GlobalModalConstants.js33
-rw-r--r--openecomp-ui/src/nfvo-components/modal/GlobalModalReducer.js50
-rw-r--r--openecomp-ui/src/nfvo-components/modal/Modal.jsx15
-rw-r--r--openecomp-ui/src/nfvo-components/notifications/NotificationConstants.js29
-rw-r--r--openecomp-ui/src/nfvo-components/notifications/NotificationModal.jsx100
-rw-r--r--openecomp-ui/src/nfvo-components/notifications/NotificationReducer.js51
-rw-r--r--openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx125
-rw-r--r--openecomp-ui/src/nfvo-components/panel/SlidePanel.jsx109
-rw-r--r--openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx245
-rw-r--r--openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js29
-rw-r--r--openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js39
-rw-r--r--openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx15
-rw-r--r--openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx29
-rw-r--r--openecomp-ui/src/nfvo-components/table/SelectActionTableCell.jsx20
-rw-r--r--openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx30
-rw-r--r--openecomp-ui/src/nfvo-utils/DirectedGraph.js45
-rw-r--r--openecomp-ui/src/nfvo-utils/ErrorResponseHandler.js38
-rw-r--r--openecomp-ui/src/nfvo-utils/KeyMirror.js23
-rw-r--r--openecomp-ui/src/nfvo-utils/RestAPIUtil.js304
-rw-r--r--openecomp-ui/src/nfvo-utils/UUID.js21
-rw-r--r--openecomp-ui/src/nfvo-utils/Validator.js110
-rw-r--r--openecomp-ui/src/nfvo-utils/i18n/i18n.js21
-rw-r--r--openecomp-ui/src/nfvo-utils/json/JSONPointer.js23
-rw-r--r--openecomp-ui/src/nfvo-utils/json/JSONSchema.js127
-rw-r--r--openecomp-ui/src/nfvo-utils/sortByStringProperty.js18
-rw-r--r--openecomp-ui/src/sdc-app/AppStore.js43
-rw-r--r--openecomp-ui/src/sdc-app/Application.jsx19
-rw-r--r--openecomp-ui/src/sdc-app/ModulesOptions.jsx21
-rw-r--r--openecomp-ui/src/sdc-app/Test.jsx122
-rw-r--r--openecomp-ui/src/sdc-app/common/helpers/ValidationHelper.js91
-rw-r--r--openecomp-ui/src/sdc-app/common/modal/ModalContentMapper.js31
-rw-r--r--openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducer.js145
-rw-r--r--openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducerConstants.js23
-rw-r--r--openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js94
-rw-r--r--openecomp-ui/src/sdc-app/common/reducers/PlainDataReducerConstants.js22
-rw-r--r--openecomp-ui/src/sdc-app/config/Configuration.js25
-rw-r--r--openecomp-ui/src/sdc-app/config/config.json2
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsActions.js46
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsConstants.js23
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsEditorModal.js46
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsEditorModalView.jsx38
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsListEditor.js31
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsListEditorView.jsx20
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsListReducer.js56
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsPunchOut.jsx15
-rw-r--r--openecomp-ui/src/sdc-app/flows/FlowsReducersMap.js23
-rw-r--r--openecomp-ui/src/sdc-app/flows/ImportantLogic.jsx15
-rw-r--r--openecomp-ui/src/sdc-app/flows/SequenceDiagram.jsx17
-rw-r--r--openecomp-ui/src/sdc-app/flows/SequenceDiagramModelHelper.js21
-rw-r--r--openecomp-ui/src/sdc-app/heatValidation.app.jsx16
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/Attachments.js44
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/HeatSetup.js28
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/UploadScreen.jsx186
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/UploadScreenActionHelper.js200
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/UploadScreenConstants.js28
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/UploadScreenReducer.js33
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/attachments/Attachments.js46
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx190
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js158
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingCatalog.js59
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingCatalogView.jsx147
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingConstants.js30
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx387
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingReducers.js23
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingReducersMap.js28
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js78
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js124
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js23
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js79
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js48
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js26
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js47
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx67
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js54
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js33
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js77
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx363
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js41
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx67
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js74
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx413
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx86
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js118
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx48
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js44
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js52
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js84
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx43
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js41
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js60
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js64
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx326
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js48
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx66
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js59
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx49
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js41
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js48
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js57
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx183
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js163
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js42
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx105
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx33
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx123
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx53
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx53
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx48
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx26
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx56
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js126
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js86
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx134
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx62
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx56
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js90
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js28
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx95
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js85
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js30
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx98
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx24
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js38
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx74
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx96
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx57
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js25
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js182
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js340
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js72
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js61
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js95
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js44
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js60
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js199
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsUtils.js25
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx253
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js62
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js77
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js42
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js124
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx328
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidation.js51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js (renamed from openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsActionHelper.js)25
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js (renamed from openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsConstants.js)28
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js (renamed from openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsReducer.js)35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationView.jsx274
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js57
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js117
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js33
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js25
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentComputeView.jsx149
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx76
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx94
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/VmSizing.jsx68
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js49
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx430
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancing.js34
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx134
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js38
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js70
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringConstants.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorReducer.js51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx356
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js96
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js27
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js46
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx104
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Acceptable.jsx75
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/FlowLength.jsx35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/InFlowTraffic.jsx35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/IpConfig.jsx45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx54
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx62
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/OutFlowTraffic.jsx35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/PacketsBytes.jsx65
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Protocols.jsx74
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Sizing.jsx39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesActionHelper.js76
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditor.js42
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorReducer.js56
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesEditorView.jsx189
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesList.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesConfirmationModal.jsx45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesListView.jsx36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx256
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js56
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js62
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js26
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js64
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx140
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js40
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js58
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js29
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js64
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx98
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js47
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js56
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx480
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js63
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageUploadConfirmationModal.jsx38
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx91
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js29
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx34
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js34
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js74
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConfirmationModal.jsx45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js43
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js55
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx202
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx35
-rw-r--r--openecomp-ui/src/sdc-app/punch-outs.js21
-rw-r--r--openecomp-ui/src/sdc-app/sdc.app.jsx16
295 files changed, 13677 insertions, 7958 deletions
diff --git a/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx b/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx
index f2ec1582f3..0759f2c28d 100644
--- a/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx
+++ b/openecomp-ui/src/nfvo-components/SubmitErrorResponse.jsx
@@ -1,9 +1,24 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React, {Component} from 'react';
import ListGroupItem from 'react-bootstrap/lib/ListGroupItem.js';
-import ListGroup from 'react-bootstrap/lib/ListGroup.js';
-import Panel from 'react-bootstrap/lib/Panel.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
-
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import Icon from 'nfvo-components/icon/Icon.jsx';
+import {Collapse} from 'react-bootstrap';
/**
* parsing and showing the following Java Response object
*
@@ -31,103 +46,117 @@ class SubmitErrorResponse extends Component {
render() {
- let {validationResponse} = this.props;
+ let {validationResponse : {vspErrors, licensingDataErrors, questionnaireValidationResult, uploadDataErrors}} = this.props;
return (
<div className='submit-error-response-view'>
- {validationResponse.vspErrors && this.renderVspErrors(validationResponse.vspErrors)}
- {validationResponse.licensingDataErrors && this.renderVspErrors(validationResponse.licensingDataErrors)}
- {validationResponse.compilationErrors && this.renderCompilationErrors(validationResponse.compilationErrors)}
- {validationResponse.uploadDataErrors && this.renderUploadDataErrors(validationResponse.uploadDataErrors)}
- {validationResponse.questionnaireValidationResult && this.renderQuestionnaireValidationResult(validationResponse.questionnaireValidationResult)}
+ {vspErrors && this.renderVspErrors(vspErrors)}
+ {licensingDataErrors && this.renderVspErrors(licensingDataErrors)}
+ {questionnaireValidationResult && this.renderComponentsErrors(questionnaireValidationResult)}
+ {uploadDataErrors && this.renderUploadDataErrors(uploadDataErrors)}
</div>
);
}
- renderVspErrors(vspErrors) {
+ renderVspErrors(errors) {
return (
- <Panel header={i18n('VSP Errors')} collapsible>{this.parseErrorCodeCollection(vspErrors)}</Panel>
+ <ErrorBlock errorType={i18n('VSP Errors')}>
+ <div>
+ {errors.length && errors.map(error=>{return (<ErrorMessage error={error.message}/>);})}
+ </div>
+ </ErrorBlock>
);
}
- renderLicensingDataErrors(licensingDataErrors) {
+
+ renderComponentsErrors(errors) {
return (
- <Panel
- header={i18n('Licensing Data Errors')}
- collapsible>{this.parseErrorCodeCollection(licensingDataErrors)}
- </Panel>
+ <ErrorBlock errorType={i18n('Components Errors')}>
+ <div>
+ {errors.validationData.length && errors.validationData.map(item =>{ return (<ComponentError item={item}/>);})}
+ </div>
+ </ErrorBlock>
);
}
renderUploadDataErrors(uploadDataErrors) {
return (
- <Panel
- header={i18n('Upload Data Errors')}
- collapsible>{this.parseMapOfErrorMessagesList(uploadDataErrors)}
- </Panel>
+ <ErrorBlock errorType={i18n('Upload Data Errors')}>
+ <div>
+ <UploadErrorList items={uploadDataErrors}/>
+ </div>
+ </ErrorBlock>
);
}
+}
- renderCompilationErrors(compilationErrors) {
- return (
- <Panel
- header={i18n('Compilation Errors')}
- collapsible>{this.parseMapOfErrorMessagesList(compilationErrors)}
- </Panel>
- );
- }
- parseErrorCodeCollection(errors) {
- return (
- <ListGroup>{errors.map(error =>
- <ListGroupItem className='error-code-list-item'>
- <div><span>{i18n('Category: ')}</span>{error.category}</div>
- <div><span>{i18n('Message: ')}</span>{error.message}</div>
- </ListGroupItem>
- )}</ListGroup>
- );
- }
+const ComponentError = ({item}) => {
+ let i = 0;
+ return (
+ <div>
+ <div className='component-name-header'>{item.entityName}</div>
+ {item.errors.map(error => {return(<ErrorMessage key={i++} error={error}/>);})}
+ </div>
+ );
+};
- parseMapOfErrorMessagesList(errorMap) {
- return (
- <ListGroup>
- {Object.keys(errorMap).map(errorStringKey =>
- <Panel header={errorStringKey} collapsible>
- <ListGroup>{errorMap[errorStringKey].map(error =>
- <ListGroupItem className='error-code-list-item'>
- <div><span>{i18n('Level: ')}</span>{error.level}</div>
- <div><span>{i18n('Message: ')}</span>{error.message}</div>
- </ListGroupItem>
- )}</ListGroup>
- </Panel>
- )}
- </ListGroup>
- );
+function* entries(obj) {
+ for (let key of Object.keys(obj)) {
+ yield {header: key, list: obj[key]};
}
+}
+const UploadErrorList = ({items}) => {
+ let generator = entries(items);
+
+ let errors = [];
+ let i = 0;
+ for (let item of generator) {errors.push(
+ <div>
+ <div className='component-name-header'>{item.header}</div>
+ {item.list.map(error => <ErrorMessage key={i++} warning={error.level === 'WARNING'} error={error.message}/> )}
+ </div>
+ );}
+ return (
+ <div>
+ {errors}
+ </div>
+ );
+};
+
+class ErrorBlock extends React.Component {
+ state = {
+ collapsed: false
+ };
- renderQuestionnaireValidationResult(questionnaireValidationResult) {
- if (!questionnaireValidationResult.valid) {
- return this.parseAndRenderCompositionEntityValidationData(questionnaireValidationResult.validationData);
- }
- }
-
- parseAndRenderCompositionEntityValidationData(validationData) {
- let {entityType, entityId, errors = [], subEntitiesValidationData = []} = validationData;
+ render() {
+ let {errorType, children} = this.props;
return (
- <ListGroup>
- <Panel header={`${entityType}: ${entityId}`} collapsible>
- <ListGroup>{errors.map(error =>
- <ListGroupItem className='error-code-list-item'>
- <div>{error}</div>
- </ListGroupItem>
- )}</ListGroup>
- {subEntitiesValidationData.map(subValidationData => this.parseAndRenderCompositionEntityValidationData(subValidationData))}
- </Panel>
- </ListGroup>
+ <div className='error-block'>
+ <ErrorHeader collapsed={this.state.collapsed} onClick={()=>{this.setState({collapsed: !this.state.collapsed});}} errorType={errorType}/>
+ <Collapse in={this.state.collapsed}>
+ {children}
+ </Collapse>
+ </div>
);
}
-
-
}
+const ErrorHeader = ({errorType, collapsed, onClick}) => {
+ return(
+ <div onClick={onClick} className='error-block-header'>
+ <SVGIcon iconClassName={collapsed ? '' : 'right' } name='chevron-down'/>
+ {errorType}
+ </div>
+ );
+};
+
+const ErrorMessage = ({error, warning}) => {
+ return (
+ <ListGroupItem className='error-code-list-item'>
+ <Icon image={warning ? 'warning' : 'error'} label={error}/>
+ </ListGroupItem>
+ );
+};
+
export default SubmitErrorResponse;
diff --git a/openecomp-ui/src/nfvo-components/activity-log/ActivityLog.js b/openecomp-ui/src/nfvo-components/activity-log/ActivityLog.js
new file mode 100644
index 0000000000..f7354f96e2
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/activity-log/ActivityLog.js
@@ -0,0 +1,27 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {connect} from 'react-redux';
+import ActivityLogView from './ActivityLogView.jsx';
+
+export const mapStateToProps = ({licenseModel: {activityLog}}) => {
+
+ let activities = activityLog;
+ return {
+ activities
+ };
+};
+
+export default connect(mapStateToProps, undefined, null, {withRef: true})(ActivityLogView);
diff --git a/openecomp-ui/src/nfvo-components/activity-log/ActivityLogActionHelper.js b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogActionHelper.js
new file mode 100644
index 0000000000..01a27abbc5
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogActionHelper.js
@@ -0,0 +1,31 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import ActivityLogConstants from './ActivityLogConstants.js';
+
+
+function baseUrl(itemId, versionId) {
+ const restPrefix = Configuration.get('restPrefix');
+ return `${restPrefix}/v1.0/activity-logs/${itemId}/versions/${versionId}`;
+}
+
+export default {
+
+ fetchActivityLog(dispatch, {itemId, versionId}){
+ return RestAPIUtil.fetch(baseUrl(itemId, versionId)).then(response => dispatch({type: ActivityLogConstants.ACTIVITY_LOG_UPDATED, response}));
+ }
+};
diff --git a/openecomp-ui/src/nfvo-components/activity-log/ActivityLogConstants.js b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogConstants.js
new file mode 100644
index 0000000000..69faf7cbb6
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogConstants.js
@@ -0,0 +1,23 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export default keyMirror({
+
+ ACTIVITY_LOG_UPDATED: null
+
+});
+
diff --git a/openecomp-ui/src/nfvo-components/activity-log/ActivityLogReducer.js b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogReducer.js
new file mode 100644
index 0000000000..fc3dfa1515
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogReducer.js
@@ -0,0 +1,25 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import ActivityLogConstants from './ActivityLogConstants.js';
+
+export default (state = [], action) => {
+ switch (action.type) {
+ case ActivityLogConstants.ACTIVITY_LOG_UPDATED:
+ return [...action.response.results];
+ }
+
+ return state;
+};
diff --git a/openecomp-ui/src/nfvo-components/activity-log/ActivityLogView.jsx b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogView.jsx
new file mode 100644
index 0000000000..6ff3c806a8
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/activity-log/ActivityLogView.jsx
@@ -0,0 +1,124 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component} from 'react';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+function ActivityLogSortableCellHeader({isHeader, data, isDes, onSort}) {
+ if (isHeader) {
+ return (
+ <span className='date-header' onClick={onSort}>
+ <span>{data}</span>
+ <span className={`header-sort-arrow ${isDes ? 'up' : 'down'}`}></span>
+ </span>
+ );
+ }
+ return (
+ <span className='date-cell'>
+ <span>{i18n.dateNormal(data, {
+ year: 'numeric', month: 'numeric', day: 'numeric'
+ })}</span>
+ <span>{i18n.dateNormal(data, {
+ hour: 'numeric', minute: 'numeric',
+ hour12: true
+ })}</span>
+ </span>
+ );
+}
+
+function ActivityLogStatus({status, isHeader}) {
+ if (isHeader) {
+ return <span>{status}</span>;
+ }
+ let {message, success} = status;
+ return (
+ <span>
+ <span className={`status-icon ${success}`}>{`${success ? i18n('Success') : i18n('Failure')}`}</span>
+ {success && <SVGIcon name='check-circle'/>}
+ {!success && <OverlayTrigger placement='bottom' overlay={<Tooltip className='activity-log-message-tooltip' id={'activity-log-message-tooltip'}>
+ <div className='message-block'>{message}</div>
+ </Tooltip>}>
+ <span className='message-further-info-icon'>{'?'}</span>
+ </OverlayTrigger>}
+ </span>
+ );
+}
+
+export function ActivityListItem({activity, isHeader, isDes, onSort}) {
+ let {type, timestamp, comment, user, status} = activity;
+ return (
+ <li className={`activity-list-item ${isHeader ? 'header' : ''}`} data-test-id='activity-list-item'>
+ <div className='table-cell activity-date' data-test-id='activity-date'><ActivityLogSortableCellHeader isHeader={isHeader} data={timestamp} isDes={isDes} onSort={onSort}/></div>
+ <div className='table-cell activity-action' data-test-id='activity-action'>{type}</div>
+ <div className='table-cell activity-comment' title={comment} data-test-id='activity-comment'><span>{comment}</span></div>
+ <div className='table-cell activity-username' data-test-id='activity-username'>{user}</div>
+ <div className='table-cell activity-status' data-test-id='activity-status'><ActivityLogStatus isHeader={isHeader} status={status}/></div>
+ </li>
+ );
+}
+
+class ActivityLogView extends Component {
+
+ state = {
+ localFilter: '',
+ sortDescending: true
+ };
+
+ render() {
+ return (
+ <div className='activity-log-view'>
+ <ListEditorView
+ title={i18n('Activity Log')}
+ filterValue={this.state.localFilter}
+ onFilter={filter => this.setState({localFilter: filter})}>
+ <ActivityListItem
+ isHeader={true}
+ activity={{timestamp: 'Date', type: 'Action', comment: 'Comment', user: 'Username', status: 'Status'}}
+ isDes={this.state.sortDescending}
+ onSort={() => this.setState({sortDescending: !this.state.sortDescending})}/>
+ {this.sortActivities(this.filterActivities(), this.state.sortDescending).map(activity => <ActivityListItem key={activity.id} activity={activity}/>)}
+ </ListEditorView>
+ </div>
+ );
+ }
+
+ filterActivities() {
+ let {activities} = this.props;
+ let {localFilter} = this.state;
+ if (localFilter.trim()) {
+ const filter = new RegExp(escape(localFilter), 'i');
+ return activities.filter(({user = '', comment = '', type = ''}) => escape(user).match(filter) || escape(comment).match(filter) || escape(type).match(filter));
+ }
+ else {
+ return activities;
+ }
+ }
+
+ sortActivities(activities) {
+ if (this.state.sortDescending) {
+ return activities.sort((a, b) => a.timestamp - b.timestamp);
+ }
+ else {
+ return activities.reverse();
+ }
+ }
+
+}
+
+export default ActivityLogView;
diff --git a/openecomp-ui/src/nfvo-components/confirmations/ConfirmationModalView.jsx b/openecomp-ui/src/nfvo-components/confirmations/ConfirmationModalView.jsx
deleted file mode 100644
index cc971c608c..0000000000
--- a/openecomp-ui/src/nfvo-components/confirmations/ConfirmationModalView.jsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import React from 'react';
-import Button from 'react-bootstrap/lib/Button.js';
-
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import Modal from 'nfvo-components/modal/Modal.jsx';
-
-let typeClass = {
- 'default': 'primary',
- error: 'danger',
- warning: 'warning',
- success: 'success'
-};
-
-
-class ConfirmationModalView extends React.Component {
-
- static propTypes = {
- show: React.PropTypes.bool,
- type: React.PropTypes.oneOf(['default', 'error', 'warning', 'success']),
- msg: React.PropTypes.node,
- title: React.PropTypes.string,
- confirmationDetails: React.PropTypes.object,
- confirmationButtonText: React.PropTypes.string,
-
- };
-
- static defaultProps = {
- show: false,
- type: 'warning',
- title: 'Warning',
- msg: '',
- confirmationButtonText: i18n('Delete')
- };
-
- render() {
- let {title, type, msg, show, confirmationButtonText} = this.props;
-
- return(
- <Modal show={show} className={`notification-modal ${typeClass[type]}`}>
- <Modal.Header>
- <Modal.Title>{title}</Modal.Title>
- </Modal.Header>
- <Modal.Body>{msg}</Modal.Body>
- <Modal.Footer>
- <Button bsStyle={typeClass[type]} onClick={() => this.props.onDeclined(this.props.confirmationDetails)}>{i18n('Cancel')}</Button>
- <Button bsStyle={typeClass[type]} onClick={() => this.props.onConfirmed(this.props.confirmationDetails)}>{confirmationButtonText}</Button>
- </Modal.Footer>
- </Modal>
- );
- };
-}
-
-export default ConfirmationModalView;
diff --git a/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx b/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx
index 4a106b5ff4..2a0b7d4d2a 100644
--- a/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx
+++ b/openecomp-ui/src/nfvo-components/editor/TabulatedEditor.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import classnames from 'classnames';
@@ -7,10 +22,17 @@ import NavigationSideBar from 'nfvo-components/panel/NavigationSideBar.jsx';
export default class TabulatedEditor extends React.Component {
render() {
- const {versionControllerProps, navigationBarProps, onToggle, onVersionSwitching, onCreate, onSave, onClose, onVersionControllerAction, onNavigate, children} = this.props;
+ const {navigationBarProps, onToggle, onVersionSwitching, onCreate, onSave, onClose, onVersionControllerAction, onNavigate, children, meta} = this.props;
+ let {versionControllerProps} = this.props;
const {className = ''} = React.Children.only(children).props;
const child = this.prepareChild();
+ if(onClose) {
+ versionControllerProps = {
+ ...versionControllerProps,
+ onClose: () => onClose(versionControllerProps)
+ };
+ }
return (
<div className='software-product-view'>
<div className='software-product-navigation-side-bar'>
@@ -19,11 +41,10 @@ export default class TabulatedEditor extends React.Component {
<div className='software-product-landing-view-right-side flex-column'>
<VersionController
{...versionControllerProps}
- onVersionSwitching={version => onVersionSwitching(version)}
- callVCAction={onVersionControllerAction}
+ onVersionSwitching={version => onVersionSwitching(version, meta)}
+ callVCAction={(action, version) => onVersionControllerAction(action, version, meta)}
onCreate={onCreate && this.handleCreate}
- onSave={onSave && this.handleSave}
- onClose={() => onClose(versionControllerProps)}/>
+ onSave={onSave && this.handleSave}/>
<div className={classnames('content-area', `${className}`)}>
{
child
diff --git a/openecomp-ui/src/nfvo-components/grid/GridItem.jsx b/openecomp-ui/src/nfvo-components/grid/GridItem.jsx
new file mode 100644
index 0000000000..8819ab78a3
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/grid/GridItem.jsx
@@ -0,0 +1,26 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+const GridItem = ({colSpan = 1, children, stretch = false}) => (
+ <div className={`grid-col-${colSpan}`}>
+ <div className={`grid-item${stretch ? '-stretch' : ''}`}>
+ {children}
+ </div>
+ </div>
+);
+
+export default GridItem;
diff --git a/openecomp-ui/src/nfvo-components/grid/GridSection.jsx b/openecomp-ui/src/nfvo-components/grid/GridSection.jsx
new file mode 100644
index 0000000000..175b3ee082
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/grid/GridSection.jsx
@@ -0,0 +1,33 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+const GridSection = ({title, children, titleClassName}) => {
+ return (
+ <div className='grid-section'>
+ {title && <div className={`section-title ${titleClassName || ''}`}>{title}</div>}
+ <div className='grid-items'>
+ {children}
+ </div>
+ </div>
+ );
+};
+
+GridSection.propTypes = {
+ title: React.PropTypes.string,
+};
+
+export default GridSection;
diff --git a/openecomp-ui/src/nfvo-components/icon/Icon.jsx b/openecomp-ui/src/nfvo-components/icon/Icon.jsx
new file mode 100644
index 0000000000..125577664b
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/icon/Icon.jsx
@@ -0,0 +1,45 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, { Component, PropTypes } from 'react';
+
+
+export default class Icon extends Component {
+
+ static propTypes = {
+ image: PropTypes.string.isRequired,
+ onClick: PropTypes.func,
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
+ className: PropTypes.string,
+ iconClassName: PropTypes.string
+ };
+
+ static defaultProps = {
+ label: '',
+ className: '',
+ iconClassName: ''
+ };
+
+ render() {
+ let {image, onClick, label, className, iconClassName, ...other} = this.props;
+ let classes = `icon-component ${className} ${onClick ? 'clickable' : ''}`;
+ return (
+ <div {...other} onClick={onClick} className={classes}>
+ <span className={`icon ${image} ${iconClassName}`}></span>
+ <span className='icon-label'>{label}</span>
+ </div>
+ );
+ }
+}
diff --git a/openecomp-ui/src/nfvo-components/icon/SVGIcon.jsx b/openecomp-ui/src/nfvo-components/icon/SVGIcon.jsx
new file mode 100644
index 0000000000..dd165fb52c
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/icon/SVGIcon.jsx
@@ -0,0 +1,54 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {PropTypes} from 'react';
+import Configuration from 'sdc-app/config/Configuration.js';
+
+export default class SVGIcon extends React.Component {
+
+ static propTypes = {
+ name: PropTypes.string.isRequired,
+ onClick: PropTypes.func,
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
+ labelPosition: PropTypes.string,
+ className: PropTypes.string,
+ iconClassName: PropTypes.string,
+ labelClassName: PropTypes.string
+ };
+
+ static defaultProps = {
+ name: '',
+ label: '',
+ className: '',
+ iconClassName: '',
+ labelClassName: '',
+ labelPosition: 'bottom'
+ };
+
+ render() {
+ let {name, onClick, label, className, iconClassName, labelClassName, labelPosition, ...other} = this.props;
+ let classes = `svg-icon-wrapper ${className} ${onClick ? 'clickable' : ''} ${labelPosition}`;
+
+ return (
+ <div {...other} onClick={onClick} className={classes}>
+ <svg className={`svg-icon ${name} ${iconClassName}`} >
+ <use href={Configuration.get('appContextPath') + '/resources/images/svg/' + this.props.name + '.svg#' + this.props.name + '_icon' }
+ xlinkHref={Configuration.get('appContextPath') + '/resources/images/svg/' + this.props.name + '.svg#' + this.props.name + '_icon' } />
+ </svg>
+ {label && <span className={`svg-icon-label ${labelClassName}`}>{label}</span>}
+ </div>
+ );
+ }
+}
diff --git a/openecomp-ui/src/nfvo-components/icon/SVGIcon.stories.js b/openecomp-ui/src/nfvo-components/icon/SVGIcon.stories.js
new file mode 100644
index 0000000000..6675670cea
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/icon/SVGIcon.stories.js
@@ -0,0 +1,50 @@
+import React from 'react';
+import {storiesOf, action} from '@kadira/storybook';
+import {select, text, withKnobs} from '@kadira/storybook-addon-knobs';
+import SVGIcon from './SVGIcon.jsx';
+
+const stories = storiesOf('SVGIcon', module);
+
+const iconNames = ['locked',
+ 'pencil',
+ 'plus-circle',
+ 'plus',
+ 'search',
+ 'sliders',
+ 'trash-o',
+ 'unlocked',
+ 'vendor',
+ 'version-controller-lock-closed',
+ 'version-controller-lock-open',
+ 'version-controller-revert',
+ 'version-controller-save',
+ 'version-controller-submit',
+ 'vlm',
+ 'vsp' ];
+
+function colorChanger() {
+ return {fill: text('Color', '')};
+}
+
+function iconName() {
+ return select('Icon name' , iconNames, iconNames[0]);
+}
+
+stories.addDecorator(withKnobs);
+
+stories
+ .add('icon', () => {
+ return (
+ <SVGIcon name={iconName()} style={colorChanger()}/>
+ );
+ })
+ .add('icon with label', () => {
+ return (
+ <SVGIcon name={iconName()} label={iconName()} style={colorChanger()}/>
+ );
+ })
+ .add('locked clickable', () => {
+ return (
+ <SVGIcon name={iconName()} onClick={action('clicked')} style={colorChanger()}/>
+ );
+ }); \ No newline at end of file
diff --git a/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx b/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx
index 3ac3fcad28..e2ee40fcd2 100644
--- a/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx
+++ b/openecomp-ui/src/nfvo-components/input/ExpandableInput.jsx
@@ -1,77 +1,115 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import FontAwesome from 'react-fontawesome';
-import classnames from 'classnames';
-import Input from 'react-bootstrap/lib/Input';
+import ReactDOM from 'react-dom';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import Input from 'nfvo-components/input/validation/InputWrapper.jsx';
+const ExpandableInputClosed = ({iconType, onClick}) => (
+ <SVGIcon className='expandable-input-wrapper closed' name={iconType} onClick={onClick} />
+);
-class ExpandableInput extends React.Component {
- constructor(props){
- super(props);
- this.state = {showInput: false, value: ''};
- this.toggleInput = this.toggleInput.bind(this);
- this.handleFocus = this.handleFocus.bind(this);
- this.handleInput = this.handleInput.bind(this);
- this.handleClose = this.handleClose.bind(this);
+class ExpandableInputOpened extends React.Component {
+ componentDidMount(){
+ this.rawDomNode = ReactDOM.findDOMNode(this.searchInputNode.inputWrapper);
+ this.rawDomNode.focus();
}
- toggleInput(){
- if (!this.state.showInput){
- this.searchInputNode.refs.input.focus();
- } else {
- this.setState({showInput: false});
+ componentWillReceiveProps(newProps){
+ if (!newProps.value){
+ if (!(document.activeElement === this.rawDomNode)){
+ this.props.handleBlur();
+ }
}
}
- handleInput(e){
- let {onChange} = this.props;
+ handleClose(){
+ this.props.onChange('');
+ this.rawDomNode.focus();
+ }
- this.setState({value: e.target.value});
- onChange(e);
+ handleKeyDown(e){
+ if (e.key === 'Escape'){
+ e.preventDefault();
+ if (this.props.value) {
+ this.handleClose();
+ } else {
+ this.rawDomNode.blur();
+ }
+ };
}
- handleClose(){
- this.handleInput({target: {value: ''}});
- this.searchInputNode.refs.input.focus();
+ render() {
+ let {iconType, value, onChange, handleBlur} = this.props;
+ return (
+ <div className='expandable-input-wrapper opened' key='expandable'>
+ <Input
+ type='text'
+ value={value}
+ ref={(input) => this.searchInputNode = input}
+ className='expandable-active'
+ groupClassName='expandable-input-control'
+ onChange={e => onChange(e)}
+ onKeyDown={e => this.handleKeyDown(e)}
+ onBlur={handleBlur}/>
+ {value && <SVGIcon onClick={() => this.handleClose()} name='close' />}
+ {!value && <SVGIcon name={iconType} onClick={handleBlur}/>}
+ </div>
+ );
}
+}
+
+class ExpandableInput extends React.Component {
- handleFocus(){
- if (!this.state.showInput){
- this.setState({showInput: true});
+ static propTypes = {
+ iconType: React.PropTypes.string,
+ onChange: React.PropTypes.func,
+ value: React.PropTypes.string
+ };
+
+ state = {showInput: false};
+
+ closeInput(){
+ if (!this.props.value) {
+ this.setState({showInput: false});
}
}
getValue(){
- return this.state.value;
+ return this.props.value;
}
render(){
- let {iconType} = this.props;
-
- let inputClasses = classnames({
- 'expandable-active': this.state.showInput,
- 'expandable-not-active': !this.state.showInput
- });
-
- let iconClasses = classnames(
- 'expandable-icon',
- {'expandable-icon-active': this.state.showInput}
- );
-
+ let {iconType, value, onChange = false} = this.props;
return (
- <div className='expandable-input-wrapper'>
- <Input
- type='text'
- value={this.state.value}
- ref={(input) => this.searchInputNode = input}
- className={inputClasses}
- groupClassName='expandable-input-control'
- onChange={e => this.handleInput(e)}
- onFocus={this.handleFocus}/>
- {this.state.showInput && this.state.value && <FontAwesome onClick={this.handleClose} name='close' className='expandable-close-button'/>}
- {!this.state.value && <FontAwesome onClick={this.toggleInput} name={iconType} className={iconClasses}/>}
+ <div className='expandable-input-top'>
+ {this.state.showInput &&
+ <ExpandableInputOpened
+ key='open'
+ iconType={iconType}
+ onChange={onChange}
+ value={value}
+ handleKeyDown={(e) => this.handleKeyDown(e)}
+ handleBlur={() => this.closeInput()}/>
+ }
+ {!this.state.showInput && <ExpandableInputClosed key='closed' iconType={iconType} onClick={() => this.setState({showInput: true})} />}
</div>
- );
+ );
}
}
+
export default ExpandableInput;
diff --git a/openecomp-ui/src/nfvo-components/input/SelectInput.jsx b/openecomp-ui/src/nfvo-components/input/SelectInput.jsx
index 1036ac41c3..03c727379e 100644
--- a/openecomp-ui/src/nfvo-components/input/SelectInput.jsx
+++ b/openecomp-ui/src/nfvo-components/input/SelectInput.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
/**
* The HTML structure here is aligned with bootstrap HTML structure for form elements.
* In this way we have proper styling and it is aligned with other form elements on screen.
@@ -20,8 +35,9 @@ class SelectInput extends Component {
render() {
let {label, value, ...other} = this.props;
+ const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
return (
- <div className='validation-input-wrapper dropdown-multi-select'>
+ <div {...dataTestId} className='validation-input-wrapper dropdown-multi-select'>
<div className='form-group'>
{label && <label className='control-label'>{label}</label>}
<Select ref='_myInput' onChange={value => this.onSelectChanged(value)} {...other} value={value} />
diff --git a/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx b/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx
index 873d3ded65..7bbafa3696 100644
--- a/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx
+++ b/openecomp-ui/src/nfvo-components/input/ToggleInput.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
export default
diff --git a/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx b/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx
index 171bead9bb..c60d6f777e 100644
--- a/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx
+++ b/openecomp-ui/src/nfvo-components/input/dualListbox/DualListboxView.jsx
@@ -1,6 +1,21 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import FontAwesome from 'react-fontawesome';
-import Input from 'react-bootstrap/lib/Input.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import Input from 'nfvo-components/input/validation/InputWrapper.jsx';
class DualListboxView extends React.Component {
@@ -30,37 +45,32 @@ class DualListboxView extends React.Component {
state = {
availableListFilter: '',
- selectedValuesListFilter: ''
- };
-
- static contextTypes = {
- isReadOnlyMode: React.PropTypes.bool
+ selectedValuesListFilter: '',
+ selectedValues: []
};
render() {
- let {availableList, selectedValuesList, filterTitle} = this.props;
+ let {availableList, selectedValuesList, filterTitle, isReadOnlyMode} = this.props;
let {availableListFilter, selectedValuesListFilter} = this.state;
- let isReadOnlyMode = this.context.isReadOnlyMode;
let unselectedList = availableList.filter(availableItem => !selectedValuesList.find(value => value === availableItem.id));
let selectedList = availableList.filter(availableItem => selectedValuesList.find(value => value === availableItem.id));
selectedList = selectedList.sort((a, b) => selectedValuesList.indexOf(a.id) - selectedValuesList.indexOf(b.id));
-
return (
<div className='dual-list-box'>
{this.renderListbox(filterTitle.left, unselectedList, {
value: availableListFilter,
ref: 'availableListFilter',
disabled: isReadOnlyMode,
- onChange: () => this.setState({availableListFilter: this.refs.availableListFilter.getValue()})
- }, {ref: 'availableValues', disabled: isReadOnlyMode})}
+ onChange: (value) => this.setState({availableListFilter: value})
+ }, {ref: 'availableValues', disabled: isReadOnlyMode, testId: 'available',})}
{this.renderOperationsBar(isReadOnlyMode)}
{this.renderListbox(filterTitle.right, selectedList, {
value: selectedValuesListFilter,
ref: 'selectedValuesListFilter',
disabled: isReadOnlyMode,
- onChange: () => this.setState({selectedValuesListFilter: this.refs.selectedValuesListFilter.getValue()})
- }, {ref: 'selectedValues', disabled: isReadOnlyMode})}
+ onChange: (value) => this.setState({selectedValuesListFilter: value})
+ }, {ref: 'selectedValues', disabled: isReadOnlyMode, testId: 'selected'})}
</div>
);
}
@@ -69,21 +79,25 @@ class DualListboxView extends React.Component {
let regExFilter = new RegExp(escape(filterProps.value), 'i');
let matchedItems = list.filter(item => item.name.match(regExFilter));
let unMatchedItems = list.filter(item => !item.name.match(regExFilter));
-
-
return (
<div className='dual-search-multi-select-section'>
<p>{filterTitle}</p>
<div className='dual-text-box-search search-wrapper'>
- <Input name='search-input-control' type='text' groupClassName='search-input-control' {...filterProps}/>
- <FontAwesome name='search' className='search-icon'/>
+ <Input data-test-id={`${props.testId}-search-input`}
+ name='search-input-control' type='text'
+ groupClassName='search-input-control'
+ {...filterProps}/>
+ <SVGIcon name='search' className='search-icon'/>
</div>
<Input
multiple
+ onChange={(event) => this.onSelectItems(event.target.selectedOptions)}
groupClassName='dual-list-box-multi-select'
type='select'
name='dual-list-box-multi-select'
- {...props}>
+ data-test-id={`${props.testId}-select-input`}
+ disabled={props.disabled}
+ ref={props.ref}>
{matchedItems.map(item => this.renderOption(item.id, item.name))}
{matchedItems.length && unMatchedItems.length && <option style={{pointerEvents: 'none'}}>--------------------</option>}
{unMatchedItems.map(item => this.renderOption(item.id, item.name))}
@@ -92,6 +106,11 @@ class DualListboxView extends React.Component {
);
}
+ onSelectItems(selectedOptions) {
+ let selectedValues = Object.keys(selectedOptions).map((k) => selectedOptions[k].value);
+ this.setState({selectedValues});
+ }
+
renderOption(value, name) {
return (<option className='dual-list-box-multi-select-text' key={value} value={value}>{name}</option>);
}
@@ -107,17 +126,19 @@ class DualListboxView extends React.Component {
);
}
- renderOperationBarButton(onClick, fontAwesomeIconName){
- return (<div className='dual-list-option' onClick={onClick}><FontAwesome name={fontAwesomeIconName}/></div>);
+ renderOperationBarButton(onClick, iconName){
+ return (<div className='dual-list-option' data-test-id={`operation-icon-${iconName}`} onClick={onClick}><SVGIcon name={iconName}/></div>);
}
addToSelectedList() {
- this.props.onChange(this.props.selectedValuesList.concat(this.refs.availableValues.getValue()));
+ this.props.onChange(this.props.selectedValuesList.concat(this.state.selectedValues));
+ this.setState({selectedValues: []});
}
removeFromSelectedList() {
- const selectedValues = this.refs.selectedValues.getValue();
+ const selectedValues = this.state.selectedValues;
this.props.onChange(this.props.selectedValuesList.filter(value => !selectedValues.find(selectedValue => selectedValue === value)));
+ this.setState({selectedValues: []});
}
addAllToSelectedList() {
diff --git a/openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx b/openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx
index 5daaffea41..e8aadc4357 100644
--- a/openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx
+++ b/openecomp-ui/src/nfvo-components/input/inputOptions/InputOptions.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import classNames from 'classnames';
@@ -13,15 +28,21 @@ class InputOptions extends React.Component {
title: React.PropTypes.string
})),
isEnabledOther: React.PropTypes.bool,
- title: React.PropTypes.string,
+ label: React.PropTypes.string,
selectedValue: React.PropTypes.string,
- multiSelectedEnum: React.PropTypes.array,
+ multiSelectedEnum: React.PropTypes.oneOfType([
+ React.PropTypes.string,
+ React.PropTypes.array
+ ]),
selectedEnum: React.PropTypes.string,
otherValue: React.PropTypes.string,
onEnumChange: React.PropTypes.func,
onOtherChange: React.PropTypes.func,
+ onBlur: React.PropTypes.func,
isRequired: React.PropTypes.bool,
- isMultiSelect: React.PropTypes.bool
+ isMultiSelect: React.PropTypes.bool,
+ hasError: React.PropTypes.bool,
+ disabled: React.PropTypes.bool
};
@@ -41,7 +62,7 @@ class InputOptions extends React.Component {
render() {
let {label, isRequired, values, otherValue, onOtherChange, isMultiSelect, onBlur, multiSelectedEnum, selectedEnum, hasError, validations, children} = this.props;
-
+ const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
let currentMultiSelectedEnum = [];
let currentSelectedEnum = '';
let {otherInputDisabled} = this.state;
@@ -54,14 +75,18 @@ class InputOptions extends React.Component {
else if(selectedEnum){
currentSelectedEnum = selectedEnum;
}
+ if (!onBlur) {
+ onBlur = () => {};
+ }
let isReadOnlyMode = this.context.isReadOnlyMode;
return(
- <div className={classNames('form-group', {'required' : validations.required , 'has-error' : hasError})}>
+ <div className={classNames('form-group', {'required' : (validations && validations.required) || isRequired, 'has-error' : hasError})}>
{label && <label className='control-label'>{label}</label>}
{isMultiSelect && otherInputDisabled ?
<Select
+ {...dataTestId}
ref='_myInput'
value={currentMultiSelectedEnum}
className='options-input'
@@ -74,18 +99,18 @@ class InputOptions extends React.Component {
multi/> :
<div className={classNames('input-options',{'has-error' : hasError})}>
<select
+ {...dataTestId}
ref={'_myInput'}
label={label}
className='form-control input-options-select'
value={currentSelectedEnum}
- style={{'width' : otherInputDisabled ? '100%' : '95px'}}
+ style={{'width' : otherInputDisabled ? '100%' : '100px'}}
onBlur={() => onBlur()}
disabled={isReadOnlyMode || Boolean(this.props.disabled)}
onChange={ value => this.enumChanged(value)}
type='select'>
- {values && values.length && values.map(val => this.renderOptions(val))}
+ {children || (values && values.length && values.map((val, index) => this.renderOptions(val, index)))}
{onOtherChange && <option key='other' value={other.OTHER}>{i18n(other.OTHER)}</option>}
- {children}
</select>
{!otherInputDisabled && <div className='input-options-separator'/>}
@@ -104,9 +129,9 @@ class InputOptions extends React.Component {
);
}
- renderOptions(val){
- return(
- <option key={val.enum} value={val.enum}>{val.title}</option>
+ renderOptions(val, index){
+ return (
+ <option key={index} value={val.enum}>{val.title}</option>
);
}
@@ -154,9 +179,9 @@ class InputOptions extends React.Component {
enumChanged() {
let enumValue = this.refs._myInput.value;
- let {onEnumChange, isMultiSelect, onChange} = this.props;
+ let {onEnumChange, onOtherChange, isMultiSelect, onChange} = this.props;
this.setState({
- otherInputDisabled: enumValue !== other.OTHER
+ otherInputDisabled: !Boolean(onOtherChange) || enumValue !== other.OTHER
});
let value = isMultiSelect ? [enumValue] : enumValue;
@@ -169,7 +194,7 @@ class InputOptions extends React.Component {
}
multiSelectEnumChanged(enumValue) {
- let {onEnumChange} = this.props;
+ let {onEnumChange, onOtherChange} = this.props;
let selectedValues = enumValue.map(enumVal => {
return enumVal.value;
});
@@ -182,7 +207,7 @@ class InputOptions extends React.Component {
}
this.setState({
- otherInputDisabled: !selectedValues.includes(i18n(other.OTHER))
+ otherInputDisabled: !Boolean(onOtherChange) || !selectedValues.includes(i18n(other.OTHER))
});
onEnumChange(selectedValues);
}
diff --git a/openecomp-ui/src/nfvo-components/input/validation/Form.jsx b/openecomp-ui/src/nfvo-components/input/validation/Form.jsx
new file mode 100644
index 0000000000..47922f86a0
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/input/validation/Form.jsx
@@ -0,0 +1,114 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import React from 'react';
+import ValidationButtons from './ValidationButtons.jsx';
+
+class Form extends React.Component {
+
+ static defaultProps = {
+ hasButtons : true,
+ onSubmit : null,
+ onReset : null,
+ labledButtons: true,
+ onValidChange : null,
+ isValid: true
+ };
+
+ static propTypes = {
+ isValid : React.PropTypes.bool,
+ formReady : React.PropTypes.bool,
+ isReadOnlyMode : React.PropTypes.bool,
+ hasButtons : React.PropTypes.bool,
+ onSubmit : React.PropTypes.func,
+ onReset : React.PropTypes.func,
+ labledButtons: React.PropTypes.bool,
+ onValidChange : React.PropTypes.func,
+ onValidityChanged: React.PropTypes.func,
+ onValidateForm: React.PropTypes.func
+ };
+
+ constructor(props) {
+ super(props);
+ }
+
+
+ render() {
+ // eslint-disable-next-line no-unused-vars
+ let {isValid, formReady, onValidateForm, isReadOnlyMode, hasButtons, onSubmit, labledButtons, onValidChange, onValidityChanged, onDataChanged, children, ...formProps} = this.props;
+ return (
+ <form {...formProps} ref={(form) => this.form = form} onSubmit={event => this.handleFormValidation(event)}>
+ <div className='validation-form-content'>
+ <fieldset disabled={isReadOnlyMode}>
+ {children}
+ </fieldset>
+ </div>
+ {hasButtons && <ValidationButtons labledButtons={labledButtons} ref={(buttons) => this.buttons = buttons} isReadOnlyMode={isReadOnlyMode}/>}
+ </form>
+ );
+ }
+
+ handleFormValidation(event) {
+ event.preventDefault();
+ if (this.props.onValidateForm && !this.props.formReady){
+ return this.props.onValidateForm();
+ } else {
+ return this.handleFormSubmit(event);
+ }
+ }
+ handleFormSubmit(event) {
+ if (event) {
+ event.preventDefault();
+ }
+ if(this.props.onSubmit) {
+ return this.props.onSubmit(event);
+ }
+ }
+
+ componentDidMount() {
+ if (this.props.hasButtons) {
+ this.buttons.setState({isValid: this.props.isValid});
+ }
+ }
+
+
+
+ componentDidUpdate(prevProps) {
+ // only handling this programatically if the validation of the form is done outside of the view
+ // (example with a form that is dependent on the state of other forms)
+ if (prevProps.isValid !== this.props.isValid) {
+ if (this.props.hasButtons) {
+ this.buttons.setState({isValid: this.props.isValid});
+ }
+ // callback in case form is part of bigger picture in view
+ if (this.props.onValidChange) {
+ this.props.onValidChange(this.props.isValid);
+ }
+
+ // TODO - maybe this has to be part of componentWillUpdate
+ if(this.props.onValidityChanged) {
+ this.props.onValidityChanged(this.props.isValid);
+ }
+ }
+ if (this.props.formReady) { // if form validation succeeded -> continue with submit
+ this.handleFormSubmit();
+ }
+ }
+
+}
+
+
+export default Form;
diff --git a/openecomp-ui/src/nfvo-components/input/validation/Input.jsx b/openecomp-ui/src/nfvo-components/input/validation/Input.jsx
new file mode 100644
index 0000000000..59c35d7993
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/input/validation/Input.jsx
@@ -0,0 +1,180 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import ReactDOM from 'react-dom';
+import classNames from 'classnames';
+import Checkbox from 'react-bootstrap/lib/Checkbox.js';
+import Radio from 'react-bootstrap/lib/Radio.js';
+import FormGroup from 'react-bootstrap/lib/FormGroup.js';
+import FormControl from 'react-bootstrap/lib/FormControl.js';
+import Overlay from 'react-bootstrap/lib/Overlay.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+
+class Input extends React.Component {
+
+ state = {
+ value: this.props.value,
+ checked: this.props.checked,
+ selectedValues: []
+ }
+
+ render() {
+ const {label, isReadOnlyMode, value, onBlur, onKeyDown, type, disabled, checked, name} = this.props;
+ // eslint-disable-next-line no-unused-vars
+ const {groupClassName, isValid = true, errorText, isRequired, ...inputProps} = this.props;
+ let wrapperClassName = (type !== 'radio') ? 'validation-input-wrapper' : 'form-group';
+ if (disabled) {
+ wrapperClassName += ' disabled';
+ }
+ return(
+ <div className={wrapperClassName}>
+ <FormGroup className={classNames('form-group', [groupClassName], {'required' : isRequired , 'has-error' : !isValid})} >
+ {(label && (type !== 'checkbox' && type !== 'radio')) && <label className='control-label'>{label}</label>}
+ {(type === 'text' || type === 'number') &&
+ <FormControl
+ bsClass={'form-control input-options-other'}
+ onChange={(e) => this.onChange(e)}
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ onBlur={onBlur}
+ onKeyDown={onKeyDown}
+ value={value || ''}
+ inputRef={(input) => this.input = input}
+ type={type}
+ data-test-id={this.props['data-test-id']}/>}
+
+ {type === 'textarea' &&
+ <FormControl
+ className='form-control input-options-other'
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ value={value || ''}
+ onBlur={onBlur}
+ onKeyDown={onKeyDown}
+ componentClass={type}
+ onChange={(e) => this.onChange(e)}
+ inputRef={(input) => this.input = input}
+ data-test-id={this.props['data-test-id']}/>}
+
+ {type === 'checkbox' &&
+ <Checkbox
+ className={classNames({'required' : isRequired , 'has-error' : !isValid})}
+ onChange={(e)=>this.onChangeCheckBox(e)}
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ checked={value}
+ data-test-id={this.props['data-test-id']}>{label}</Checkbox>}
+
+ {type === 'radio' &&
+ <Radio name={name}
+ checked={checked}
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ value={value}
+ onChange={(e)=>this.onChangeRadio(e)}
+ data-test-id={this.props['data-test-id']}>{label}</Radio>}
+ {type === 'select' &&
+ <FormControl onClick={ (e) => this.optionSelect(e) }
+ componentClass={type}
+ inputRef={(input) => this.input = input}
+ name={name} {...inputProps}
+ data-test-id={this.props['data-test-id']}/>}
+ </FormGroup>
+ { this.renderErrorOverlay() }
+ </div>
+ );
+ }
+
+ getValue() {
+ return this.props.type !== 'select' ? this.state.value : this.state.selectedValues;
+ }
+
+ getChecked() {
+ return this.state.checked;
+ }
+
+ optionSelect(e) {
+ let selectedValues = [];
+ if (e.target.value) {
+ selectedValues.push(e.target.value);
+ }
+ this.setState({
+ selectedValues
+ });
+ }
+
+ onChange(e) {
+ const {onChange, type} = this.props;
+ let value = e.target.value;
+ if (type === 'number') {
+ value = Number(value);
+ }
+ this.setState({
+ value
+ });
+ onChange(value);
+ }
+
+ onChangeCheckBox(e) {
+ let {onChange} = this.props;
+ this.setState({
+ checked: e.target.checked
+ });
+ onChange(e.target.checked);
+ }
+
+ onChangeRadio(e) {
+ let {onChange} = this.props;
+ this.setState({
+ checked: e.target.checked
+ });
+ onChange(this.state.value);
+ }
+
+ focus() {
+ ReactDOM.findDOMNode(this.input).focus();
+ }
+
+ renderErrorOverlay() {
+ let position = 'right';
+ const {errorText = '', isValid = true, type, overlayPos} = this.props;
+
+ if (overlayPos) {
+ position = overlayPos;
+ }
+ else if (type === 'text'
+ || type === 'email'
+ || type === 'number'
+ || type === 'password') {
+ position = 'bottom';
+ }
+
+ return (
+ <Overlay
+ show={!isValid}
+ placement={position}
+ target={() => {
+ let target = ReactDOM.findDOMNode(this.input);
+ return target.offsetParent ? target : undefined;
+ }}
+ container={this}>
+ <Tooltip
+ id={`error-${errorText.replace(' ', '-')}`}
+ className='validation-error-message'>
+ {errorText}
+ </Tooltip>
+ </Overlay>
+ );
+ }
+
+}
+export default Input;
diff --git a/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx b/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx
new file mode 100644
index 0000000000..6e54254eb0
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx
@@ -0,0 +1,279 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import ReactDOM from 'react-dom';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import classNames from 'classnames';
+import Select from 'nfvo-components/input/SelectInput.jsx';
+import Overlay from 'react-bootstrap/lib/Overlay.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+
+export const other = {OTHER: 'Other'};
+
+class InputOptions extends React.Component {
+
+ static propTypes = {
+ values: React.PropTypes.arrayOf(React.PropTypes.shape({
+ enum: React.PropTypes.string,
+ title: React.PropTypes.string
+ })),
+ isEnabledOther: React.PropTypes.bool,
+ label: React.PropTypes.string,
+ selectedValue: React.PropTypes.string,
+ multiSelectedEnum: React.PropTypes.oneOfType([
+ React.PropTypes.string,
+ React.PropTypes.array
+ ]),
+ selectedEnum: React.PropTypes.string,
+ otherValue: React.PropTypes.string,
+ overlayPos: React.PropTypes.string,
+ onEnumChange: React.PropTypes.func,
+ onOtherChange: React.PropTypes.func,
+ onBlur: React.PropTypes.func,
+ isRequired: React.PropTypes.bool,
+ isMultiSelect: React.PropTypes.bool,
+ isValid: React.PropTypes.bool,
+ disabled: React.PropTypes.bool
+ };
+
+ state = {
+ otherInputDisabled: !this.props.otherValue
+ };
+
+ oldProps = {
+ selectedEnum: '',
+ otherValue: '',
+ multiSelectedEnum: []
+ };
+
+ render() {
+ let {label, isRequired, values, otherValue, onOtherChange, isMultiSelect, onBlur, multiSelectedEnum, selectedEnum, isValid, children, isReadOnlyMode} = this.props;
+ const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
+ let currentMultiSelectedEnum = [];
+ let currentSelectedEnum = '';
+ let {otherInputDisabled} = this.state;
+ if (isMultiSelect) {
+ currentMultiSelectedEnum = multiSelectedEnum;
+ if(!otherInputDisabled) {
+ currentSelectedEnum = multiSelectedEnum ? multiSelectedEnum.toString() : undefined;
+ }
+ }
+ else if(selectedEnum){
+ currentSelectedEnum = selectedEnum;
+ }
+ if (!onBlur) {
+ onBlur = () => {};
+ }
+
+ return(
+ <div className='validation-input-wrapper' >
+ <div className={classNames('form-group', {'required' : isRequired, 'has-error' : !isValid})} >
+ {label && <label className='control-label'>{label}</label>}
+ {isMultiSelect && otherInputDisabled ?
+ <Select
+ {...dataTestId}
+ ref={(input) => this.input = input}
+ value={currentMultiSelectedEnum}
+ className='options-input'
+ clearable={false}
+ required={isRequired}
+ disabled={isReadOnlyMode || Boolean(this.props.disabled)}
+ onBlur={() => onBlur()}
+ onMultiSelectChanged={value => this.multiSelectEnumChanged(value)}
+ options={this.renderMultiSelectOptions(values)}
+ multi/> :
+ <div className={classNames('input-options',{'has-error' : !isValid})} >
+ <select
+ {...dataTestId}
+ ref={(input) => this.input = input}
+ label={label}
+ className='form-control input-options-select'
+ value={currentSelectedEnum}
+ style={{'width' : otherInputDisabled ? '100%' : '100px'}}
+ onBlur={() => onBlur()}
+ disabled={isReadOnlyMode || Boolean(this.props.disabled)}
+ onChange={ value => this.enumChanged(value)}
+ type='select'>
+ {children || (values && values.length && values.map((val, index) => this.renderOptions(val, index)))}
+ {onOtherChange && <option key='other' value={other.OTHER}>{i18n(other.OTHER)}</option>}
+ </select>
+
+ {!otherInputDisabled && <div className='input-options-separator'/>}
+ <input
+ className='form-control input-options-other'
+ placeholder={i18n('other')}
+ ref={(otherValue) => this.otherValue = otherValue}
+ style={{'display' : otherInputDisabled ? 'none' : 'block'}}
+ disabled={isReadOnlyMode || Boolean(this.props.disabled)}
+ value={otherValue || ''}
+ onBlur={() => onBlur()}
+ onChange={() => this.changedOtherInput()}/>
+ </div>
+ }
+ </div>
+ { this.renderErrorOverlay() }
+ </div>
+ );
+ }
+
+ renderOptions(val, index){
+ return (
+ <option key={index} value={val.enum}>{val.title}</option>
+ );
+ }
+
+
+ renderMultiSelectOptions(values) {
+ let {onOtherChange} = this.props;
+ let optionsList = [];
+ if (onOtherChange) {
+ optionsList = values.map(option => {
+ return {
+ label: option.title,
+ value: option.enum,
+ };
+ }).concat([{
+ label: i18n(other.OTHER),
+ value: i18n(other.OTHER),
+ }]);
+ }
+ else {
+ optionsList = values.map(option => {
+ return {
+ label: option.title,
+ value: option.enum,
+ };
+ });
+ }
+ if (optionsList.length > 0 && optionsList[0].value === '') {
+ optionsList.shift();
+ }
+ return optionsList;
+ }
+
+ renderErrorOverlay() {
+ let position = 'right';
+ const {errorText = '', isValid = true, type, overlayPos} = this.props;
+
+ if (overlayPos) {
+ position = overlayPos;
+ }
+ else if (type === 'text'
+ || type === 'email'
+ || type === 'number'
+ || type === 'password') {
+ position = 'bottom';
+ }
+
+ return (
+ <Overlay
+ show={!isValid}
+ placement={position}
+ target={() => {
+ let {otherInputDisabled} = this.state;
+ let target = otherInputDisabled ? ReactDOM.findDOMNode(this.input) : ReactDOM.findDOMNode(this.otherValue);
+ return target.offsetParent ? target : undefined;
+ }}
+ container={this}>
+ <Tooltip
+ id={`error-${errorText.replace(' ', '-')}`}
+ className='validation-error-message'>
+ {errorText}
+ </Tooltip>
+ </Overlay>
+ );
+ }
+
+ getValue() {
+ let res = '';
+ let {isMultiSelect} = this.props;
+ let {otherInputDisabled} = this.state;
+
+ if (otherInputDisabled) {
+ res = isMultiSelect ? this.input.getValue() : this.input.value;
+ } else {
+ res = this.otherValue.value;
+ }
+ return res;
+ }
+
+ enumChanged() {
+ let enumValue = this.input.value;
+ let {onEnumChange, onOtherChange, isMultiSelect, onChange} = this.props;
+ this.setState({
+ otherInputDisabled: !Boolean(onOtherChange) || enumValue !== other.OTHER
+ });
+
+ let value = isMultiSelect ? [enumValue] : enumValue;
+ if (onEnumChange) {
+ onEnumChange(value);
+ }
+ if (onChange) {
+ onChange(value);
+ }
+ }
+
+ multiSelectEnumChanged(enumValue) {
+ let {onEnumChange, onOtherChange} = this.props;
+ let selectedValues = enumValue.map(enumVal => {
+ return enumVal.value;
+ });
+
+ if (this.state.otherInputDisabled === false) {
+ selectedValues.shift();
+ }
+ else if (selectedValues.includes(i18n(other.OTHER))) {
+ selectedValues = [i18n(other.OTHER)];
+ }
+
+ this.setState({
+ otherInputDisabled: !Boolean(onOtherChange) || !selectedValues.includes(i18n(other.OTHER))
+ });
+ onEnumChange(selectedValues);
+ }
+
+ changedOtherInput() {
+ let {onOtherChange} = this.props;
+ onOtherChange(this.otherValue.value);
+ }
+
+ componentDidUpdate() {
+ let {otherValue, selectedEnum, onInputChange, multiSelectedEnum} = this.props;
+ if (this.oldProps.otherValue !== otherValue
+ || this.oldProps.selectedEnum !== selectedEnum
+ || this.oldProps.multiSelectedEnum !== multiSelectedEnum) {
+ this.oldProps = {
+ otherValue,
+ selectedEnum,
+ multiSelectedEnum
+ };
+ onInputChange();
+ }
+ }
+
+ static getTitleByName(values, name) {
+ for (let key of Object.keys(values)) {
+ let option = values[key].find(option => option.enum === name);
+ if (option) {
+ return option.title;
+ }
+ }
+ return name;
+ }
+
+}
+
+export default InputOptions;
diff --git a/openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx b/openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx
new file mode 100644
index 0000000000..5ca716cc20
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/input/validation/InputWrapper.jsx
@@ -0,0 +1,134 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import ReactDOM from 'react-dom';
+import classNames from 'classnames';
+import Checkbox from 'react-bootstrap/lib/Checkbox.js';
+import Radio from 'react-bootstrap/lib/Radio.js';
+import FormGroup from 'react-bootstrap/lib/FormGroup.js';
+import FormControl from 'react-bootstrap/lib/FormControl.js';
+
+class InputWrapper extends React.Component {
+
+ state = {
+ value: this.props.value,
+ checked: this.props.checked,
+ selectedValues: []
+ }
+
+ render() {
+ const {label, hasError, validations = {}, isReadOnlyMode, value, onBlur, onKeyDown, type, disabled, checked, name} = this.props;
+ const {groupClassName, ...inputProps} = this.props;
+ return(
+ <FormGroup className={classNames('form-group', [groupClassName], {'required' : validations.required , 'has-error' : hasError})} >
+ {(label && (type !== 'checkbox' && type !== 'radio')) && <label className='control-label'>{label}</label>}
+ {(type === 'text' || type === 'number') &&
+ <FormControl
+ bsClass={'form-control input-options-other'}
+ onChange={(e) => this.onChange(e)}
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ onBlur={onBlur}
+ onKeyDown={onKeyDown}
+ value={value || ''}
+ ref={(input) => this.inputWrapper = input}
+ type={type}
+ data-test-id={this.props['data-test-id']}/>}
+
+ {type === 'textarea' &&
+ <FormControl
+ className='form-control input-options-other'
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ value={value || ''}
+ onBlur={onBlur}
+ onKeyDown={onKeyDown}
+ componentClass={type}
+ onChange={(e) => this.onChange(e)}
+ data-test-id={this.props['data-test-id']}/>}
+
+ {type === 'checkbox' &&
+ <Checkbox
+ className={classNames({'required' : validations.required , 'has-error' : hasError})}
+ onChange={(e)=>this.onChangeCheckBox(e)}
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ checked={value}
+ data-test-id={this.props['data-test-id']}>{label}</Checkbox>}
+
+ {type === 'radio' &&
+ <Radio name={name}
+ checked={checked}
+ disabled={isReadOnlyMode || Boolean(disabled)}
+ value={value}
+ onChange={(e)=>this.onChangeRadio(e)}
+ data-test-id={this.props['data-test-id']}>{label}</Radio>}
+ {type === 'select' &&
+ <FormControl onClick={ (e) => this.optionSelect(e) }
+ componentClass={type}
+ name={name} {...inputProps}
+ data-test-id={this.props['data-test-id']}/>}
+
+ </FormGroup>
+
+ );
+ }
+
+ getValue() {
+ return this.props.type !== 'select' ? this.state.value : this.state.selectedValues;
+ }
+
+ getChecked() {
+ return this.state.checked;
+ }
+
+ optionSelect(e) {
+ let selectedValues = [];
+ if (e.target.value) {
+ selectedValues.push(e.target.value);
+ }
+ this.setState({
+ selectedValues
+ });
+ }
+
+ onChange(e) {
+ let {onChange} = this.props;
+ this.setState({
+ value: e.target.value
+ });
+ onChange(e.target.value);
+ }
+
+ onChangeCheckBox(e) {
+ let {onChange} = this.props;
+ this.setState({
+ checked: e.target.checked
+ });
+ onChange(e.target.checked);
+ }
+
+ onChangeRadio(e) {
+ let {onChange} = this.props;
+ this.setState({
+ checked: e.target.checked
+ });
+ onChange(this.state.value);
+ }
+
+ focus() {
+ ReactDOM.findDOMNode(this.inputWrapper).focus();
+ }
+
+}
+export default InputWrapper;
diff --git a/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx b/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx
new file mode 100644
index 0000000000..95144b1468
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx
@@ -0,0 +1,79 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import ReactDOM from 'react-dom';
+import {default as BTabs} from 'react-bootstrap/lib/Tabs.js';
+import Overlay from 'react-bootstrap/lib/Overlay.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+export default
+class Tabs extends React.Component {
+
+ static propTypes = {
+ children: React.PropTypes.node
+ };
+
+ cloneTab(element) {
+ const {invalidTabs} = this.props;
+ return React.cloneElement(
+ element,
+ {
+ key: element.props.eventKey,
+ tabClassName: invalidTabs.indexOf(element.props.eventKey) > -1 ? 'invalid-tab' : 'valid-tab'
+ }
+ );
+ }
+
+ showTabsError() {
+ const {invalidTabs} = this.props;
+ const showError = ((invalidTabs.length === 1 && invalidTabs[0] !== this.props.activeKey) || (invalidTabs.length > 1));
+ return showError;
+ }
+
+ render() {
+ // eslint-disable-next-line no-unused-vars
+ let {invalidTabs, ...tabProps} = this.props;
+ return (
+ <div>
+ <BTabs {...tabProps} ref='tabsList' id='tabsList' >
+ {this.props.children.map(element => this.cloneTab(element))}
+ </BTabs>
+ <Overlay
+ animation={false}
+ show={this.showTabsError()}
+ placement='bottom'
+ containerPadding={50}
+ target={() => {
+ let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.active):nth-of-type(n)');
+ return target && target.offsetParent ? target : undefined;
+ }
+ }
+ container={() => {
+ let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.active):nth-of-type(n)');
+ return target && target.offsetParent ? target.offsetParent : this;
+ }}>
+ <Tooltip
+ id='error-some-tabs-contain-errors'
+ className='validation-error-message'>
+ {i18n('One or more tabs are invalid')}
+ </Tooltip>
+ </Overlay>
+ </div>
+ );
+ }
+}
diff --git a/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx b/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx
index a87c8d6f40..ebb1473c04 100644
--- a/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx
+++ b/openecomp-ui/src/nfvo-components/input/validation/ValidationButtons.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
/**
* Holds the buttons for save/reset for forms.
* Used by the ValidationForm that changes the state of the buttons according to its own state.
@@ -8,7 +23,7 @@
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import Button from 'react-bootstrap/lib/Button.js';
-import FontAwesome from 'react-fontawesome';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
class ValidationButtons extends React.Component {
@@ -22,8 +37,8 @@ class ValidationButtons extends React.Component {
};
render() {
- var submitBtn = this.props.labledButtons ? i18n('Save') : <FontAwesome className='check' name='check'/>;
- var closeBtn = this.props.labledButtons ? i18n('Cancel') : <FontAwesome className='close' name='close'/>;
+ var submitBtn = this.props.labledButtons ? i18n('Save') : <SVGIcon className='check' name='check'/>;
+ var closeBtn = this.props.labledButtons ? i18n('Cancel') : <SVGIcon className='close' name='close'/>;
return (
<div className='validation-buttons'>
{!this.props.isReadOnlyMode ?
diff --git a/openecomp-ui/src/nfvo-components/input/validation/ValidationForm.jsx b/openecomp-ui/src/nfvo-components/input/validation/ValidationForm.jsx
deleted file mode 100644
index 098ccf1fd4..0000000000
--- a/openecomp-ui/src/nfvo-components/input/validation/ValidationForm.jsx
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * ValidationForm should be used in order to have a form that handles it's internal validation state.
- * All ValidationInputs inside the form are checked for validity and the styling and submit buttons
- * are updated accordingly.
- *
- * The properties that ahould be given to the form:
- * labledButtons - whether or not use icons only as the form default buttons or use buttons with labels
- * onSubmit - function for click on the submit button
- * onReset - function for click on the reset button
- */
-import React from 'react';
-import JSONSchema from 'nfvo-utils/json/JSONSchema.js';
-import JSONPointer from 'nfvo-utils/json/JSONPointer.js';
-import ValidationButtons from './ValidationButtons.jsx';
-
-class ValidationForm extends React.Component {
-
- static childContextTypes = {
- validationParent: React.PropTypes.any,
- isReadOnlyMode: React.PropTypes.bool,
- validationSchema: React.PropTypes.instanceOf(JSONSchema),
- validationData: React.PropTypes.object
- };
-
- static defaultProps = {
- hasButtons : true,
- onSubmit : null,
- onReset : null,
- labledButtons: true,
- onValidChange : null,
- isValid: true
- };
-
- static propTypes = {
- isValid : React.PropTypes.bool,
- isReadOnlyMode : React.PropTypes.bool,
- hasButtons : React.PropTypes.bool,
- onSubmit : React.PropTypes.func,
- onReset : React.PropTypes.func,
- labledButtons: React.PropTypes.bool,
- onValidChange : React.PropTypes.func,
- onValidityChanged: React.PropTypes.func,
- schema: React.PropTypes.object,
- data: React.PropTypes.object
- };
-
- state = {
- isValid: this.props.isValid
- };
-
- constructor(props) {
- super(props);
- this.validationComponents = [];
- }
-
- componentWillMount() {
- let {schema, data} = this.props;
- if (schema) {
- this.processSchema(schema, data);
- }
- }
-
- componentWillReceiveProps(nextProps) {
- let {schema, data} = this.props;
- let {schema: nextSchema, data: nextData} = nextProps;
-
- if (schema !== nextSchema || data !== nextData) {
- if (!schema || !nextSchema) {
- throw new Error('ValidationForm: dynamically adding/removing schema is not supported');
- }
-
- if (schema !== nextSchema) {
- this.processSchema(nextSchema, nextData);
- } else {
- this.setState({data: nextData});
- }
- }
- }
-
- processSchema(rawSchema, rawData) {
- let schema = new JSONSchema();
- schema.setSchema(rawSchema);
- let data = schema.processData(rawData);
- this.setState({
- schema,
- data
- });
- }
-
- render() {
- // eslint-disable-next-line no-unused-vars
- let {isValid, isReadOnlyMode, hasButtons, onSubmit, labledButtons, onValidChange, onValidityChanged, schema, data, children, ...formProps} = this.props;
- return (
- <form {...formProps} onSubmit={event => this.handleFormSubmit(event)}>
- <div className='validation-form-content'>{children}</div>
- {hasButtons && <ValidationButtons labledButtons={labledButtons} ref='buttons' isReadOnlyMode={isReadOnlyMode}/>}
- </form>
- );
- }
-
- handleFormSubmit(event) {
- event.preventDefault();
- let isFormValid = true;
- this.validationComponents.forEach(validationComponent => {
- const isInputValid = validationComponent.validate().isValid;
- isFormValid = isInputValid && isFormValid;
- });
- if(isFormValid && this.props.onSubmit) {
- return this.props.onSubmit(event);
- } else if(!isFormValid) {
- this.setState({isValid: false});
- }
- }
-
- componentWillUpdate(nextProps, nextState) {
- if(this.state.isValid !== nextState.isValid && this.props.onValidityChanged) {
- this.props.onValidityChanged(nextState.isValid);
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- // only handling this programatically if the validation of the form is done outside of the view
- // (example with a form that is dependent on the state of other forms)
- if (prevProps.isValid !== this.props.isValid) {
- if (this.props.hasButtons) {
- this.refs.buttons.setState({isValid: this.state.isValid});
- }
- } else if(this.state.isValid !== prevState.isValid) {
- if (this.props.hasButtons) {
- this.refs.buttons.setState({isValid: this.state.isValid});
- }
- // callback in case form is part of bigger picture in view
- if (this.props.onValidChange) {
- this.props.onValidChange(this.state.isValid);
- }
- }
- }
-
- componentDidMount() {
- if (this.props.hasButtons) {
- this.refs.buttons.setState({isValid: this.state.isValid});
- }
- }
-
-
- getChildContext() {
- return {
- validationParent: this,
- isReadOnlyMode: this.props.isReadOnlyMode,
- validationSchema: this.state.schema,
- validationData: this.state.data
- };
- }
-
-
- /***
- * Used by ValidationInput in order to let the (parent) form know
- * the valid state. If there is a change in the state of the form,
- * the buttons will be updated.
- *
- * @param validationComponent
- * @param isValid
- */
- childValidStateChanged(validationComponent, isValid) {
- if (isValid !== this.state.isValid) {
- let oldState = this.state.isValid;
- let newState = isValid && this.validationComponents.filter(otherValidationComponent => validationComponent !== otherValidationComponent).every(otherValidationComponent => {
- return otherValidationComponent.isValid();
- });
-
- if (oldState !== newState) {
- this.setState({isValid: newState});
- }
- }
- }
-
- register(validationComponent) {
- if (this.state.schema) {
- // TODO: register
- } else {
- this.validationComponents.push(validationComponent);
- }
- }
-
- unregister(validationComponent) {
- this.childValidStateChanged(validationComponent, true);
- this.validationComponents = this.validationComponents.filter(otherValidationComponent => validationComponent !== otherValidationComponent);
- }
-
- onValueChanged(pointer, value, isValid, error) {
- this.props.onDataChanged({
- data: JSONPointer.setValue(this.props.data, pointer, value),
- isValid,
- error
- });
- }
-}
-
-
-export default ValidationForm;
diff --git a/openecomp-ui/src/nfvo-components/input/validation/ValidationInput.jsx b/openecomp-ui/src/nfvo-components/input/validation/ValidationInput.jsx
deleted file mode 100644
index 0f14307645..0000000000
--- a/openecomp-ui/src/nfvo-components/input/validation/ValidationInput.jsx
+++ /dev/null
@@ -1,509 +0,0 @@
-/**
- * Used for inputs on a validation form.
- * All properties will be passed on to the input element.
- *
- * The following properties can be set for OOB validations and callbacks:
- - required: Boolean: Should be set to true if the input must have a value
- - numeric: Boolean : Should be set to true id the input should be an integer
- - onChange : Function : Will be called to validate the value if the default validations are not sufficient, should return a boolean value
- indicating whether the value is valid
- - didUpdateCallback :Function: Will be called after the state has been updated and the component has rerendered. This can be used if
- there are dependencies between inputs in a form.
- *
- * The following properties of the state can be set to determine
- * the state of the input from outside components:
- - isValid : Boolean - whether the value is valid
- - value : value for the input field,
- - disabled : Boolean,
- - required : Boolean - whether the input value must be filled out.
- */
-import React from 'react';
-import ReactDOM from 'react-dom';
-import Validator from 'validator';
-import FormGroup from 'react-bootstrap/lib/FormGroup.js';
-import Input from 'react-bootstrap/lib/Input.js';
-import Overlay from 'react-bootstrap/lib/Overlay.js';
-import Tooltip from 'react-bootstrap/lib/Tooltip.js';
-import isEqual from 'lodash/isEqual.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import JSONSchema from 'nfvo-utils/json/JSONSchema.js';
-import JSONPointer from 'nfvo-utils/json/JSONPointer.js';
-
-
-import InputOptions from '../inputOptions/InputOptions.jsx';
-
-const globalValidationFunctions = {
- required: value => value !== '',
- maxLength: (value, length) => Validator.isLength(value, {max: length}),
- minLength: (value, length) => Validator.isLength(value, {min: length}),
- pattern: (value, pattern) => Validator.matches(value, pattern),
- numeric: value => {
- if (value === '') {
- // to allow empty value which is not zero
- return true;
- }
- return Validator.isNumeric(value);
- },
- maxValue: (value, maxValue) => value < maxValue,
- minValue: (value, minValue) => value >= minValue,
- alphanumeric: value => Validator.isAlphanumeric(value),
- alphanumericWithSpaces: value => Validator.isAlphanumeric(value.replace(/ /g, '')),
- validateName: value => Validator.isAlphanumeric(value.replace(/\s|\.|\_|\-/g, ''), 'en-US'),
- validateVendorName: value => Validator.isAlphanumeric(value.replace(/[\x7F-\xFF]|\s/g, ''), 'en-US'),
- freeEnglishText: value => Validator.isAlphanumeric(value.replace(/\s|\.|\_|\-|\,|\(|\)|\?/g, ''), 'en-US'),
- email: value => Validator.isEmail(value),
- ip: value => Validator.isIP(value),
- url: value => Validator.isURL(value)
-};
-
-const globalValidationMessagingFunctions = {
- required: () => i18n('Field is required'),
- maxLength: (value, maxLength) => i18n('Field value has exceeded it\'s limit, {maxLength}. current length: {length}', {
- length: value.length,
- maxLength
- }),
- minLength: (value, minLength) => i18n('Field value should contain at least {minLength} characters.', {minLength}),
- pattern: (value, pattern) => i18n('Field value should match the pattern: {pattern}.', {pattern}),
- numeric: () => i18n('Field value should contain numbers only.'),
- maxValue: (value, maxValue) => i18n('Field value should be less than: {maxValue}.', {maxValue}),
- minValue: (value, minValue) => i18n('Field value should be at least: {minValue}.', {minValue}),
- alphanumeric: () => i18n('Field value should contain letters or digits only.'),
- alphanumericWithSpaces: () => i18n('Field value should contain letters, digits or spaces only.'),
- validateName: ()=> i18n('Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'),
- validateVendorName: ()=> i18n('Field value should contain English letters digits and spaces only.'),
- freeEnglishText: ()=> i18n('Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'),
- email: () => i18n('Field value should be a valid email address.'),
- ip: () => i18n('Field value should be a valid ip address.'),
- url: () => i18n('Field value should be a valid url address.'),
- general: () => i18n('Field value is invalid.')
-};
-
-class ValidationInput extends React.Component {
-
- static contextTypes = {
- validationParent: React.PropTypes.any,
- isReadOnlyMode: React.PropTypes.bool,
- validationSchema: React.PropTypes.instanceOf(JSONSchema),
- validationData: React.PropTypes.object
- };
-
- static defaultProps = {
- onChange: null,
- disabled: null,
- didUpdateCallback: null,
- validations: {},
- value: ''
- };
-
- static propTypes = {
- type: React.PropTypes.string.isRequired,
- onChange: React.PropTypes.func,
- disabled: React.PropTypes.bool,
- didUpdateCallback: React.PropTypes.func,
- validations: React.PropTypes.object,
- isMultiSelect: React.PropTypes.bool,
- onOtherChange: React.PropTypes.func,
- pointer: React.PropTypes.string
- };
-
-
- state = {
- isValid: true,
- style: null,
- value: this.props.value,
- error: {},
- previousErrorMessage: '',
- wasInvalid: false,
- validations: this.props.validations,
- isMultiSelect: this.props.isMultiSelect
- };
-
- componentWillMount() {
- if (this.context.validationSchema) {
- let {validationSchema: schema, validationData: data} = this.context,
- {pointer} = this.props;
-
- if (!schema.exists(pointer)) {
- console.error(`Field doesn't exists in the schema ${pointer}`);
- }
-
- let value = JSONPointer.getValue(data, pointer);
- if (value === undefined) {
- value = schema.getDefault(pointer);
- if (value === undefined) {
- value = '';
- }
- }
- this.setState({value});
-
- let enums = schema.getEnum(pointer);
- if (enums) {
- let values = enums.map(value => ({enum: value, title: value, groupName: pointer})),
- isMultiSelect = schema.isArray(pointer);
-
- if (!isMultiSelect && this.props.type !== 'radiogroup') {
- values = [{enum: '', title: i18n('Select...')}, ...values];
- }
- if (isMultiSelect && Array.isArray(value) && value.length === 0) {
- value = '';
- }
-
- this.setState({
- isMultiSelect,
- values,
- onEnumChange: value => this.changedInputOptions(value),
- value
- });
- }
-
- this.setState({validations: this.extractValidationsFromSchema(schema, pointer, this.props)});
- }
- }
-
- extractValidationsFromSchema(schema, pointer, props) {
- /* props are here to get precedence over the scheme definitions */
- let validations = {};
-
- if (schema.isRequired(pointer)) {
- validations.required = true;
- }
-
- if (schema.isNumber(pointer)) {
- validations.numeric = true;
-
- const maxValue = props.validations.maxValue || schema.getMaxValue(pointer);
- if (maxValue !== undefined) {
- validations.maxValue = maxValue;
- }
-
- const minValue = props.validations.minValue || schema.getMinValue(pointer);
- if (minValue !== undefined) {
- validations.minValue = minValue;
- }
- }
-
-
- if (schema.isString(pointer)) {
-
- const pattern = schema.getPattern(pointer);
- if (pattern) {
- validations.pattern = pattern;
- }
-
- const maxLength = schema.getMaxLength(pointer);
- if (maxLength !== undefined) {
- validations.maxLength = maxLength;
- }
-
- const minLength = schema.getMinLength(pointer);
- if (minLength !== undefined) {
- validations.minLength = minLength;
- }
- }
-
- return validations;
- }
-
- componentWillReceiveProps({value: nextValue, validations: nextValidations, pointer: nextPointer}, nextContext) {
- const {validations, value} = this.props;
- const validationsChanged = !isEqual(validations, nextValidations);
- if (nextContext.validationSchema) {
- if (this.props.pointer !== nextPointer ||
- this.context.validationData !== nextContext.validationData) {
- let currentValue = JSONPointer.getValue(this.context.validationData, this.props.pointer),
- nextValue = JSONPointer.getValue(nextContext.validationData, nextPointer);
- if(nextValue === undefined) {
- nextValue = '';
- }
- if (this.state.isMultiSelect && Array.isArray(nextValue) && nextValue.length === 0) {
- nextValue = '';
- }
- if (currentValue !== nextValue) {
- this.setState({value: nextValue});
- }
- if (validationsChanged) {
- this.setState({
- validations: this.extractValidationsFromSchema(nextContext.validationSchema, nextPointer, {validations: nextValidations})
- });
- }
- }
- } else {
- if (validationsChanged) {
- this.setState({validations: nextValidations});
- }
- if (this.state.wasInvalid && (value !== nextValue || validationsChanged)) {
- this.validate(nextValue, nextValidations);
- } else if (value !== nextValue) {
- this.setState({value: nextValue});
- }
- }
- }
-
- shouldTypeBeNumberBySchemeDefinition(pointer) {
- return this.context.validationSchema &&
- this.context.validationSchema.isNumber(pointer);
- }
-
- hasEnum(pointer) {
- return this.context.validationSchema &&
- this.context.validationSchema.getEnum(pointer);
- }
-
- render() {
- let {value, isMultiSelect, values, onEnumChange, style, isValid, validations} = this.state;
- let {onOtherChange, type, pointer} = this.props;
- if (this.shouldTypeBeNumberBySchemeDefinition(pointer) && !this.hasEnum(pointer)) {
- type = 'number';
- }
- let props = {...this.props};
-
- let groupClasses = this.props.groupClassName || '';
- if (validations.required) {
- groupClasses += ' required';
- }
- let isReadOnlyMode = this.context.isReadOnlyMode;
-
- if (value === true && (type === 'checkbox' || type === 'radio')) {
- props.checked = true;
- }
- return (
- <div className='validation-input-wrapper'>
- {
- !isMultiSelect && !onOtherChange && type !== 'select' && type !== 'radiogroup'
- && <Input
- {...props}
- type={type}
- groupClassName={groupClasses}
- ref={'_myInput'}
- value={value}
- disabled={isReadOnlyMode || Boolean(this.props.disabled)}
- bsStyle={style}
- onChange={() => this.changedInput()}
- onBlur={() => this.blurInput()}>
- {this.props.children}
- </Input>
- }
- {
- type === 'radiogroup'
- && <FormGroup>
- {
- values.map(val =>
- <Input disabled={isReadOnlyMode || Boolean(this.props.disabled)}
- inline={true}
- ref={'_myInput' + (typeof val.enum === 'string' ? val.enum.replace(/\W/g, '_') : val.enum)}
- value={val.enum} checked={value === val.enum}
- type='radio' label={val.title}
- name={val.groupName}
- onChange={() => this.changedInput()}/>
- )
- }
- </FormGroup>
- }
- {
- (isMultiSelect || onOtherChange || type === 'select')
- && <InputOptions
- onInputChange={() => this.changedInput()}
- onBlur={() => this.blurInput()}
- hasError={!isValid}
- ref={'_myInput'}
- isMultiSelect={isMultiSelect}
- values={values}
- onEnumChange={onEnumChange}
- selectedEnum={value}
- multiSelectedEnum={value}
- {...props} />
- }
- {this.renderOverlay()}
- </div>
- );
- }
-
- renderOverlay() {
- let position = 'right';
- if (this.props.type === 'text'
- || this.props.type === 'email'
- || this.props.type === 'number'
- || this.props.type === 'password'
-
- ) {
- position = 'bottom';
- }
-
- let validationMessage = this.state.error.message || this.state.previousErrorMessage;
- return (
- <Overlay
- show={!this.state.isValid}
- placement={position}
- target={() => {
- let target = ReactDOM.findDOMNode(this.refs._myInput);
- return target.offsetParent ? target : undefined;
- }}
- container={this}>
- <Tooltip
- id={`error-${validationMessage.replace(' ', '-')}`}
- className='validation-error-message'>
- {validationMessage}
- </Tooltip>
- </Overlay>
- );
- }
-
- componentDidMount() {
- if (this.context.validationParent) {
- this.context.validationParent.register(this);
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (this.context.validationParent) {
- if (prevState.isValid !== this.state.isValid) {
- this.context.validationParent.childValidStateChanged(this, this.state.isValid);
- }
- }
- if (this.props.didUpdateCallback) {
- this.props.didUpdateCallback();
- }
-
- }
-
- componentWillUnmount() {
- if (this.context.validationParent) {
- this.context.validationParent.unregister(this);
- }
- }
-
- isNumberInputElement() {
- return this.props.type === 'number' || this.refs._myInput.props.type === 'number';
- }
-
- /***
- * Adding same method as the actual input component
- * @returns {*}
- */
- getValue() {
- if (this.props.type === 'checkbox') {
- return this.refs._myInput.getChecked();
- }
- if (this.props.type === 'radiogroup') {
- for (let key in this.refs) { // finding the value of the radio button that was checked
- if (this.refs[key].getChecked()) {
- return this.refs[key].getValue();
- }
- }
- }
- if (this.isNumberInputElement()) {
- return Number(this.refs._myInput.getValue());
- }
-
- return this.refs._myInput.getValue();
- }
-
- resetValue() {
- this.setState({value: this.props.value});
- }
-
-
- /***
- * internal method that validated the value. includes callback to the onChange method
- * @param value
- * @param validations - map containing validation id and the limitation describing the validation.
- * @returns {object}
- */
- validateValue = (value, validations) => {
- let {customValidationFunction} = validations;
- let error = {};
- let isValid = true;
- for (let validation in validations) {
- if ('customValidationFunction' !== validation) {
- if (validations[validation]) {
- if (!globalValidationFunctions[validation](value, validations[validation])) {
- error.id = validation;
- error.message = globalValidationMessagingFunctions[validation](value, validations[validation]);
- isValid = false;
- break;
- }
- }
- } else {
- let customValidationResult = customValidationFunction(value);
-
- if (customValidationResult !== true) {
- error.id = 'custom';
- isValid = false;
- if (typeof customValidationResult === 'string') {//custom validation error message supplied.
- error.message = customValidationResult;
- } else {
- error.message = globalValidationMessagingFunctions.general();
- }
- break;
- }
-
-
- }
- }
-
- return {
- isValid,
- error
- };
- };
-
- /***
- * Internal method that handles the change event of the input. validates and updates the state.
- */
- changedInput() {
-
- let {isValid, error} = this.state.wasInvalid ? this.validate() : this.state;
- let onChange = this.props.onChange;
- if (onChange) {
- onChange(this.getValue(), isValid, error);
- }
- if (this.context.validationSchema) {
- let value = this.getValue();
- if (this.state.isMultiSelect && value === '') {
- value = [];
- }
- if (this.shouldTypeBeNumberBySchemeDefinition(this.props.pointer)) {
- value = Number(value);
- }
- this.context.validationParent.onValueChanged(this.props.pointer, value, isValid, error);
- }
- }
-
- changedInputOptions(value) {
- this.context.validationParent.onValueChanged(this.props.pointer, value, true);
- }
-
- blurInput() {
- if (!this.state.wasInvalid) {
- this.setState({wasInvalid: true});
- }
-
- let {isValid, error} = !this.state.wasInvalid ? this.validate() : this.state;
- let onBlur = this.props.onBlur;
- if (onBlur) {
- onBlur(this.getValue(), isValid, error);
- }
- }
-
- validate(value = this.getValue(), validations = this.state.validations) {
- let validationStatus = this.validateValue(value, validations);
- let {isValid, error} = validationStatus;
- let _style = isValid ? null : 'error';
- this.setState({
- isValid,
- error,
- value,
- previousErrorMessage: this.state.error.message || '',
- style: _style,
- wasInvalid: !isValid || this.state.wasInvalid
- });
-
- return validationStatus;
- }
-
- isValid() {
- return this.state.isValid;
- }
-
-}
-export default ValidationInput;
diff --git a/openecomp-ui/src/nfvo-components/input/validation/ValidationTab.jsx b/openecomp-ui/src/nfvo-components/input/validation/ValidationTab.jsx
deleted file mode 100644
index 6036518288..0000000000
--- a/openecomp-ui/src/nfvo-components/input/validation/ValidationTab.jsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import React from 'react';
-import Tab from 'react-bootstrap/lib/Tab.js';
-
-export default
-class ValidationTab extends React.Component {
-
- static propTypes = {
- children: React.PropTypes.node,
- eventKey: React.PropTypes.any.isRequired,
- onValidationStateChange: React.PropTypes.func //This property is assigned dynamically via React.cloneElement. lookup ValidationTabs.jsx. therefore it cannot be stated as required!
- };
-
- constructor(props) {
- super(props);
- this.validationComponents = [];
- }
-
- static childContextTypes = {
- validationParent: React.PropTypes.any
- };
-
- static contextTypes = {
- validationParent: React.PropTypes.any
- };
-
- getChildContext() {
- return {validationParent: this};
- }
-
- state = {
- isValid: true,
- notifyParent: false
- };
-
- componentDidMount() {
- let validationParent = this.context.validationParent;
- if (validationParent) {
- validationParent.register(this);
- }
- }
-
- componentWillUnmount() {
- let validationParent = this.context.validationParent;
- if (validationParent) {
- validationParent.unregister(this);
- }
- }
-
- register(validationComponent) {
- this.validationComponents.push(validationComponent);
- }
-
- unregister(validationComponent) {
- this.childValidStateChanged(validationComponent, true);
- this.validationComponents = this.validationComponents.filter(otherValidationComponent => validationComponent !== otherValidationComponent);
- }
-
- notifyValidStateChangedToParent(isValid) {
-
- let validationParent = this.context.validationParent;
- if (validationParent) {
- validationParent.childValidStateChanged(this, isValid);
- }
- }
-
- childValidStateChanged(validationComponent, isValid) {
-
- const currentValidState = this.state.isValid;
- if (isValid !== currentValidState) {
- let filteredValidationComponents = this.validationComponents.filter(otherValidationComponent => validationComponent !== otherValidationComponent);
- let newValidState = isValid && filteredValidationComponents.every(otherValidationComponent => {
- return otherValidationComponent.isValid();
- });
- this.setState({isValid: newValidState, notifyParent: true});
- }
- }
-
- validate() {
- let isValid = true;
- this.validationComponents.forEach(validationComponent => {
- const isValidationComponentValid = validationComponent.validate().isValid;
- isValid = isValidationComponentValid && isValid;
- });
- this.setState({isValid, notifyParent: false});
- return {isValid};
- }
-
- componentDidUpdate(prevProps, prevState) {
- if(prevState.isValid !== this.state.isValid) {
- if(this.state.notifyParent) {
- this.notifyValidStateChangedToParent(this.state.isValid);
- }
- this.props.onValidationStateChange(this.props.eventKey, this.state.isValid);
- }
- }
-
- isValid() {
- return this.state.isValid;
- }
-
- render() {
- let {children, ...tabProps} = this.props;
- return (
- <Tab {...tabProps}>{children}</Tab>
- );
- }
-}
diff --git a/openecomp-ui/src/nfvo-components/input/validation/ValidationTabs.jsx b/openecomp-ui/src/nfvo-components/input/validation/ValidationTabs.jsx
deleted file mode 100644
index 6eda4b9827..0000000000
--- a/openecomp-ui/src/nfvo-components/input/validation/ValidationTabs.jsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import Tabs from 'react-bootstrap/lib/Tabs.js';
-import Overlay from 'react-bootstrap/lib/Overlay.js';
-import Tooltip from 'react-bootstrap/lib/Tooltip.js';
-
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-export default
-class ValidationTab extends React.Component {
-
- static propTypes = {
- children: React.PropTypes.node
- };
-
- state = {
- invalidTabs: []
- };
-
- cloneTab(element) {
- const {invalidTabs} = this.state;
- return React.cloneElement(
- element,
- {
- key: element.props.eventKey,
- tabClassName: invalidTabs.indexOf(element.props.eventKey) > -1 ? 'invalid-tab' : 'valid-tab',
- onValidationStateChange: (eventKey, isValid) => this.validTabStateChanged(eventKey, isValid)
- }
- );
- }
-
- validTabStateChanged(eventKey, isValid) {
- let {invalidTabs} = this.state;
- let invalidTabIndex = invalidTabs.indexOf(eventKey);
- if (isValid && invalidTabIndex > -1) {
- this.setState({invalidTabs: invalidTabs.filter(otherEventKey => eventKey !== otherEventKey)});
- } else if (!isValid && invalidTabIndex === -1) {
- this.setState({invalidTabs: [...invalidTabs, eventKey]});
- }
- }
-
- showTabsError() {
- const {invalidTabs} = this.state;
- return invalidTabs.length > 0 && (invalidTabs.length > 1 || invalidTabs[0] !== this.props.activeKey);
- }
-
- render() {
- return (
- <div>
- <Tabs {...this.props} ref='tabsList'>
- {this.props.children.map(element => this.cloneTab(element))}
- </Tabs>
- <Overlay
- animation={false}
- show={this.showTabsError()}
- placement='bottom'
- target={() => {
- let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.active):nth-of-type(n)');
- return target && target.offsetParent ? target : undefined;
- }
- }
- container={this}>
- <Tooltip
- id='error-some-tabs-contain-errors'
- className='validation-error-message'>
- {i18n('One or more tabs are invalid')}
- </Tooltip>
- </Overlay>
- </div>
- );
- }
-}
diff --git a/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx
index e8d0fc2536..f6c906b56b 100644
--- a/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx
+++ b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx
@@ -1,7 +1,24 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import FontAwesome from 'react-fontawesome';
+import classnames from 'classnames';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
import store from 'sdc-app/AppStore.js';
-import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
class ListEditorItem extends React.Component {
static propTypes = {
@@ -16,14 +33,14 @@ class ListEditorItem extends React.Component {
let {onDelete, onSelect, onEdit, children, isReadOnlyMode} = this.props;
let isAbilityToDelete = isReadOnlyMode === undefined ? true : !isReadOnlyMode;
return (
- <div className='list-editor-item-view'>
+ <div className={classnames('list-editor-item-view', {'selectable': Boolean(onSelect)})} data-test-id='list-editor-item'>
<div className='list-editor-item-view-content' onClick={onSelect}>
{children}
</div>
- <div className='list-editor-item-view-controller'>
- {onEdit && <FontAwesome name='sliders' onClick={() => this.onClickedItem(onEdit)}/>}
- {onDelete && isAbilityToDelete && <FontAwesome name='trash-o' onClick={() => this.onClickedItem(onDelete)}/>}
- </div>
+ {(onEdit || onDelete) && <div className='list-editor-item-view-controller'>
+ {onEdit && <SVGIcon name='sliders' onClick={() => this.onClickedItem(onEdit)}/>}
+ {onDelete && isAbilityToDelete && <SVGIcon name='trash-o' onClick={() => this.onClickedItem(onDelete)}/>}
+ </div>}
</div>
);
}
@@ -33,8 +50,11 @@ class ListEditorItem extends React.Component {
let {isCheckedOut} = this.props;
if (isCheckedOut === false) {
store.dispatch({
- type: NotificationConstants.NOTIFY_ERROR,
- data: {title: 'Error', msg: 'This item is checkedin/submitted, Click Check Out to continue'}
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data: {
+ title: i18n('Error'),
+ msg: i18n('This item is checkedin/submitted, Click Check Out to continue')
+ }
});
}
else {
diff --git a/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemViewField.jsx b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemViewField.jsx
new file mode 100644
index 0000000000..839f9a504a
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemViewField.jsx
@@ -0,0 +1,24 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+export const ListEditorItemViewField = ({children}) => (
+ <div className='list-editor-item-view-field'>
+ {children}
+ </div>
+);
+
+export default ListEditorItemViewField;
diff --git a/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx b/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx
index 1ee91f31f6..cc805e9ada 100644
--- a/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx
+++ b/openecomp-ui/src/nfvo-components/listEditor/ListEditorView.jsx
@@ -1,12 +1,63 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import FontAwesome from 'react-fontawesome';
-import Input from 'react-bootstrap/lib/Input.js';
+import classnames from 'classnames';
+import ExpandableInput from 'nfvo-components/input/ExpandableInput.jsx';
+const ListEditorHeader = ({onAdd, isReadOnlyMode, title, plusButtonTitle}) => {
+ return (
+ <div className='list-editor-view-header'>
+ {title && <div className='list-editor-view-title'>{title}</div>}
+ <div className={`list-editor-view-add-controller${isReadOnlyMode ? ' disabled' : ''}`}>
+ { onAdd &&
+ <div className='list-editor-view-add-title' data-test-id='add-button' onClick={onAdd}>
+ <span>{`+ ${plusButtonTitle}`}</span>
+ </div>
+ }
+ </div>
+ </div>
+ );
+};
+
+const ListEditorScroller = ({children, twoColumns}) => {
+ return (
+ <div className='list-editor-view-list-scroller'>
+ <div className={classnames('list-editor-view-list', {'two-columns': twoColumns})}>
+ {children}
+ </div>
+ </div>
+ );
+};
+
+const FilterWrapper = ({onFilter, filterValue}) => {
+ return (
+ <div className='expandble-search-wrapper'>
+ <ExpandableInput
+ onChange={onFilter}
+ iconType='search'
+ value={filterValue}/>
+ </div>
+ );
+};
class ListEditorView extends React.Component {
static defaultProps = {
- className: ''
+ className: '',
+ twoColumns: false
};
static propTypes = {
@@ -17,45 +68,17 @@ class ListEditorView extends React.Component {
onFilter: React.PropTypes.func,
className: React.PropTypes.string,
isReadOnlyMode: React.PropTypes.bool,
- placeholder: React.PropTypes.string
+ placeholder: React.PropTypes.string,
+ twoColumns: React.PropTypes.bool
};
render() {
- let {title, plusButtonTitle, onAdd, children, filterValue, onFilter, className, placeholder, isReadOnlyMode} = this.props;
+ let {title, plusButtonTitle, onAdd, children, onFilter, className, isReadOnlyMode, twoColumns, filterValue} = this.props;
return (
- <div className={`list-editor-view ${className}`}>
- {title && onAdd && <div className='list-editor-view-title'>{title}</div>}
- <div className='list-editor-view-actions'>
- {title && !onAdd && <div className='list-editor-view-title-inline'>{title}</div>}
- <div className={`list-editor-view-add-controller${isReadOnlyMode ? ' disabled' : ''}`} >
- { onAdd &&
- <div onClick={onAdd}>
- <span className='plus-icon-button pull-left'/>
- <span>{plusButtonTitle}</span>
- </div>
- }
- </div>
-
- {
- onFilter &&
- <div className='list-editor-view-search search-wrapper'>
- <Input
- ref='filter'
- type='text'
- value={filterValue}
- name='list-editor-view-search'
- placeholder={placeholder}
- groupClassName='search-input-control'
- onChange={() => onFilter(this.refs.filter.getValue())}/>
- <FontAwesome name='filter' className='filter-icon'/>
- </div>
- }
- </div>
- <div className='list-editor-view-list-scroller'>
- <div className='list-editor-view-list'>
- {children}
- </div>
- </div>
+ <div className={classnames('list-editor-view', className)}>
+ <ListEditorHeader onAdd={onAdd} isReadOnlyMode={isReadOnlyMode} plusButtonTitle={plusButtonTitle} title={title}/>
+ {onFilter && (children.length || filterValue) && <FilterWrapper onFilter={onFilter} filterValue={filterValue}/>}
+ <ListEditorScroller children={children} twoColumns={twoColumns}/>
</div>
);
}
diff --git a/openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js b/openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js
new file mode 100644
index 0000000000..276b05e270
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/listEditor/listEditor.stories.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import {storiesOf, action} from '@kadira/storybook';
+import ListEditorView from './ListEditorView.jsx';
+import ListEditorItemView from './ListEditorItemView.jsx';
+import ListEditorItemViewField from './ListEditorItemViewField.jsx';
+import {text, number} from '@kadira/storybook-addon-knobs';
+import {withKnobs} from '@kadira/storybook-addon-knobs';
+
+function makeChildren({onEdit = false, onDelete = false} = {}) {
+ return (
+ [...Array(number('Items', 2)).keys()].map(index => (
+ <ListEditorItemView
+ key={index}
+ onEdit={onEdit ? onEdit : undefined}
+ onDelete={onDelete ? onDelete : undefined}>
+ <ListEditorItemViewField>
+ <div>{text('field 1', 'Lorum Ipsum')}</div>
+ </ListEditorItemViewField>
+ <ListEditorItemViewField>
+ <div>{text('field 2', 'Lorum Ipsum')}</div>
+ </ListEditorItemViewField>
+ </ListEditorItemView>)
+ )
+ );
+}
+
+const stories = storiesOf('ListEditor', module);
+stories.addDecorator(withKnobs);
+
+stories
+ .add('regular', () => (
+ <ListEditorView title='List Editor'>
+ {makeChildren()}
+ </ListEditorView>
+ ))
+ .add('two columns', () => (
+ <ListEditorView title='List Editor' twoColumns>
+ {makeChildren()}
+ </ListEditorView>
+ ))
+ .add('with add', () => (
+ <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
+ {makeChildren()}
+ </ListEditorView>
+ ))
+ .add('with delete', () => (
+ <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
+ {makeChildren({onDelete: action('onDelete')})}
+ </ListEditorView>
+ ))
+ .add('with edit', () => (
+ <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
+ {makeChildren({onEdit: action('onEdit')})}
+ </ListEditorView>
+ ))
+ .add('with edit and delete', () => (
+ <ListEditorView title='List Editor' onAdd={action('onAdd')} plusButtonTitle='Add' twoColumns>
+ {makeChildren({onDelete: action('onDelete'), onEdit: action('onEdit')})}
+ </ListEditorView>
+ ));
diff --git a/openecomp-ui/src/nfvo-components/loader/Loader.jsx b/openecomp-ui/src/nfvo-components/loader/Loader.jsx
index cc1ffdb2b3..675b04c8ea 100644
--- a/openecomp-ui/src/nfvo-components/loader/Loader.jsx
+++ b/openecomp-ui/src/nfvo-components/loader/Loader.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import {connect} from 'react-redux';
diff --git a/openecomp-ui/src/nfvo-components/loader/LoaderConstants.js b/openecomp-ui/src/nfvo-components/loader/LoaderConstants.js
index e8e4953eb9..7c0c0e2b08 100644
--- a/openecomp-ui/src/nfvo-components/loader/LoaderConstants.js
+++ b/openecomp-ui/src/nfvo-components/loader/LoaderConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
diff --git a/openecomp-ui/src/nfvo-components/loader/LoaderReducer.js b/openecomp-ui/src/nfvo-components/loader/LoaderReducer.js
index 582eff330d..2eff70a617 100644
--- a/openecomp-ui/src/nfvo-components/loader/LoaderReducer.js
+++ b/openecomp-ui/src/nfvo-components/loader/LoaderReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './LoaderConstants.js';
export default (state = {}, action) => {
diff --git a/openecomp-ui/src/nfvo-components/modal/GlobalModal.js b/openecomp-ui/src/nfvo-components/modal/GlobalModal.js
new file mode 100644
index 0000000000..65a1ad683b
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/modal/GlobalModal.js
@@ -0,0 +1,120 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import React from 'react';
+import {connect} from 'react-redux';
+
+import Modal from 'nfvo-components/modal/Modal.jsx';
+import Button from 'react-bootstrap/lib/Button.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {modalContentComponents} from 'sdc-app/common/modal/ModalContentMapper.js';
+import {actionTypes, typeEnum} from './GlobalModalConstants.js';
+
+
+const typeClass = {
+ 'default': 'primary',
+ error: 'danger',
+ warning: 'warning',
+ success: 'success'
+};
+
+
+const ModalFooter = ({type, onConfirmed, onDeclined, onClose, confirmationButtonText, cancelButtonText}) =>
+ <Modal.Footer>
+ <Button bsStyle={typeClass[type]} onClick={onDeclined ? () => {
+ onDeclined();
+ onClose();} : () => onClose()}>
+ {cancelButtonText}
+ </Button>
+ {onConfirmed && <Button bsStyle={typeClass[type]} onClick={() => {
+ onConfirmed();
+ onClose();
+ }}>{confirmationButtonText}</Button>}
+ </Modal.Footer>;
+
+ModalFooter.defaultProps = {
+ type: 'default',
+ confirmationButtonText: i18n('OK'),
+ cancelButtonText: i18n('Cancel')
+};
+
+export const mapStateToProps = ({modal}) => {
+ const show = !!modal;
+ return {
+ show,
+ ...modal
+ };
+};
+
+export const mapActionToProps = (dispatch) => {
+ return {
+ onClose: () => dispatch({type: actionTypes.GLOBAL_MODAL_CLOSE})
+ };
+};
+
+
+export class GlobalModalView extends React.Component {
+
+ static propTypes = {
+ show: React.PropTypes.bool,
+ type: React.PropTypes.oneOf(['default', 'error', 'warning', 'success']),
+ title: React.PropTypes.string,
+ modalComponentProps: React.PropTypes.object,
+ modalComponentName: React.PropTypes.string,
+ onConfirmed: React.PropTypes.func,
+ onDeclined: React.PropTypes.func,
+ confirmationButtonText: React.PropTypes.string,
+ cancelButtonText: React.PropTypes.string
+ };
+
+ static defaultProps = {
+ show: false,
+ type: 'default',
+ title: ''
+ };
+
+ render() {
+ let {title, type, show, modalComponentName, modalComponentProps,
+ modalClassName, msg, onConfirmed, onDeclined, confirmationButtonText, cancelButtonText, onClose} = this.props;
+ const ComponentToRender = modalContentComponents[modalComponentName];
+ return (
+ <Modal show={show} bsSize={modalComponentProps && modalComponentProps.size} className={`onborading-modal ${modalClassName || ''} ${typeClass[type]}`}>
+ <Modal.Header>
+ <Modal.Title>{title}</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ {ComponentToRender ? <ComponentToRender {...modalComponentProps}/> : msg}
+ </Modal.Body>
+ {(onConfirmed || onDeclined || type !== typeEnum.DEFAULT) &&
+ <ModalFooter
+ type={type}
+ onConfirmed={onConfirmed}
+ onDeclined={onDeclined}
+ onClose={onClose}
+ confirmationButtonText={confirmationButtonText}
+ cancelButtonText={cancelButtonText}/>}
+ </Modal>
+ );
+ }
+
+ componentDidUpdate() {
+ if (this.props.timeout) {
+ setTimeout(this.props.onClose, this.props.timeout);
+ }
+ }
+};
+
+export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(GlobalModalView);
diff --git a/openecomp-ui/src/nfvo-components/modal/GlobalModalConstants.js b/openecomp-ui/src/nfvo-components/modal/GlobalModalConstants.js
new file mode 100644
index 0000000000..0a0ed1fd71
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/modal/GlobalModalConstants.js
@@ -0,0 +1,33 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+ GLOBAL_MODAL_SHOW: null,
+ GLOBAL_MODAL_CLOSE: null,
+ GLOBAL_MODAL_ERROR: null,
+ GLOBAL_MODAL_WARNING: null,
+ GLOBAL_MODAL_SUCCESS: null,
+
+});
+
+
+export const typeEnum = {
+ DEFAULT: 'default',
+ ERROR: 'error',
+ WARNING: 'warning',
+ SUCCESS: 'success'
+};
diff --git a/openecomp-ui/src/nfvo-components/modal/GlobalModalReducer.js b/openecomp-ui/src/nfvo-components/modal/GlobalModalReducer.js
new file mode 100644
index 0000000000..28674ea569
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/modal/GlobalModalReducer.js
@@ -0,0 +1,50 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import {actionTypes, typeEnum} from './GlobalModalConstants.js';
+
+export default (state = null, action) => {
+ switch (action.type) {
+ case actionTypes.GLOBAL_MODAL_SHOW:
+ return {
+ ...action.data
+ };
+ case actionTypes.GLOBAL_MODAL_ERROR:
+ return {
+ type: typeEnum.ERROR,
+ modalClassName: 'notification-modal',
+ ...action.data
+ };
+ case actionTypes.GLOBAL_MODAL_WARNING:
+ return {
+ type: typeEnum.WARNING,
+ modalClassName: 'notification-modal',
+ ...action.data
+ };
+
+ case actionTypes.GLOBAL_MODAL_SUCCESS:
+ return {
+ type: typeEnum.SUCCESS,
+ modalClassName: 'notification-modal',
+ ...action.data
+ };
+
+ case actionTypes.GLOBAL_MODAL_CLOSE:
+ return null;
+ default:
+ return state;
+ }
+};
diff --git a/openecomp-ui/src/nfvo-components/modal/Modal.jsx b/openecomp-ui/src/nfvo-components/modal/Modal.jsx
index be4963ef65..b0f704dba9 100644
--- a/openecomp-ui/src/nfvo-components/modal/Modal.jsx
+++ b/openecomp-ui/src/nfvo-components/modal/Modal.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import ReactDOM from 'react-dom';
import BootstrapModal from 'react-bootstrap/lib/Modal.js';
diff --git a/openecomp-ui/src/nfvo-components/notifications/NotificationConstants.js b/openecomp-ui/src/nfvo-components/notifications/NotificationConstants.js
deleted file mode 100644
index 1a53f4c135..0000000000
--- a/openecomp-ui/src/nfvo-components/notifications/NotificationConstants.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import keyMirror from 'nfvo-utils/KeyMirror.js';
-
-export default keyMirror({
- NOTIFY_ERROR: null,
- NOTIFY_SUCCESS: null,
- NOTIFY_WARNING: null,
- NOTIFY_INFO: null,
- NOTIFY_CLOSE: null
-});
diff --git a/openecomp-ui/src/nfvo-components/notifications/NotificationModal.jsx b/openecomp-ui/src/nfvo-components/notifications/NotificationModal.jsx
deleted file mode 100644
index 71793097fb..0000000000
--- a/openecomp-ui/src/nfvo-components/notifications/NotificationModal.jsx
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * NotificationModal options:
- *
- * show: whether to show notification or not,
- * type: the type of the notification. valid values are: 'default', 'error', 'warning', 'success'
- * msg: the notification content. could be a string or node (React component)
- * title: the notification title
- * timeout: timeout for the notification to fade out. if timeout == 0 then the notification is rendered until the user closes it
- *
- */
-import React, {Component, PropTypes} from 'react';
-import {connect} from 'react-redux';
-import Button from 'react-bootstrap/lib/Button.js';
-
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import Modal from 'nfvo-components/modal/Modal.jsx';
-import SubmitErrorResponse from 'nfvo-components/SubmitErrorResponse.jsx';
-import NotificationConstants from './NotificationConstants.js';
-
-let typeClass = {
- 'default': 'primary',
- error: 'danger',
- warning: 'warning',
- success: 'success'
-};
-
-const mapActionsToProps = (dispatch) => {
- return {onCloseClick: () => dispatch({type: NotificationConstants.NOTIFY_CLOSE})};
-};
-
-const mapStateToProps = ({notification}) => {
-
- let show = notification !== null && notification.title !== 'Conflict';
- let mapResult = {show};
- if (show) {
- mapResult = {show, ...notification};
- }
-
- return mapResult;
-};
-
-export class NotificationModal extends Component {
-
- static propTypes = {
- show: PropTypes.bool,
- type: PropTypes.oneOf(['default', 'error', 'warning', 'success']),
- title: PropTypes.string,
- msg: PropTypes.node,
- validationResponse: PropTypes.object,
- timeout: PropTypes.number
- };
-
- static defaultProps = {
- show: false,
- type: 'default',
- title: '',
- msg: '',
- timeout: 0
- };
-
- state = {type: undefined};
-
- componentWillReceiveProps(nextProps) {
- if (this.props.show !== nextProps.show && nextProps.show === false) {
- this.setState({type: this.props.type});
- }
- else {
- this.setState({type: undefined});
- }
- }
-
- componentDidUpdate() {
- if (this.props.timeout) {
- setTimeout(this.props.onCloseClick, this.props.timeout);
- }
- }
-
- render() {
- let {title, type, msg, show, validationResponse, onCloseClick} = this.props;
- if (!show) {
- type = this.state.type;
- }
- if (validationResponse) {
- msg = (<SubmitErrorResponse validationResponse={validationResponse}/>);
- }
- return (
- <Modal show={show} className={`notification-modal ${typeClass[type]}`}>
- <Modal.Header>
- <Modal.Title>{title}</Modal.Title>
- </Modal.Header>
- <Modal.Body>{msg}</Modal.Body>
- <Modal.Footer>
- <Button bsStyle={typeClass[type]} onClick={onCloseClick}>{i18n('OK')}</Button>
- </Modal.Footer>
- </Modal>
- );
- }
-}
-
-export default connect(mapStateToProps, mapActionsToProps)(NotificationModal);
diff --git a/openecomp-ui/src/nfvo-components/notifications/NotificationReducer.js b/openecomp-ui/src/nfvo-components/notifications/NotificationReducer.js
deleted file mode 100644
index c8b30d6e50..0000000000
--- a/openecomp-ui/src/nfvo-components/notifications/NotificationReducer.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import NotificationConstants from './NotificationConstants.js';
-
-export default (state = null, action) => {
- switch (action.type) {
- case NotificationConstants.NOTIFY_INFO:
- return {type: 'default', title: action.data.title, msg: action.data.msg, timeout: action.data.timeout};
-
- case NotificationConstants.NOTIFY_ERROR:
- return {
- type: 'error',
- title: action.data.title,
- msg: action.data.msg,
- validationResponse: action.data.validationResponse,
- timeout: action.data.timeout
- };
-
- case NotificationConstants.NOTIFY_WARNING:
- return {type: 'warning', title: action.data.title, msg: action.data.msg, timeout: action.data.timeout};
-
- case NotificationConstants.NOTIFY_SUCCESS:
- return {
- type: 'success', title: action.data.title, msg: action.data.msg, timeout: action.data.timeout
- };
- case NotificationConstants.NOTIFY_CLOSE:
- return null;
-
- default:
- return state;
- }
-
-};
diff --git a/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx b/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx
index feb0f813ea..3b89137090 100644
--- a/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx
+++ b/openecomp-ui/src/nfvo-components/panel/NavigationSideBar.jsx
@@ -1,9 +1,23 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import classnames from 'classnames';
import Collapse from 'react-bootstrap/lib/Collapse.js';
class NavigationSideBar extends React.Component {
-
static PropTypes = {
activeItemId: React.PropTypes.string.isRequired,
onSelect: React.PropTypes.func,
@@ -11,51 +25,26 @@ class NavigationSideBar extends React.Component {
groups: React.PropTypes.array
};
+ constructor(props) {
+ super(props);
+ this.state = {
+ activeItemId: null
+ };
+ this.handleItemClicked = this.handleItemClicked.bind(this);
+ }
+
render() {
let {groups, activeItemId} = this.props;
return (
<div className='navigation-side-content'>
{groups.map(group => (
- <div className='navigation-group' key={group.id}>
- <div className='group-name'>{group.name}</div>
- <div className='navigation-group-items'>
- {
- group.items && group.items.map(item => this.renderGroupItem(item, activeItemId))
- }
- </div>
- </div>
+ <NavigationMenu menu={group} activeItemId={activeItemId} onNavigationItemClick={this.handleItemClicked} key={'menu_' + group.id} />
))}
</div>
);
}
- renderGroupItem(item, activeItemId) {
- let isGroup = item.items && item.items.length > 0;
- return (
- <div className={classnames('navigation-group-item', {'selected-item': item.id === activeItemId})}>
- <div
- key={item.id}
- className={classnames('navigation-group-item-name', {
- 'selected': item.id === activeItemId,
- 'disabled': item.disabled,
- 'bold-name': item.expanded,
- 'hidden': item.hidden
- })}
- onClick={(event) => this.handleItemClicked(event, item)}>
- {item.name}
- </div>
- {isGroup &&
- <Collapse in={item.expanded}>
- <div>
- {item.items.map(item => this.renderGroupItem(item, activeItemId))}
- </div>
- </Collapse>
- }
- </div>
- );
- }
-
handleItemClicked(event, item) {
event.stopPropagation();
if(this.props.onToggle) {
@@ -70,4 +59,70 @@ class NavigationSideBar extends React.Component {
}
}
+class NavigationMenu extends React.Component {
+ static PropTypes = {
+ activeItemId: React.PropTypes.string.isRequired,
+ onNavigationItemClick: React.PropTypes.func,
+ menu: React.PropTypes.array
+ };
+
+ render() {
+ const {menu, activeItemId, onNavigationItemClick} = this.props;
+ return (
+ <div className='navigation-group' key={menu.id}>
+ <NavigationMenuHeader title={menu.name} />
+ <NavigationMenuItems items={menu.items} activeItemId={activeItemId} onNavigationItemClick={onNavigationItemClick} />
+ </div>);
+ }
+}
+
+function NavigationMenuHeader(props) {
+ return <div className='group-name' data-test-id='navbar-group-name'>{props.title}</div>;
+}
+
+function NavigationMenuItems(props) {
+ const {items, activeItemId, onNavigationItemClick} = props;
+ return (
+ <div className='navigation-group-items'>
+ {
+ items && items.map(item => (<NavigationMenuItem key={'menuItem_' + item.id} item={item} activeItemId={activeItemId} onNavigationItemClick={onNavigationItemClick} />))
+ }
+ </div>
+ );
+}
+
+function NavigationMenuItem(props) {
+ const {onNavigationItemClick, item, activeItemId} = props;
+ const isGroup = item.items && item.items.length > 0;
+ return (
+ <div className={classnames('navigation-group-item', {'selected-item': item.id === activeItemId})} key={'item_' + item.id}>
+ <NavigationLink item={item} activeItemId={activeItemId} onClick={onNavigationItemClick} />
+ {isGroup && <Collapse in={item.expanded} data-test-id={'navigation-group-' + item.id}>
+ <div>
+ {item.items.map(subItem => (<NavigationMenuItem key={'menuItem_' + subItem.id} item={subItem} onNavigationItemClick={onNavigationItemClick} activeItemId={activeItemId} />)) }
+ </div>
+ </Collapse>
+ }
+ </div>
+ );
+}
+
+function NavigationLink(props) {
+ const {item, activeItemId, onClick} = props;
+ return (
+ <div
+ key={'navAction_' + item.id}
+ className={classnames('navigation-group-item-name', {
+ 'selected': item.id === activeItemId,
+ 'disabled': item.disabled,
+ 'bold-name': item.expanded,
+ 'hidden': item.hidden
+ })}
+ onClick={(event) => onClick(event, item)}
+ data-test-id={'navbar-group-item-' + item.id}>
+ {item.name}
+ </div>
+ );
+}
+
export default NavigationSideBar;
diff --git a/openecomp-ui/src/nfvo-components/panel/SlidePanel.jsx b/openecomp-ui/src/nfvo-components/panel/SlidePanel.jsx
deleted file mode 100644
index 10c5326300..0000000000
--- a/openecomp-ui/src/nfvo-components/panel/SlidePanel.jsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import React from 'react';
-import FontAwesome from 'react-fontawesome';
-import ReactDOM from 'react-dom';
-
-class SlidePanel extends React.Component {
-
- static PropTypes = {
- direction: React.PropTypes.string.isRequired,
- className: React.PropTypes.string,
- title: React.PropTypes.string,
- isOpen: React.PropTypes.bool
- };
-
- static defaultProps = {
- title: '',
- className: '',
- isOpen: true
- };
-
- state = {
- isOpen: this.props.isOpen,
- direction: this.props.direction,
- width: 0,
- arrowWidth: 0
- };
-
- componentDidMount() {
- this.setSliderPosition();
- }
-
- componentDidUpdate() {
- this.setSliderPosition();
- }
-
- render() {
-
- let {children, className} = this.props;
- let {isOpen} = this.state;
-
- return (
- <div className={ `slide-panel ${className}`}>
- {this.renderHeader(isOpen)}
- <div className={'slide-panel-content ' + (isOpen ? 'opened' : 'closed')}>{children}</div>
- </div>
- );
- }
-
- renderHeader(isOpen) {
- let {direction: initialDirection, title} = this.props;
- let {direction: currentDirection} = this.state;
-
- let iconName = currentDirection === 'right' ? 'angle-double-right collapse-double-icon' : 'angle-double-left collapse-double-icon';
-
- let awestyle = {padding: '5px'};
-
- if (!isOpen && initialDirection === 'right') {
- awestyle.marginLeft = '-1px';
- }
- return (
- <div className='slide-panel-header'>
- { initialDirection === 'left' && <span className='slide-panel-header-title'>{title}</span>}
- <FontAwesome
- ref='arrowIcon'
- style={awestyle}
- onClick={this.handleClick}
- className='pull-right'
- name={iconName}
- size='2x'/>
- { initialDirection === 'right' && <span className='slide-panel-header-title'>{title}</span>}
- </div>
- );
- }
-
- handleClick = () => {
- this.setState({
- isOpen: !this.state.isOpen,
- direction: this.state.direction === 'left' ? 'right' : 'left'
- });
- }
-
- setSliderPosition = () => {
-
- let el = ReactDOM.findDOMNode(this);
- let {style} = el;
-
- let {direction: initialDirection} = this.props;
- let arrowIconSize = Math.floor(ReactDOM.findDOMNode(this.refs.arrowIcon).getBoundingClientRect().width) * 2;
- if (!this.state.isOpen) {
- if (this.props.direction === 'left') {
- style.left = arrowIconSize - el.getBoundingClientRect().width + 'px';
- }
- if (initialDirection === 'right') {
- style.right = arrowIconSize - el.getBoundingClientRect().width + 'px';
- }
- }
- else {
- if (initialDirection === 'left') {
- style.left = '0px';
- }
-
- if (this.props.direction === 'right') {
- style.right = '0px';
- }
- }
- }
-
-}
-
-export default SlidePanel; \ No newline at end of file
diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx b/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx
index 78525f84c6..6d900dd0bb 100644
--- a/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx
+++ b/openecomp-ui/src/nfvo-components/panel/versionController/VersionController.jsx
@@ -1,17 +1,31 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import classnames from 'classnames';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import Navbar from 'react-bootstrap/lib/Navbar.js';
-import Nav from 'react-bootstrap/lib/Nav.js';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
-import {actionsEnum, statusEnum} from './VersionControllerConstants.js';
+import {actionsEnum, statusEnum, statusBarTextMap } from './VersionControllerConstants.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
class VersionController extends React.Component {
static propTypes = {
- version: React.PropTypes.string,
+ version: React.PropTypes.object,
viewableVersions: React.PropTypes.array,
onVersionSwitching: React.PropTypes.func,
isCheckedOut: React.PropTypes.bool.isRequired,
@@ -23,143 +37,146 @@ class VersionController extends React.Component {
};
render() {
- let {status, isCheckedOut, version = '', viewableVersions = [], onVersionSwitching, callVCAction, onSave, isFormDataValid, onClose} = this.props;
+ let {status, isCheckedOut, version = {}, viewableVersions = [], onVersionSwitching, callVCAction, onSave, isFormDataValid, onClose} = this.props;
let isCheckedIn = Boolean(status === statusEnum.CHECK_IN_STATUS);
- let isLatestVersion = Boolean(version === viewableVersions[viewableVersions.length - 1]);
+ let isLatestVersion = Boolean(version.id === viewableVersions[viewableVersions.length - 1].id);
if (!isLatestVersion) {
status = statusEnum.PREVIOUS_VERSION;
}
-
return (
<div className='version-controller-bar'>
- <Navbar inverse className='navbar'>
- <Navbar.Collapse>
- <Nav className='items-in-left'>
- <div className='version-section'>
- <ValidationInput
- type='select'
- selectedEnum={version}
- onEnumChange={value => onVersionSwitching && onVersionSwitching(value)}>
- {viewableVersions && viewableVersions.map(viewVersion => {
- return (
- <option key={viewVersion} value={viewVersion}>{`V ${viewVersion}`}</option>
- );
- })
- }
- {!viewableVersions.includes(version) &&
- <option key={version} value={version}>{`V ${version}`}</option>}
- </ValidationInput>
- </div>
- <div className='vc-status'>
- <div className='onboarding-status-icon'></div>
- <div className='status-text'> {i18n('ONBOARDING')}
- <div className='status-text-dash'> -</div>
- </div>
- {this.renderStatus(status)}
- </div>
- </Nav>
- <Nav pullRight>
- <div className='items-in-right'>
- <div className='action-buttons'>
- {callVCAction &&
- <div className='version-control-buttons'>
- <div
- className={classnames('vc-nav-item-button button-submit', {'disabled': !isCheckedIn || !isLatestVersion})}
- onClick={() => this.submit(callVCAction)}>
- {i18n('Submit')}
- </div>
- <div
- className={classnames('vc-nav-item-button button-checkin-checkout', {'disabled': status === statusEnum.LOCK_STATUS || !isLatestVersion})}
- onClick={() => this.checkinCheckoutVersion(callVCAction)}>
- {`${isCheckedOut ? i18n('Check In') : i18n('Check Out')}`}
- </div>
- <div
- className={classnames('sprite-new revert-btn ng-scope ng-isolate-scope', {'disabled': !isCheckedOut || version === '0.1' || !isLatestVersion})}
- onClick={() => this.revertCheckout(callVCAction)}>
- </div>
- </div>
- }
- {onSave &&
- <div
- className={classnames('sprite-new save-btn ng-scope ng-isolate-scope', {'disabled': !isCheckedOut || !isFormDataValid || !isLatestVersion})}
- onClick={() => onSave()}>
- </div>
- }
- </div>
- <div className='vc-nav-item-close' onClick={() => onClose && onClose()}> X</div>
- </div>
- </Nav>
- </Navbar.Collapse>
- </Navbar>
+ <div className='vc-container'>
+ <div className='version-status-container'>
+ <VersionSelector viewableVersions={viewableVersions} version={version} onVersionSwitching={onVersionSwitching} />
+ <StatusBarUpdates status={status}/>
+ </div>
+ <div className='save-submit-cancel-container'>
+ <ActionButtons onSubmit={callVCAction ? () => this.submit(callVCAction, version) : undefined}
+ onRevert={callVCAction ? () => this.revertCheckout(callVCAction, version) : undefined}
+ status={status}
+ onCheckinCheckout={callVCAction ? () => this.checkinCheckoutVersion(callVCAction, version) : undefined}
+ onSave={onSave ? () => onSave() : undefined}
+ isLatestVersion={isLatestVersion}
+ isCheckedOut={isCheckedOut}
+ isCheckedIn={isCheckedIn} isFormDataValid={isFormDataValid} version={version}/>
+ {onClose && <div className='vc-nav-item-close' onClick={() => onClose()} data-test-id='vc-cancel-btn'> X</div>}
+ </div>
+ </div>
</div>
);
}
- renderStatus(status) {
- switch (status) {
- case statusEnum.CHECK_OUT_STATUS:
- return (
- <div className='checkout-status-icon'>
- <div className='catalog-tile-check-in-status sprite-new checkout-editable-status-icon'></div>
- <div className='status-text'> {i18n('CHECKED OUT')} </div>
- </div>
- );
- case statusEnum.LOCK_STATUS:
- return (
- <div className='status-text'> {i18n('LOCKED')} </div>
- );
- case statusEnum.CHECK_IN_STATUS:
- return (
- <div className='status-text'> {i18n('CHECKED IN')} </div>
- );
- case statusEnum.SUBMIT_STATUS:
- return (
- <div className='status-text'> {i18n('SUBMITTED')} </div>
- );
- default:
- return (
- <div className='status-text'> {i18n(status)} </div>
- );
- }
+ submit(callVCAction, version) {
+ const action = actionsEnum.SUBMIT;
+ callVCAction(action, version);
+ }
+
+ revertCheckout(callVCAction, version) {
+ const action = actionsEnum.UNDO_CHECK_OUT;
+ callVCAction(action, version);
}
- checkinCheckoutVersion(callVCAction) {
+ checkinCheckoutVersion(callVCAction, version) {
if (this.props.isCheckedOut) {
- this.checkin(callVCAction);
+ this.checkin(callVCAction, version);
}
else {
- this.checkout(callVCAction);
+ this.checkout(callVCAction, version);
}
}
-
- checkin(callVCAction) {
-
+ checkin(callVCAction, version) {
const action = actionsEnum.CHECK_IN;
-
if (this.props.onSave) {
this.props.onSave().then(()=>{
- callVCAction(action);
- });
+ callVCAction(action, version);
+ });
}else{
- callVCAction(action);
+ callVCAction(action, version);
}
}
-
- checkout(callVCAction) {
+ checkout(callVCAction, version) {
const action = actionsEnum.CHECK_OUT;
- callVCAction(action);
+ callVCAction(action, version);
}
+}
- submit(callVCAction) {
- const action = actionsEnum.SUBMIT;
- callVCAction(action);
+class ActionButtons extends React.Component {
+ static propTypes = {
+ version: React.PropTypes.object,
+ onSubmit: React.PropTypes.func,
+ onRevert: React.PropTypes.func,
+ onSave: React.PropTypes.func,
+ isLatestVersion: React.PropTypes.bool,
+ isCheckedIn: React.PropTypes.bool,
+ isCheckedOut: React.PropTypes.bool,
+ isFormDataValid: React.PropTypes.bool
+ };
+ render() {
+ const {onSubmit, onRevert, onSave, isLatestVersion, isCheckedIn, isCheckedOut, isFormDataValid, version, status, onCheckinCheckout} = this.props;
+ const [checkinBtnIconSvg, checkinCheckoutBtnTitle] = status === statusEnum.CHECK_OUT_STATUS ?
+ ['version-controller-lock-open', i18n('Check In')] :
+ ['version-controller-lock-closed', i18n('Check Out')];
+ const disabled = (isLatestVersion && onCheckinCheckout && status !== statusEnum.LOCK_STATUS) ? false : true;
+ return (
+ <div className='action-buttons'>
+ <VCButton dataTestId='vc-checkout-btn' onClick={onCheckinCheckout} isDisabled={disabled}
+ name={checkinBtnIconSvg} tooltipText={checkinCheckoutBtnTitle}/>
+ {onSubmit && onRevert &&
+ <div className='version-control-buttons'>
+ <VCButton dataTestId='vc-submit-btn' onClick={onSubmit} isDisabled={!isCheckedIn || !isLatestVersion}
+ name='version-controller-submit' tooltipText={i18n('Submit')}/>
+ <VCButton dataTestId='vc-revert-btn' onClick={onRevert} isDisabled={!isCheckedOut || version.label === '0.1' || !isLatestVersion}
+ name='version-controller-revert' tooltipText={i18n('Revert')}/>
+ </div>
+ }
+ {onSave &&
+ <VCButton dataTestId='vc-save-btn' onClick={() => onSave()} isDisabled={!isCheckedOut || !isFormDataValid || !isLatestVersion}
+ name='version-controller-save' tooltipText={i18n('Save')}/>
+ }
+ </div>
+ );
}
+}
- revertCheckout(callVCAction) {
- const action = actionsEnum.UNDO_CHECK_OUT;
- callVCAction(action);
- }
+function StatusBarUpdates({status}) {
+ return (
+ <div className='vc-status'>
+ <span className='status-text'>{i18n(statusBarTextMap[status])}</span>
+ </div>
+ );
+}
+
+function VCButton({name, tooltipText, isDisabled, onClick, dataTestId}) {
+ let onClickAction = isDisabled ? ()=>{} : onClick;
+ let disabled = isDisabled ? 'disabled' : '';
+
+ return (
+ <OverlayTrigger placement='top' overlay={<Tooltip id='vc-tooltip'>{tooltipText}</Tooltip>}>
+ <div disabled={disabled} className='action-buttons-svg'>
+ <SVGIcon data-test-id={dataTestId} iconClassName={disabled} onClick={onClickAction ? onClickAction : undefined} name={name}/>
+ </div>
+ </OverlayTrigger>
+ );
+}
+
+function VersionSelector(props) {
+ let {version = {}, viewableVersions = [], onVersionSwitching} = props;
+ const includedVersions = viewableVersions.filter(ver => {return ver.id === version.id;});
+ return (<div className='version-section-wrapper'>
+ <select className='version-selector'
+ onChange={ev => onVersionSwitching && onVersionSwitching({id: ev.target.value, label: ev.target.value})}
+ value={version.label}>
+ {viewableVersions && viewableVersions.map(viewVersion => {
+ return (
+ <option key={viewVersion.id} value={viewVersion.id} data-test-id='vc-version-option'>{`V ${viewVersion.label}`}</option>
+ );
+ })
+ }
+ {!includedVersions.length &&
+ <option key={version.id} value={version.id}>{`V ${version.label}`}</option>}
+ </select>
+ </div>);
}
export default VersionController;
diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js
index 9251fd12c4..9af142433c 100644
--- a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js
+++ b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionsEnum = keyMirror({
@@ -36,3 +31,11 @@ export const statusEnum = keyMirror({
PREVIOUS_VERSION: 'READ ONLY'
});
+export const statusBarTextMap = keyMirror({
+ 'Locked': 'Checked Out',
+ 'LockedByUser': '',
+ 'Available': 'Checked In',
+ 'Final': 'Submitted',
+ 'READ ONLY': 'Locked'
+});
+
diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js
index de9914454c..e8c12abec3 100644
--- a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js
+++ b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerUtils.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import Configuration from 'sdc-app/config/Configuration.js';
import {statusEnum} from './VersionControllerConstants.js';
@@ -25,24 +20,32 @@ import {statusEnum} from './VersionControllerConstants.js';
const VersionControllerUtils = {
getCheckOutStatusKindByUserID(status, lockingUser) {
- let currentLoginUserID = Configuration.get('ATTUserID');
- let isCheckedOut = currentLoginUserID === lockingUser;
+ let returnStatus;
+ let isCheckedOut;
+ let currentLoginUserID = Configuration.get('UserID');
+ if (lockingUser) {
+ isCheckedOut = currentLoginUserID === lockingUser;
+ returnStatus = isCheckedOut ? status : statusEnum.LOCK_STATUS;
+ } else {
+ isCheckedOut = false;
+ returnStatus = status;
+ }
return {
- status: isCheckedOut ? status : statusEnum.LOCK_STATUS,
+ status: returnStatus,
isCheckedOut
};
},
isCheckedOutByCurrentUser(resource) {
- let currentLoginUserID = Configuration.get('ATTUserID');
+ let currentLoginUserID = Configuration.get('UserID');
return resource.lockingUser !== undefined && resource.lockingUser === currentLoginUserID;
},
isReadOnly(resource) {
const {version, viewableVersions = []} = resource;
const latestVersion = viewableVersions[viewableVersions.length - 1];
- return version !== latestVersion || !VersionControllerUtils.isCheckedOutByCurrentUser(resource);
+ return version.id !== latestVersion.id || !VersionControllerUtils.isCheckedOutByCurrentUser(resource);
}
};
diff --git a/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx b/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx
index d786aeef8b..40720c39f4 100644
--- a/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx
+++ b/openecomp-ui/src/nfvo-components/progressBar/ProgressBar.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
class ProgressBar extends React.Component {
diff --git a/openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx b/openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx
new file mode 100644
index 0000000000..06cb98bbe8
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx
@@ -0,0 +1,29 @@
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import uuid from 'uuid-js';
+
+export default class SelectActionTable extends React.Component {
+
+ render() {
+ let {columns, onAdd, isReadOnlyMode, children, onAddItem} = this.props;
+ return (
+ <div className={`select-action-table-view ${isReadOnlyMode ? 'disabled' : ''}`}>
+ <div className='select-action-table-controllers'>
+ {onAdd && onAddItem && <div data-test-id='select-action-table-add' onClick={onAdd}>{onAddItem}</div>}
+ <SVGIcon name='trash-o' className='dummy-icon' />
+ </div>
+ <div className='select-action-table'>
+ <div className='select-action-table-headers'>
+ {columns.map(column => <div key={uuid.create()} className='select-action-table-header'>{i18n(column)}</div>)}
+ <SVGIcon name='trash-o' className='dummy-icon' />
+ <SVGIcon name='trash-o' className='dummy-icon' />
+ </div>
+ <div className='select-action-table-body'>
+ {children}
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/openecomp-ui/src/nfvo-components/table/SelectActionTableCell.jsx b/openecomp-ui/src/nfvo-components/table/SelectActionTableCell.jsx
new file mode 100644
index 0000000000..2664c8e944
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/table/SelectActionTableCell.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import SelectInput from 'nfvo-components/input/SelectInput.jsx';
+
+const SelectActionTableCell = ({options, selected, disabled, onChange, clearable = true, placeholder}) => {
+ return (
+ <div className='select-action-table-cell'>
+ <SelectInput
+ placeholder={placeholder}
+ type='select'
+ value={selected}
+ data-test-id='select-action-table-dropdown'
+ disabled={disabled}
+ onChange={option => onChange(option ? option.value : null)}
+ clearable={clearable}
+ options={options} />
+ </div>
+ );
+};
+
+export default SelectActionTableCell;
diff --git a/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx b/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx
new file mode 100644
index 0000000000..17d8a17c09
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import SVGIcon from '../icon/SVGIcon.jsx';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+
+function tooltip (msg) {
+ return (
+ <Tooltip className='select-action-table-error-tooltip' id='error-tooltip'>{msg}</Tooltip>
+ );
+};
+
+const IconWithOverlay = ({overlayMsg}) => (
+ <OverlayTrigger placement='bottom' overlay={tooltip(overlayMsg)}>
+ <SVGIcon name='error-circle'/>
+ </OverlayTrigger>
+);
+
+const SelectActionTableRow = ({children, onDelete, hasError, overlayMsg}) => (
+ <div className='select-action-table-row-wrapper'>
+ <div className={`select-action-table-row ${hasError ? 'has-error' : ''}`}>
+ {children}
+ </div>
+ {onDelete ? <SVGIcon name='trash-o' data-test-id='select-action-table-delete' onClick={onDelete} /> : <SVGIcon name='angle-left' className='dummy-icon' />}
+ {hasError ? overlayMsg ? <IconWithOverlay overlayMsg={overlayMsg}/> : <SVGIcon name='error-circle'/>
+ : hasError === undefined ? <SVGIcon name='angle-left' className='dummy-icon'/> : <SVGIcon name='check-circle'/>}
+
+ </div>
+);
+
+export default SelectActionTableRow;
diff --git a/openecomp-ui/src/nfvo-utils/DirectedGraph.js b/openecomp-ui/src/nfvo-utils/DirectedGraph.js
new file mode 100644
index 0000000000..197625a013
--- /dev/null
+++ b/openecomp-ui/src/nfvo-utils/DirectedGraph.js
@@ -0,0 +1,45 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+export default class Graph {
+ constructor() {
+ this.nodes = {};
+ }
+
+ addNode(node) {
+ this.nodes[node] = [];
+ }
+
+ hasNode(node) {
+ return this.nodes.hasOwnProperty(node);
+ }
+
+ addEdge(firstNode, secondNode, payload) {
+ if (!this.hasNode(firstNode)) {
+ this.addNode(firstNode);
+ }
+
+ if (!this.hasNode(secondNode)) {
+ this.addNode(secondNode);
+ }
+
+ this.nodes[firstNode].push({...payload, target: secondNode});
+ }
+
+ getEdges(node) {
+ return this.nodes[node];
+ }
+} \ No newline at end of file
diff --git a/openecomp-ui/src/nfvo-utils/ErrorResponseHandler.js b/openecomp-ui/src/nfvo-utils/ErrorResponseHandler.js
index 0d27204bef..d58a2454b6 100644
--- a/openecomp-ui/src/nfvo-utils/ErrorResponseHandler.js
+++ b/openecomp-ui/src/nfvo-utils/ErrorResponseHandler.js
@@ -1,25 +1,23 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import store from 'sdc-app/AppStore.js';
-import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js';
+import React from 'react';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SubmitErrorResponse from 'nfvo-components/SubmitErrorResponse.jsx';
function showVariablesInMessage(variables, msg) {
let regex;
@@ -45,6 +43,10 @@ function parseATTExceptionObject(responseJSON) {
msg = showVariablesInMessage(variables, msg);
}
}
+ else if (responseJSON.uploadDataErrors) {
+ title = i18n('Error: Upload Data Error');
+ msg = (<SubmitErrorResponse validationResponse={{uploadDataErrors: responseJSON.uploadDataErrors}} />);
+ }
else {
title = responseJSON.status;
msg = responseJSON.message;
@@ -60,12 +62,14 @@ var errorResponseHandler = (xhr/*, textStatus, errorThrown*/) => {
else {
errorData = {
title: xhr.statusText,
- msg: xhr.responseText
+ msg: xhr.responseText,
};
}
store.dispatch({
- type: NotificationConstants.NOTIFY_ERROR,
- data: {...errorData}
+ type: modalActionTypes.GLOBAL_MODAL_ERROR,
+ data: {
+ ...errorData
+ }
});
};
diff --git a/openecomp-ui/src/nfvo-utils/KeyMirror.js b/openecomp-ui/src/nfvo-utils/KeyMirror.js
index eb50d31e07..220fe07430 100644
--- a/openecomp-ui/src/nfvo-utils/KeyMirror.js
+++ b/openecomp-ui/src/nfvo-utils/KeyMirror.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
var keyMirror = function (obj) {
var ret = {};
var key;
@@ -41,4 +36,4 @@ var keyMirror = function (obj) {
return Object.freeze(ret);
};
-export default keyMirror;
+export default keyMirror; \ No newline at end of file
diff --git a/openecomp-ui/src/nfvo-utils/RestAPIUtil.js b/openecomp-ui/src/nfvo-utils/RestAPIUtil.js
index 24734739a2..c878c9e673 100644
--- a/openecomp-ui/src/nfvo-utils/RestAPIUtil.js
+++ b/openecomp-ui/src/nfvo-utils/RestAPIUtil.js
@@ -1,27 +1,19 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import _extend from 'lodash/extend.js';
-import _clone from 'lodash/clone.js';
-import _defaults from 'lodash/defaults.js';
-import $ from 'jquery';
+import {RestfulAPI} from 'restful-js';
import uuid from 'uuid-js';
import md5 from 'md5';
@@ -30,30 +22,81 @@ import {actionTypes as LoaderConstants} from 'nfvo-components/loader/LoaderConst
import Configuration from 'sdc-app/config/Configuration.js';
import errorResponseHandler from './ErrorResponseHandler.js';
-const methodMap = {
- 'create': 'POST',
- 'update': 'PUT',
- 'delete': 'DELETE',
- 'read': 'GET'
-};
const AUTHORIZATION_HEADER = 'X-AUTH-TOKEN';
const STORAGE_AUTH_KEY = 'sdc-auth-token';
const REQUEST_ID_HEADER = 'X-ECOMP-RequestID';
const CONTENT_MD5_HEADER = 'Content-MD5';
-const namedParam = /{(\w+)}/g;
-const queryParamsNames = {
- pageStart: 'pageStart',
- pageSize: 'pageSize',
- sortField: 'sortField',
- sortDir: 'sortDir',
- filtering: 'filter'
-};
+
+
+function applyMD5Header(options, data) {
+ if (options.md5) {
+ let headers = options.headers;
+ headers[CONTENT_MD5_HEADER] = window.btoa(md5(JSON.stringify(data)).toLowerCase());
+ }
+}
+
+function handleResponse(xhr) {
+ let authToken = xhr.getResponseHeader(AUTHORIZATION_HEADER);
+ let prevToken = this && this.headers && this.headers[AUTHORIZATION_HEADER];
+ if (authToken && authToken !== prevToken) {
+ if (authToken === 'null') {
+ localStorage.removeItem(STORAGE_AUTH_KEY);
+ } else {
+ localStorage.setItem(STORAGE_AUTH_KEY, authToken);
+ }
+ }
+}
+
+
+class RestAPIUtil extends RestfulAPI {
+
+ applySecurity(options, data) {
+ let headers = options.headers || (options.headers = {});
+
+ let authToken = localStorage.getItem(STORAGE_AUTH_KEY);
+ if (authToken) {
+ headers[AUTHORIZATION_HEADER] = authToken;
+ }
+
+ let attApiHeaders = Configuration.get('ATTApiHeaders'),
+ attUidHeader = attApiHeaders && attApiHeaders.userId;
+ if (attUidHeader) {
+ headers[attUidHeader.name] = attUidHeader.value;
+ }
+
+ headers[REQUEST_ID_HEADER] = uuid.create().toString();
+ applyMD5Header(options, data);
+ }
+
+ handleRequest(url, type, options = {}, data){
+ let success = options.success;
+ options.success = function (resp, textStatus, xhr) {
+ handleResponse.call(this, xhr);
+ if (success) {
+ success.call(options.context, {...resp}, textStatus, xhr);
+ }
+ };
+
+ if (DEBUG) {
+ console.log('--> Making REST call (' + type + '): ' + url);
+ }
+ return super.handleRequest(url, type, options, data);
+ }
+
+}
+
+const instance = new RestAPIUtil({
+ errorResponseHandler,
+ ajaxStartHandler: () => store.dispatch({type: LoaderConstants.SHOW}),
+ ajaxStopHandler: () => store.dispatch({type: LoaderConstants.HIDE})
+});
+
// jQuery binary transport to download files through XHR
// http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/
// https://github.com/henrya/js-jquery/tree/master/BinaryTransport
-$.ajaxTransport('+binary', function (options/*, originalOptions , jqXHR*/) {
+instance.$.ajaxTransport('+binary', function (options/*, originalOptions , jqXHR*/) {
// check for conditions and support for blob / arraybuffer response type
if (window.FormData && ((options.dataType && (options.dataType === 'binary')) ||
(options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) ||
@@ -62,19 +105,19 @@ $.ajaxTransport('+binary', function (options/*, originalOptions , jqXHR*/) {
return {
// create new XMLHttpRequest
send: function (headers, callback) {
- // setup all variables
- var xhr = new XMLHttpRequest(),
+ // setup all letiables
+ let xhr = new XMLHttpRequest(),
url = options.url,
type = options.type,
async = options.async || true,
- // blob or arraybuffer. Default is blob
+ // blob or arraybuffer. Default is blob
dataType = options.responseType || 'blob',
data = options.data || null,
username = options.username || null,
password = options.password || null;
xhr.addEventListener('load', function () {
- var data = {};
+ let data = {};
data[options.dataType] = xhr.response;
// make callback and send data
callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
@@ -83,7 +126,7 @@ $.ajaxTransport('+binary', function (options/*, originalOptions , jqXHR*/) {
xhr.open(type, url, async, username, password);
// setup custom headers
- for (var i in headers) {
+ for (let i in headers) {
xhr.setRequestHeader(i, headers[i]);
}
@@ -96,193 +139,4 @@ $.ajaxTransport('+binary', function (options/*, originalOptions , jqXHR*/) {
}
});
-$(document).ajaxStart(()=> store.dispatch({type: LoaderConstants.SHOW}));
-$(document).ajaxStop(()=> store.dispatch({type: LoaderConstants.HIDE}));
-
-function urlError() {
- throw new Error('A "url" property or function must be specified');
-};
-
-export function makeQueryParams(options) {
- var qParams = {};
- if (options.pagination) {
- qParams[queryParamsNames.pageStart] = options.pagination.pageStart;
- qParams[queryParamsNames.pageSize] = options.pagination.pageSize;
- }
- if (options.sorting) {
- qParams[queryParamsNames.sortField] = options.sorting.sortField;
- qParams[queryParamsNames.sortDir] = options.sorting.sortDir;
- }
- if (options.filtering) {
- qParams[queryParamsNames.filtering] = JSON.stringify(options.filtering);
- }
-
- return _defaults(qParams, options.qParams);
-}
-
-function appendQueryParam(p, value) {
- var str = '';
-
- if (value instanceof Array) {
- if (value.length === 1) {
- str = appendQueryParam(p, value[0]);
- } else if (value.length > 1) {
- str = appendQueryParam(p, value.shift()) + '&' + appendQueryParam(p, value);
- }
- } else {
- str = p + '=' + encodeURIComponent(value);
- }
-
- return str;
-}
-
-function appendQueryString(url, qParams) {
- var str = '';
- for (var param in qParams) {
- str += (str ? '&' : '') + appendQueryParam(param, qParams[param]);
- }
- return url + (str ? '?' : '') + str;
-}
-
-function composeURL(baseUrl, options) {
- var url = baseUrl || urlError();
- if (options.url) {
- delete options.url;
- }
-
- var qParams = makeQueryParams(options);
- url = appendQueryString(url, qParams);
-
- var matches = url.match(namedParam);
- if (matches) {
- for (var i = 0; i < matches.length; i++) {
- var param = matches[i].substring(1, matches[i].length - 1);
- var value = (options.params && options.params[param]);
-
- if (value === undefined) {
- value = options[param];
- }
- url = url.replace(matches[i], encodeURIComponent(value));
- }
- }
-
- return url;
-}
-
-function applyMD5Header(options, data) {
- if (options.md5) {
- let headers = options.headers;
- headers[CONTENT_MD5_HEADER] = window.btoa(md5(JSON.stringify(data)).toLowerCase());
- }
-}
-
-function applySecurity(options, data) {
- var headers = options.headers || (options.headers = {});
-
- var authToken = localStorage.getItem(STORAGE_AUTH_KEY);
- if (authToken) {
- headers[AUTHORIZATION_HEADER] = authToken;
- }
-
- var attApiHeaders = Configuration.get('ATTApiHeaders'),
- attUidHeader = attApiHeaders && attApiHeaders.userId;
- if (attUidHeader) {
- headers[attUidHeader.name] = attUidHeader.value;
- }
-
- headers[REQUEST_ID_HEADER] = uuid.create().toString();
-
- applyMD5Header(options, data);
-}
-
-function handleResponse(options) {
- var authToken = options.xhr.getResponseHeader(AUTHORIZATION_HEADER);
- var prevToken = options.headers && options.headers[AUTHORIZATION_HEADER];
- if (authToken && authToken !== prevToken) {
- if (authToken === 'null') {
- localStorage.removeItem(STORAGE_AUTH_KEY);
- } else {
- localStorage.setItem(STORAGE_AUTH_KEY, authToken);
- }
- }
-}
-
-function sync(baseUrl, method, options, data) {
-
- options = options ? _clone(options) : {};
-
- var type = methodMap[method];
- _defaults(options || (options = {}));
- var params = {
- type: type,
- dataType: 'json'
- };
- params.url = composeURL(baseUrl, options);
-
- if ((method === 'create' || method === 'update') && data instanceof FormData) {
- params.contentType = 'multipart/form-data';
- params.data = data;
- }
- else if (method === 'create' || method === 'update') {
- params.contentType = 'application/json';
- params.data = JSON.stringify(data);
- }
-
- if (params.type !== 'GET') {
- params.processData = false;
- }
- var success = options.success;
- options.success = function (resp) {
- if (success) {
- handleResponse(options);
- success.call(options.context, _clone(resp), resp, options);
- }
- };
-
- options.error = options.error || errorResponseHandler;
-
- if (typeof options.progressCallback === 'function' && options.fileSize) {
- const {fileSize} = options;
- options.xhrFields = {
- // add listener to XMLHTTPRequest object directly for progress (jquery doesn't have this yet)
- onprogress: function (progress) {
- // calculate upload progress
- let percentage = Math.floor((progress.loaded / fileSize) * 100);
- // log upload progress to console
- //console.log('progress', percentage);
- options.progressCallback(percentage);
- if (percentage === 100) {
- console.log('DONE!');
- }
- }
- };
- }
-
- applySecurity(options, data);
-
- if (DEBUG) {
- console.log('--> Making REST call (' + type + '): ' + params.url);
- }
- var xhr = options.xhr = $.ajax(_extend(params, options));
- return xhr;
-}
-
-export default {
-
- fetch(baseUrl, options) {
- return sync(baseUrl, 'read', options);
- },
-
- save(baseUrl, data, options) {
- return sync(baseUrl, 'update', options, data);
- },
-
- create(baseUrl, data, options) {
- return sync(baseUrl, 'create', options, data);
- },
-
- destroy(baseUrl, options) {
- return sync(baseUrl, 'delete', options);
- }
-
-};
+export default instance;
diff --git a/openecomp-ui/src/nfvo-utils/UUID.js b/openecomp-ui/src/nfvo-utils/UUID.js
index 314c98ba6f..e1d4c54b1f 100644
--- a/openecomp-ui/src/nfvo-utils/UUID.js
+++ b/openecomp-ui/src/nfvo-utils/UUID.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import UUID from 'uuid-js';
let toCustomUUID = (uuid) => {
diff --git a/openecomp-ui/src/nfvo-utils/Validator.js b/openecomp-ui/src/nfvo-utils/Validator.js
new file mode 100644
index 0000000000..708179e9fb
--- /dev/null
+++ b/openecomp-ui/src/nfvo-utils/Validator.js
@@ -0,0 +1,110 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import * as ValidatorJS from 'validator';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+class Validator {
+ static get globalValidationFunctions() {
+ return {
+ required: value => value !== '',
+ maxLength: (value, length) => ValidatorJS.isLength(value, {max: length}),
+ minLength: (value, length) => ValidatorJS.isLength(value, {min: length}),
+ pattern: (value, pattern) => ValidatorJS.matches(value, pattern),
+ numeric: value => {
+ if (value === '') {
+ // to allow empty value which is not zero
+ return true;
+ }
+ return ValidatorJS.isNumeric(value);
+ },
+ maximum: (value, maxValue) => value <= maxValue,
+ minimum: (value, minValue) => value >= minValue,
+ maximumExclusive: (value, maxValue) => value < maxValue,
+ minimumExclusive: (value, minValue) => value > minValue,
+ alphanumeric: value => ValidatorJS.isAlphanumeric(value),
+ alphanumericWithSpaces: value => ValidatorJS.isAlphanumeric(value.replace(/ /g, '')),
+ validateName: value => ValidatorJS.isAlphanumeric(value.replace(/\s|\.|\_|\-/g, ''), 'en-US'),
+ validateVendorName: value => ValidatorJS.isAlphanumeric(value.replace(/[\x7F-\xFF]|\s/g, ''), 'en-US'),
+ freeEnglishText: value => ValidatorJS.isAlphanumeric(value.replace(/\s|\.|\_|\-|\,|\(|\)|\?/g, ''), 'en-US'),
+ email: value => ValidatorJS.isEmail(value),
+ ip: value => ValidatorJS.isIP(value),
+ url: value => ValidatorJS.isURL(value)
+ };
+ }
+
+ static get globalValidationMessagingFunctions() {
+ return {
+ required: () => i18n('Field is required'),
+ maxLength: (value, maxLength) => i18n('Field value has exceeded it\'s limit, {maxLength}. current length: {length}', {
+ length: value.length,
+ maxLength
+ }),
+ minLength: (value, minLength) => i18n('Field value should contain at least {minLength} characters.', {minLength}),
+ pattern: (value, pattern) => i18n('Field value should match the pattern: {pattern}.', {pattern}),
+ numeric: () => i18n('Field value should contain numbers only.'),
+ maximum: (value, maxValue) => i18n('Field value should be less or equal to: {maxValue}.', {maxValue}),
+ minimum: (value, minValue) => i18n('Field value should be at least: {minValue}.', {minValue: minValue.toString()}),
+ maximumExclusive: (value, maxValue) => i18n('Field value should be less than: {maxValue}.', {maxValue}),
+ minimumExclusive: (value, minValue) => i18n('Field value should be more than: {minValue}.', {minValue: minValue.toString()}),
+ alphanumeric: () => i18n('Field value should contain letters or digits only.'),
+ alphanumericWithSpaces: () => i18n('Field value should contain letters, digits or spaces only.'),
+ validateName: ()=> i18n('Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'),
+ validateVendorName: ()=> i18n('Field value should contain English letters digits and spaces only.'),
+ freeEnglishText: ()=> i18n('Field value should contain English letters, digits , spaces, underscores, dashes and dots only.'),
+ email: () => i18n('Field value should be a valid email address.'),
+ ip: () => i18n('Field value should be a valid ip address.'),
+ url: () => i18n('Field value should be a valid url address.'),
+ general: () => i18n('Field value is invalid.')
+ };
+ }
+
+ static validateItem(value, data, type) {
+ let validationFunc = this.globalValidationFunctions[type];
+ const isValid = validationFunc(value, data);
+ let errorText = '';
+ if (!isValid) {
+ errorText = this.globalValidationMessagingFunctions[type](value, data);
+ }
+ return {
+ isValid,
+ errorText
+ };
+ }
+
+ static validate(fieldName, value, validations, state, customValidations) {
+ let result = { isValid: true, errorText: '' };
+ for (let validation of validations) {
+ result = this.validateItem(value, validation.data, validation.type);
+ if (!result.isValid) {
+ return result;
+ }
+ }
+ if (customValidations) {
+ let validationFunc = customValidations[fieldName];
+ if (validationFunc) {
+ result = validationFunc(value, state);
+ }
+ }
+ return result;
+ }
+
+ static isItemNameAlreadyExistsInList({itemId, itemName, list}) {
+ return list[itemName] && list[itemName] !== itemId;
+ }
+}
+
+export default Validator;
diff --git a/openecomp-ui/src/nfvo-utils/i18n/i18n.js b/openecomp-ui/src/nfvo-utils/i18n/i18n.js
index 64587713b7..4d03ddb8dd 100644
--- a/openecomp-ui/src/nfvo-utils/i18n/i18n.js
+++ b/openecomp-ui/src/nfvo-utils/i18n/i18n.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import IntlObj from 'intl';
import IntlMessageFormatObj from 'intl-messageformat';
import IntlRelativeFormatObj from 'intl-relativeformat';
diff --git a/openecomp-ui/src/nfvo-utils/json/JSONPointer.js b/openecomp-ui/src/nfvo-utils/json/JSONPointer.js
index a6e8198537..f4c0d4ed59 100644
--- a/openecomp-ui/src/nfvo-utils/json/JSONPointer.js
+++ b/openecomp-ui/src/nfvo-utils/json/JSONPointer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
const JSONPointer = {
extractParentPointer(pointer) {
@@ -29,7 +24,7 @@ const JSONPointer = {
return lastPart;
},
- extractParts(pointer) {
+ extractParts(pointer = '') {
return pointer.split('/').slice(1)
.map(part => part.replace(/~1/g, '/'))
.map(part => part.replace(/~0/g, '~'));
diff --git a/openecomp-ui/src/nfvo-utils/json/JSONSchema.js b/openecomp-ui/src/nfvo-utils/json/JSONSchema.js
index 8c7d8cf9aa..3b3a9bf7b4 100644
--- a/openecomp-ui/src/nfvo-utils/json/JSONSchema.js
+++ b/openecomp-ui/src/nfvo-utils/json/JSONSchema.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
// import Ajv from 'ajv';
import cloneDeep from 'lodash/cloneDeep.js';
import JSONPointer from './JSONPointer.js';
@@ -40,6 +35,108 @@ export default class JSONSchema {
return data;
}
+ // array of names of validation functions
+ setSupportedValidationFunctions(supportedValidationFunctions) {
+ this._supportedValidationFunctions = supportedValidationFunctions;
+ }
+
+ /* FYI - I was going to support "required" but then found out that server never sends it in its schema (it was a business decision. so leaving the code commented for now */
+ flattenSchema(supportedValidationFunctions) {
+ if (supportedValidationFunctions) { this.setSupportedValidationFunctions(supportedValidationFunctions); }
+ let genericFieldInfo = {};
+ if (this._schema && this._schema.properties) {
+ this.travelProperties(this._schema.properties, genericFieldInfo/*, this._schema.required*/);
+ }
+ return {genericFieldInfo};
+ }
+
+ extractGenericFieldInfo(item) {
+ let validationsArr = [];
+ let additionalInfo = { isValid: true, errorText: ''};
+ for (let value in item) {
+ if (this._supportedValidationFunctions.includes(value)) {
+ let validationItem = this.extractValidations(item, value);
+ validationsArr[validationsArr.length] = validationItem;
+ } else {
+ let enumResult = this.extractEnum(item, value);
+ if (enumResult !== null) {
+ additionalInfo.enum = enumResult;
+ }
+ else {
+ additionalInfo[value] = item[value];
+ }
+ /*if (required.includes (property)) {
+ additionalInfo[value].isRequired = true ;
+ }*/
+ }
+ }
+
+ additionalInfo.validations = validationsArr;
+ return additionalInfo;
+ }
+
+ extractValidations(item, value) {
+ let validationItem;
+ let data = item[value];
+ if (value === 'maximum') {
+ if (item.exclusiveMaximum) {
+ value = 'maximumExclusive';
+ }
+ }
+ if (value === 'minimum') {
+ if (item.exclusiveMinimum) {
+ value = 'minimumExclusive';
+ }
+ }
+ validationItem = {type: value, data: data};
+ return validationItem;
+ }
+
+ extractEnum(item, value) {
+ let enumResult = null;
+ if (value === 'type' && item[value] === 'array') {
+ let items = item.items;
+ if (items && items.enum && items.enum.length > 0) {
+ let values = items.enum
+ .filter(value => value)
+ .map(value => ({enum: value, title: value}));
+ enumResult = values;
+ }
+ }
+ else if (value === 'enum') {
+ let items = item[value];
+ if (items && items.length > 0) {
+ let values = items
+ .filter(value => value)
+ .map(value => ({enum: value, title: value}));
+ enumResult = values;
+ }
+ }
+ return enumResult;
+ }
+
+ travelProperties(properties, genericFieldDefs, /*required = [],*/ pointer = ''){
+ let newPointer = pointer;
+ for (let property in properties) {
+ newPointer = newPointer ? newPointer + '/' + property : property;
+ if (properties[property].properties) {
+ this.travelProperties(properties[property].properties, genericFieldDefs /*, properties[property].required*/, newPointer);
+ }
+ else if (properties[property].$ref){
+ let fragment = this._getSchemaFragmentByRef(properties[property].$ref);
+ if (fragment.properties) {
+ this.travelProperties(fragment.properties, genericFieldDefs /*, properties[property].required*/, newPointer);
+ } else {
+ genericFieldDefs[newPointer] = this.extractGenericFieldInfo(fragment.properties);
+ }
+ }
+ else {
+ genericFieldDefs[newPointer] = this.extractGenericFieldInfo(properties[property]);
+ }
+ newPointer = pointer;
+ }
+ }
+
getTitle(pointer) {
return this._getSchemaFragment(pointer).title;
}
@@ -73,12 +170,12 @@ export default class JSONSchema {
getMaxValue(pointer) {
const fragment = this._getSchemaFragment(pointer);
- return fragment && fragment.maximum;
+ return fragment && fragment.exclusiveMaximum ? fragment.maximum - 1 : fragment.maximum;
}
getMinValue(pointer) {
const fragment = this._getSchemaFragment(pointer);
- return fragment && fragment.minimum;
+ return fragment && fragment.exclusiveMinimum ? fragment.minimum : fragment.minimum;
}
isString(pointer) {
diff --git a/openecomp-ui/src/nfvo-utils/sortByStringProperty.js b/openecomp-ui/src/nfvo-utils/sortByStringProperty.js
new file mode 100644
index 0000000000..b415dd7e07
--- /dev/null
+++ b/openecomp-ui/src/nfvo-utils/sortByStringProperty.js
@@ -0,0 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+export default function sortByStringProperty(array, property) {
+ return [...array].sort((a, b) => a[property].toLowerCase().localeCompare(b[property].toLowerCase()));
+}
diff --git a/openecomp-ui/src/sdc-app/AppStore.js b/openecomp-ui/src/sdc-app/AppStore.js
index 0abcaac3fe..9157c340a3 100644
--- a/openecomp-ui/src/sdc-app/AppStore.js
+++ b/openecomp-ui/src/sdc-app/AppStore.js
@@ -1,46 +1,41 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-import {combineReducers, createStore} from 'redux';
+import {combineReducers, createStore, applyMiddleware, compose} from 'redux';
import onBoardingReducersMap from './onboarding/OnboardingReducersMap.js';
import flowsReducersMap from './flows/FlowsReducersMap.js';
-import notificationReducer from 'nfvo-components/notifications/NotificationReducer.js';
import loaderReducer from 'nfvo-components/loader/LoaderReducer.js';
-import uploadScreenReducer from 'sdc-app/heatvalidation/UploadScreenReducer.js';
-import SoftwareProductAttachmentsReducer from 'sdc-app/heatvalidation/attachments/AttachmentsReducer';
+import globalModalReducer from 'nfvo-components/modal/GlobalModalReducer.js';
+const thunk = store => next => action =>
+ typeof action === 'function' ?
+ action(store.dispatch, store.getState) :
+ next(action);
+
+const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export const storeCreator = (initialState) => createStore(combineReducers({
// on-boarding reducers
...onBoardingReducersMap,
// flows reducers
...flowsReducersMap,
-
- // heat validation stand-alone app
- uploadScreen: combineReducers({
- upload: uploadScreenReducer,
- attachments: SoftwareProductAttachmentsReducer
- }),
- notification: notificationReducer,
+ modal: globalModalReducer,
loader: loaderReducer
-}), initialState, window.devToolsExtension ? window.devToolsExtension() : undefined);
+}), initialState, composeEnhancers(applyMiddleware(thunk)));
+
const store = storeCreator();
diff --git a/openecomp-ui/src/sdc-app/Application.jsx b/openecomp-ui/src/sdc-app/Application.jsx
index 5cb385b61c..10e866a602 100644
--- a/openecomp-ui/src/sdc-app/Application.jsx
+++ b/openecomp-ui/src/sdc-app/Application.jsx
@@ -1,6 +1,21 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import {Provider} from 'react-redux';
-import NotificationModal from 'nfvo-components/notifications/NotificationModal.jsx';
+import GlobalModal from 'nfvo-components/modal/GlobalModal.js';
import Loader from 'nfvo-components/loader/Loader.jsx';
import store from './AppStore.js';
@@ -10,7 +25,7 @@ class Application extends React.Component {
return (
<Provider store={store}>
<div>
- <NotificationModal />
+ <GlobalModal/>
{this.props.children}
<Loader />
</div>
diff --git a/openecomp-ui/src/sdc-app/ModulesOptions.jsx b/openecomp-ui/src/sdc-app/ModulesOptions.jsx
index 4f66e579d1..61d19d9e7a 100644
--- a/openecomp-ui/src/sdc-app/ModulesOptions.jsx
+++ b/openecomp-ui/src/sdc-app/ModulesOptions.jsx
@@ -1,6 +1,21 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import {connect} from 'react-redux';
-import Input from 'react-bootstrap/lib/Input.js';
+import Input from 'nfvo-components/input/validation/InputWrapper.jsx';
import LicenseModelActionHelper from './onboarding/licenseModel/LicenseModelActionHelper.js';
import LicenseAgreementListEditor from './onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js';
@@ -13,7 +28,7 @@ import EntitlementPoolsListEditor from './onboarding/licenseModel/entitlementPoo
import EntitlementPoolsActionHelper from './onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js';
import SoftwareProductLandingPage from './onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js';
import SoftwareProductDetails from './onboarding/softwareProduct/details/SoftwareProductDetails.js';
-import OnboardingCatalog from './onboarding/OnboardingCatalog.js';
+import Onboard from './onboarding/onboard/Onboard.js';
import SoftwareProductActionHelper from './onboarding/softwareProduct/SoftwareProductActionHelper.js';
import FlowsListEditor from './flows/FlowsListEditor.js';
import FlowsActions from './flows/FlowsActions.js';
@@ -125,7 +140,7 @@ class ModuleOptions extends React.Component {
return <SoftwareProductDetails licenseModelId={licenseModelId}/>;
case 'OnboardingCatalog':
this.props.onOnboardingCatalog();
- return <OnboardingCatalog/>;
+ return <Onboard/>;
case 'Flows':
this.props.onFlowsListEditor();
return <FlowsListEditor/>;
diff --git a/openecomp-ui/src/sdc-app/Test.jsx b/openecomp-ui/src/sdc-app/Test.jsx
deleted file mode 100644
index dd45e39eca..0000000000
--- a/openecomp-ui/src/sdc-app/Test.jsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import React from 'react';
-import Tabs from 'react-bootstrap/lib/Tabs.js';
-import Tab from 'react-bootstrap/lib/Tab.js';
-import Button from 'react-bootstrap/lib/Button.js';
-import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
-import DropdownButton from 'react-bootstrap/lib/DropdownButton.js';
-import MenuItem from 'react-bootstrap/lib/MenuItem.js';
-
-import Modal from 'nfvo-components/modal/Modal.jsx';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
-import ToggleInput from 'nfvo-components/input/ToggleInput.jsx';
-
-export default class Test extends React.Component {
-
- render() {
- return (
- <div>
- <Tabs defaultActiveKey={2}>
- <Tab eventKey={1} title='Tab 1'>Tab 1 content</Tab>
- <Tab eventKey={2} title='Tab 2'>Tab 2 content</Tab>
- <Tab eventKey={3} title='Tab 3' disabled>Tab 3 content</Tab>
- </Tabs>
- <div style={{marginTop: 20, marginBottom: 20}}></div>
- <Button>Default</Button>
- <span style={{marginLeft: 20}}></span>
- <Button bsStyle='primary'>Primary</Button>
- <span style={{marginLeft: 20}}></span>
- <Button bsStyle='success'>Success</Button>
- <span style={{marginLeft: 20}}></span>
- <Button bsStyle='info'>Info</Button>
- <span style={{marginLeft: 20}}></span>
- <Button bsStyle='warning'>Warning</Button>
- <span style={{marginLeft: 20}}></span>
- <Button bsStyle='danger'>Danger</Button>
- <span style={{marginLeft: 20}}></span>
- <Button bsStyle='link'>Link</Button>
- <div style={{marginTop: 20, marginBottom: 20}}></div>
- <ButtonGroup>
- <Button>Left</Button>
- <Button>Middle</Button>
- <Button>Right</Button>
- </ButtonGroup>
- <div style={{marginTop: 20, marginBottom: 20}}></div>
- <DropdownButton title='title' id='dropdown-basic'>
- <MenuItem eventKey='1'>Action</MenuItem>
- <MenuItem eventKey='2'>Another action</MenuItem>
- <MenuItem eventKey='3' active>Active Item</MenuItem>
- <MenuItem divider/>
- <MenuItem eventKey='4'>Separated link</MenuItem>
- </DropdownButton>
-
- <div style={{marginTop: 20, marginBottom: 20}}></div>
- <Modal show={false}>
- <Modal.Header closeButton>
- <Modal.Title>Modal title</Modal.Title>
- </Modal.Header>
-
- <Modal.Body>
- One fine body...
- </Modal.Body>
-
- <Modal.Footer>
- <Button>Close</Button>
- <Button bsStyle='primary'>Save changes</Button>
- </Modal.Footer>
-
- </Modal>
-
- <div style={{marginTop: 20, marginBottom: 20}}></div>
-
- <ValidationForm>
- <ValidationInput
- type='text'
- label='Required'
- placeholder='Enter text'
- validations={{required: true}}/>
- <ValidationInput
- type='text'
- label='Text'
- placeholder='Enter text'
- validations={{required: true, minLength:5}}/>
- <ValidationInput
- type='email'
- label='Email Address'
- placeholder='Enter email'
- validations={{required: true, email: true}}/>
- <ValidationInput type='password' label='Password'/>
- <ValidationInput type='file' label='File' help='[Optional] Block level help text'/>
- <ValidationInput type='checkbox' label='Checkbox2' name='ziv'/>
- <ValidationInput type='radio' label='Radio' name='zzz'/>
- <ValidationInput type='select' label='Select' placeholder='select'>
- <option value='select'>select</option>
- <option value='other'>...</option>
- </ValidationInput>
- <ValidationInput type='select' label='Multiple Select' multiple>
- <option value='select'>select (multiple)</option>
- <option value='other'>...</option>
- </ValidationInput>
- <ValidationInput type='textarea' label='Text Area' placeholder='textarea'/>
- <ToggleInput value={true}/>
- <ToggleInput />
- <ToggleInput label='ziv' value={true}/>
- <ToggleInput label='ziv'/>
- </ValidationForm>
- </div>
- );
- }
-
- doSomething(a) {
- if (a) {
- this.doSomething2();
- }
- else {
- return 1;
- }
- }
-
- doSomething2() {
- return 2;
- }
-}
diff --git a/openecomp-ui/src/sdc-app/common/helpers/ValidationHelper.js b/openecomp-ui/src/sdc-app/common/helpers/ValidationHelper.js
new file mode 100644
index 0000000000..51dfcf9a67
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/common/helpers/ValidationHelper.js
@@ -0,0 +1,91 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes as commonActionTypes} from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
+import {actionTypes as qcommonActionTypes} from 'sdc-app/common/reducers/JSONSchemaReducerConstants.js';
+
+class ValidationHelper {
+
+ static dataChanged(dispatch, {deltaData, formName, customValidations = {}}){
+ dispatch({
+ type: commonActionTypes.DATA_CHANGED,
+ deltaData,
+ formName,
+ customValidations
+ });
+ }
+
+ static validateForm(dispatch, formName){
+ dispatch({
+ type: commonActionTypes.VALIDATE_FORM,
+ formName
+ });
+ }
+
+ static validateData(dispatch, {formName, data}) {
+ dispatch({
+ type: commonActionTypes.VALIDATE_DATA,
+ formName,
+ data
+ });
+ }
+
+ static qValidateData(dispatch, {data, qName, customValidations = {}}) {
+ dispatch({
+ type: qcommonActionTypes.VALIDATE_DATA,
+ data,
+ qName,
+ customValidations
+ });
+ }
+
+ static qValidateForm(dispatch, qName){
+ dispatch({
+ type: qcommonActionTypes.VALIDATE_FORM,
+ qName
+ });
+ }
+
+ static qDataChanged(dispatch, {deltaData, qName, customValidations = {}}){
+ dispatch({
+ type: qcommonActionTypes.DATA_CHANGED,
+ deltaData,
+ qName,
+ customValidations
+ });
+ }
+
+ static qDataLoaded(dispatch, {qName, response: {qdata, qschema}}) {
+ dispatch({
+ type: qcommonActionTypes.DATA_LOADED,
+ payload: {
+ qdata,
+ qschema
+ },
+ qName
+ });
+ }
+
+ static checkFormValid(genericFieldInfo) {
+ for (let field in genericFieldInfo) {
+ if (!genericFieldInfo[field].isValid) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+export default ValidationHelper;
diff --git a/openecomp-ui/src/sdc-app/common/modal/ModalContentMapper.js b/openecomp-ui/src/sdc-app/common/modal/ModalContentMapper.js
new file mode 100644
index 0000000000..548e0cfc9c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/common/modal/ModalContentMapper.js
@@ -0,0 +1,31 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import SoftwareProductCreation from 'sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js';
+import LicenseModelCreation from 'sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js';
+import SubmitErrorResponse from 'nfvo-components/SubmitErrorResponse.jsx';
+
+export const modalContentMapper = {
+ SOFTWARE_PRODUCT_CREATION: 'SOFTWARE_PRODUCT_CREATION',
+ LICENSE_MODEL_CREATION: 'LICENSE_MODEL_CREATION',
+ SUMBIT_ERROR_RESPONSE: 'SUMBIT_ERROR_RESPONSE'
+};
+
+export const modalContentComponents = {
+ SUMBIT_ERROR_RESPONSE: SubmitErrorResponse,
+ SOFTWARE_PRODUCT_CREATION: SoftwareProductCreation,
+ LICENSE_MODEL_CREATION: LicenseModelCreation,
+}; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducer.js b/openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducer.js
new file mode 100644
index 0000000000..35b2f936ce
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducer.js
@@ -0,0 +1,145 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './JSONSchemaReducerConstants.js';
+import Validator from 'nfvo-utils/Validator.js';
+import JSONSchema from 'nfvo-utils/json/JSONSchema.js';
+import JSONPointer from 'nfvo-utils/json/JSONPointer.js';
+import forOwn from 'lodash/forOwn.js';
+import isArray from 'lodash/isArray.js';
+
+
+function flattenData(data, result, pointer = '') {
+ let newPointer = pointer;
+ if (typeof data === 'object' && !isArray(data)) {
+ for (let i in data) {
+ newPointer = newPointer ? newPointer + '/' + i : i;
+ flattenData(data[i], result, newPointer);
+ newPointer = pointer;
+ }
+ } else {
+ result[newPointer] = data;
+ }
+}
+
+function updateSchemaDataAndValidateReducer (state = {}, action, questionnaireName) {
+ let genericFieldInfoClone;
+ switch (action.type) {
+ case actionTypes.DATA_LOADED:
+ if (questionnaireName !== action.qName) {return {...state};}
+ const schema = action.payload.qschema;
+ let schemaLoader = new JSONSchema();
+ schemaLoader.setSchema(schema);
+ schemaLoader.setSupportedValidationFunctions(Object.keys(Validator.globalValidationFunctions));
+ let {genericFieldInfo} = schemaLoader.flattenSchema();
+
+ let data = action.payload.qdata;
+ let dataMap = {};
+ flattenData(data, dataMap);
+
+ return {
+ ...state,
+ qdata: action.payload.qdata, // the original hierarchical data. to be used for submit and save
+ qgenericFieldInfo : genericFieldInfo, // information about the fields that the view will require and reducer will need, such as validations, enum to use, etc.
+ dataMap // flattened schema data for ease of use
+ };
+
+ case actionTypes.DATA_CHANGED:
+ let changedData = action.deltaData;
+ if (questionnaireName !== action.qName) {return {...state};}
+
+ genericFieldInfoClone = {...state.qgenericFieldInfo};
+ let qDataClone = {...state.qdata};
+ let dataMapClone = {...state.dataMap};
+
+ forOwn(changedData,(value, key) => {
+ if (state.qgenericFieldInfo[key]) {
+ let result = Validator.validate(key, value, state.qgenericFieldInfo[key].validations, state, action.customValidations);
+ genericFieldInfoClone[key] = {...genericFieldInfoClone[key], isValid: result.isValid, errorText: result.errorText};
+ qDataClone = JSONPointer.setValue(state.qdata, '/' + key, value);
+ dataMapClone[key] = value;
+ }
+ });
+
+ return {
+ ...state,
+ qdata: qDataClone,
+ dataMap: dataMapClone,
+ qgenericFieldInfo: genericFieldInfoClone
+ };
+
+ case actionTypes.VALIDATE_DATA:
+ let specificFields = action.data;
+ if (questionnaireName !== action.qName) {return {...state};}
+ genericFieldInfoClone = {...state.qgenericFieldInfo};
+ forOwn(specificFields,(value, key) => {
+ let result = Validator.validate(key, value, state.qgenericFieldInfo[key].validations, state, action.customValidations);
+ genericFieldInfoClone[key] = {...genericFieldInfoClone[key], isValid: result.isValid, errorText: result.errorText};
+ });
+ return {
+ ...state,
+ formReady: null,
+ qgenericFieldInfo: genericFieldInfoClone
+ };
+
+ case actionTypes.VALIDATE_FORM:
+ if (questionnaireName !== action.qName) {return {...state};}
+ genericFieldInfoClone = {...state.qgenericFieldInfo};
+ let formReady = true;
+ forOwn(state.qgenericFieldInfo,(value, key) => {
+ let val = state.data[key] ? state.data[key] : '';
+ let result = Validator.validate(key, val, state.qgenericFieldInfo[key].validations, state, {});
+ genericFieldInfoClone[key] = {...genericFieldInfoClone[key], isValid: result.isValid, errorText: result.errorText};
+ if (!result.isValid) {
+ formReady = false;
+ }
+ });
+ return {
+ ...state,
+ formReady,
+ qgenericFieldInfo: genericFieldInfoClone
+ };
+
+ default:
+ return state;
+ }
+};
+
+export function createJSONSchemaReducer(questionnaireName) {
+ return (state = {}, action) => {
+ return updateSchemaDataAndValidateReducer(state, action, questionnaireName);
+ };
+};
+
+export function createComposedJSONSchemaReducer(questionnaireName, additionalActionsReducer) {
+ return (state = {}, action) => {
+ if(action.type === actionTypes.VALIDATE_DATA ||
+ action.type === actionTypes.VALIDATE_FORM ||
+ action.type === actionTypes.DATA_CHANGED ||
+ action.type === actionTypes.DATA_LOADED
+ ) {
+ return updateSchemaDataAndValidateReducer(state, action, questionnaireName);
+ } else {
+ return additionalActionsReducer(state, action);
+ }
+ };
+};
+
+
+
+
+
+
+
diff --git a/openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducerConstants.js b/openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducerConstants.js
new file mode 100644
index 0000000000..6007b878dd
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/common/reducers/JSONSchemaReducerConstants.js
@@ -0,0 +1,23 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+ DATA_LOADED: null,
+ DATA_CHANGED: null,
+ VALIDATE_FORM: null,
+ VALIDATE_DATA: null
+});
diff --git a/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
new file mode 100644
index 0000000000..0bbb5e63be
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
@@ -0,0 +1,94 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './PlainDataReducerConstants.js';
+import Validator from 'nfvo-utils/Validator.js';
+import forOwn from 'lodash/forOwn.js';
+
+function updateDataAndValidateReducer(state = {}, action) {
+ let genericFieldInfoCopy;
+ switch (action.type) {
+ case actionTypes.DATA_CHANGED:
+ let changed = action.deltaData;
+ if (!action.formName || (state.formName !== action.formName)) {return {...state};}
+ genericFieldInfoCopy = {...state.genericFieldInfo};
+ forOwn(changed,(value, key) => {
+ if (state.genericFieldInfo[key]) {
+ let result = Validator.validate(key, value, state.genericFieldInfo[key].validations, state, action.customValidations);
+ genericFieldInfoCopy[key] = {...genericFieldInfoCopy[key], isValid: result.isValid, errorText: result.errorText};
+ }
+ });
+ return {
+ ...state,
+ formReady: null,
+ data: {
+ ...state.data,
+ ...action.deltaData
+ },
+ genericFieldInfo: genericFieldInfoCopy
+ };
+ case actionTypes.VALIDATE_FORM:
+ if (!action.formName || (state.formName !== action.formName)) {return {...state};}
+ genericFieldInfoCopy = {...state.genericFieldInfo};
+ let formReady = true;
+ forOwn(state.genericFieldInfo,(value, key) => {
+ let val = state.data && state.data[key] ? state.data[key] : '';
+ let result = Validator.validate(key, val, state.genericFieldInfo[key].validations, state, {});
+ genericFieldInfoCopy[key] = {...genericFieldInfoCopy[key], isValid: result.isValid, errorText: result.errorText};
+ if (!result.isValid) {
+ formReady = false;
+ }
+ });
+ return {
+ ...state,
+ formReady,
+ genericFieldInfo: genericFieldInfoCopy
+ };
+ case actionTypes.VALIDATE_DATA:
+ let specificFields = action.data;
+ if (!action.formName || (state.formName !== action.formName)) {return {...state};}
+ genericFieldInfoCopy = {...state.genericFieldInfo};
+ forOwn(specificFields,(value, key) => {
+ let result = Validator.validate(key, value, state.genericFieldInfo[key].validations, state, action.customValidations);
+ genericFieldInfoCopy[key] = {...genericFieldInfoCopy[key], isValid: result.isValid, errorText: result.errorText};
+ });
+ return {
+ ...state,
+ formReady: null,
+ genericFieldInfo: genericFieldInfoCopy
+ };
+ default:
+ return state;
+ }
+};
+
+export function createPlainDataReducer(loadReducer) {
+ return (state = {}, action) => {
+ if(action.type === actionTypes.VALIDATE_DATA ||
+ action.type === actionTypes.VALIDATE_FORM ||
+ action.type === actionTypes.DATA_CHANGED
+ ) {
+ return updateDataAndValidateReducer(state, action);
+ } else {
+ return loadReducer(state, action);
+ }
+ };
+};
+
+
+
+
+
+
diff --git a/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducerConstants.js b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducerConstants.js
new file mode 100644
index 0000000000..135361dd20
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducerConstants.js
@@ -0,0 +1,22 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+ DATA_CHANGED: null,
+ VALIDATE_FORM: null,
+ VALIDATE_DATA: null
+});
diff --git a/openecomp-ui/src/sdc-app/config/Configuration.js b/openecomp-ui/src/sdc-app/config/Configuration.js
index 4bbe07864f..227e36995b 100644
--- a/openecomp-ui/src/sdc-app/config/Configuration.js
+++ b/openecomp-ui/src/sdc-app/config/Configuration.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import configData from './config.json';
class Configuration {
@@ -43,19 +38,17 @@ class Configuration {
setATTApiHeaders(ATTApiHeaders) {
this.set('ATTApiHeaders', ATTApiHeaders);
- let {userId: {value: ATTUserID} = {}} = ATTApiHeaders;
- this.set('ATTUserID', ATTUserID);
+ let {userId: {value: UserID} = {}} = ATTApiHeaders;
+ this.set('UserID', UserID);
}
-
}
const configuration = new Configuration();
(function setDefaultRestPrefixes(configuration) {
-
configuration.set('restPrefix', configuration.get('defaultRestPrefix'));
configuration.set('restATTPrefix', configuration.get('defaultRestATTPrefix'));
-
+ configuration.set('appContextPath', configuration.get('appContextPath'));
})(configuration);
diff --git a/openecomp-ui/src/sdc-app/config/config.json b/openecomp-ui/src/sdc-app/config/config.json
index 4127e0c12e..2725cf1310 100644
--- a/openecomp-ui/src/sdc-app/config/config.json
+++ b/openecomp-ui/src/sdc-app/config/config.json
@@ -2,7 +2,7 @@
"pageSize": 25,
"version": "9.4",
"build": "dev",
-
+ "appContextPath" : "/onboarding",
"defaultRestPrefix": "/onboarding-api",
"defaultRestATTPrefix": "/sdc1/feProxy/rest"
}
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsActions.js b/openecomp-ui/src/sdc-app/flows/FlowsActions.js
index b8772edb08..5a751064df 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsActions.js
+++ b/openecomp-ui/src/sdc-app/flows/FlowsActions.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes, enums} from './FlowsConstants.js';
@@ -59,7 +54,8 @@ function decodeContent(base64Contents) {
sequenceDiagramModel = payload.data || payload;
sequenceDiagramModel = sequenceDiagramModel.model || sequenceDiagramModel;
- } else if (payload.VERSION.major === 1) {
+ }
+ else if (payload.VERSION.major === 1) {
description = payload.description;
sequenceDiagramModel = payload.sequenceDiagramModel;
}
@@ -80,7 +76,7 @@ function createOrUpdate(flowData) {
description: flowData.description
};
- return RestAPIUtil.create(
+ return RestAPIUtil.post(
baseUrl(flowData.serviceID, flowData.uniqueId),
createOrUpdateRequest,
{md5: true}
@@ -89,11 +85,13 @@ function createOrUpdate(flowData) {
const FlowsActions = Object.freeze({
- fetchFlowArtifacts(dispatch, {artifacts, diagramType, participants, serviceID}) {
+ fetchFlowArtifacts(dispatch, {artifacts, diagramType, participants, serviceID, readonly}) {
let results = [];
if (!Object.keys(artifacts).length) {
- dispatch({type: actionTypes.FLOW_LIST_LOADED, results, participants, serviceID, diagramType});
- FlowsActions.openFlowDetailsEditor(dispatch);
+ dispatch({type: actionTypes.FLOW_LIST_LOADED, results, participants, serviceID, diagramType, readonly});
+ if (!readonly) {
+ FlowsActions.openFlowDetailsEditor(dispatch);
+ }
}
else {
Object.keys(artifacts).forEach(artifact => results.push({
@@ -102,13 +100,13 @@ const FlowsActions = Object.freeze({
serviceID,
...artifacts[artifact]
}));
- dispatch({type: actionTypes.FLOW_LIST_LOADED, results, participants, serviceID, diagramType});
+ dispatch({type: actionTypes.FLOW_LIST_LOADED, results, participants, serviceID, diagramType, readonly});
}
},
fetchArtifact(dispatch, {flow}){
let {serviceID, uniqueId, participants} = flow;
- RestAPIUtil.fetch(baseUrl(serviceID, uniqueId)).then(response => {
+ return RestAPIUtil.fetch(baseUrl(serviceID, uniqueId)).then(response => {
let {artifactName, base64Contents} = response;
let {sequenceDiagramModel, ...other} = decodeContent(base64Contents);
@@ -146,7 +144,7 @@ const FlowsActions = Object.freeze({
name: flow.artifactName
});
}
- createOrUpdate(flow).then(response => {
+ return createOrUpdate(flow).then(response => {
let {uniqueId, artifactLabel} = response;
flow = {...flow, uniqueId, artifactLabel};
if (isNew) {
@@ -157,7 +155,7 @@ const FlowsActions = Object.freeze({
},
deleteFlow(dispatch, {flow}) {
- RestAPIUtil.destroy(baseUrl(flow.serviceID, flow.uniqueId)).then(() => dispatch({
+ return RestAPIUtil.destroy(baseUrl(flow.serviceID, flow.uniqueId)).then(() => dispatch({
type: actionTypes.DELETE_FLOW,
flow
}));
@@ -179,10 +177,6 @@ const FlowsActions = Object.freeze({
dispatch({type: actionTypes.CLOSE_FLOW_DIAGRAM_EDITOR});
},
- flowDetailsDataChanged(dispatch, {deltaData}) {
- dispatch({type: actionTypes.CURRENT_FLOW_DATA_CHANGED, deltaData});
- },
-
reset(dispatch) {
dispatch({type: actionTypes.RESET});
}
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsConstants.js b/openecomp-ui/src/sdc-app/flows/FlowsConstants.js
index 5a43a4df4f..2b3d86bae2 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsConstants.js
+++ b/openecomp-ui/src/sdc-app/flows/FlowsConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
@@ -46,3 +41,5 @@ export const enums = {
INSTANTIATION_FLOWS: 'instantiationflows',
MESSAGE_FLOWS: 'messageflows'
};
+
+export const FLOWS_EDITOR_FORM = 'FLOWS_FORM';
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsEditorModal.js b/openecomp-ui/src/sdc-app/flows/FlowsEditorModal.js
index eff1c36b80..f9585f985f 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsEditorModal.js
+++ b/openecomp-ui/src/sdc-app/flows/FlowsEditorModal.js
@@ -1,42 +1,43 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import FlowsEditorModalView from './FlowsEditorModalView.jsx';
import FlowsActions from './FlowsActions.js';
+import {FLOWS_EDITOR_FORM} from './FlowsConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
export const mapStateToProps = ({flows}) => {
- let {currentFlow = {artifactName: '', description: ''}, serviceID, diagramType, flowParticipants} = flows;
- if(!currentFlow.serviceID){
- currentFlow.serviceID = serviceID;
+ let {data = {artifactName: '', description: ''}, serviceID, diagramType, flowParticipants, genericFieldInfo, formReady} = flows;
+ if(!data.serviceID){
+ data.serviceID = serviceID;
}
- if(!currentFlow.artifactType){
- currentFlow.artifactType = diagramType;
+ if(!data.artifactType){
+ data.artifactType = diagramType;
}
- if(!currentFlow.participants){
- currentFlow.participants = flowParticipants;
+ if(!data.participants){
+ data.participants = flowParticipants;
}
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
return {
- currentFlow
+ currentFlow: data,
+ genericFieldInfo,
+ isFormValid,
+ formReady
};
};
@@ -47,7 +48,8 @@ const mapActionsToProps = (dispatch, {isNewArtifact}) => {
FlowsActions.createOrUpdateFlow(dispatch, {flow}, isNewArtifact);
},
onCancel: () => FlowsActions.closeFlowDetailsEditor(dispatch),
- onDataChanged: deltaData => FlowsActions.flowDetailsDataChanged(dispatch, {deltaData})
+ onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: FLOWS_EDITOR_FORM}),
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, FLOWS_EDITOR_FORM)
};
};
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsEditorModalView.jsx b/openecomp-ui/src/sdc-app/flows/FlowsEditorModalView.jsx
index 8441c7d1d6..1250a0b58e 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsEditorModalView.jsx
+++ b/openecomp-ui/src/sdc-app/flows/FlowsEditorModalView.jsx
@@ -1,30 +1,54 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React, {Component} from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import Input from 'nfvo-components/input/validation/ValidationInput.jsx';
-import Form from 'nfvo-components/input/validation/ValidationForm.jsx';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
class FlowsEditorModalView extends Component {
render() {
- let {onCancel, onDataChanged, currentFlow} = this.props;
+ let {onCancel, onDataChanged, currentFlow, genericFieldInfo, formReady, isFormValid, onValidateForm} = this.props;
let {artifactName, description} = currentFlow;
return (
- <Form onSubmit={() => this.onSaveClicked()} onReset={onCancel}>
+ <div>
+ {genericFieldInfo && <Form
+ onSubmit={() => this.onSaveClicked()}
+ onReset={onCancel} formReady={formReady} isValid={isFormValid} onValidateForm={() => onValidateForm()} >
<Input
type='text'
name='name'
label={i18n('Name')}
- validations={{required: true}}
+ isValid={genericFieldInfo['artifactName'].isValid}
+ errorText={genericFieldInfo['artifactName'].errorText}
+ isRequired={true}
value={artifactName}
onChange={artifactName => onDataChanged({artifactName})}/>
<Input
type='textarea'
name='description'
label={i18n('Description')}
- validations={{required: true}}
+ isValid={genericFieldInfo['description'].isValid}
+ errorText={genericFieldInfo['description'].errorText}
+ isRequired={true}
value={description}
+ overlayPos='bottom'
onChange={description => onDataChanged({description})}/>
- </Form>
+ </Form> }
+ </div>
);
}
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsListEditor.js b/openecomp-ui/src/sdc-app/flows/FlowsListEditor.js
index ff301b6e13..642c578eb7 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsListEditor.js
+++ b/openecomp-ui/src/sdc-app/flows/FlowsListEditor.js
@@ -1,30 +1,28 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import FlowsActions from './FlowsActions.js';
import FlowsListEditorView from './FlowsListEditorView.jsx';
export const mapStateToProps = ({flows}) => {
- let {flowList = [], isDisplayModal, isModalInEditMode, shouldShowWorkflowsEditor = true, currentFlow = undefined} = flows;
- let isCheckedOut = currentFlow ? !currentFlow.readonly : true;
+ let {flowList = [], isDisplayModal, isModalInEditMode, shouldShowWorkflowsEditor = true, data = undefined, readonly} = flows;
+ let isCheckedOut = !readonly;
+ if(data && data.readonly){
+ isCheckedOut = !data.readonly;
+ }
return {
flowList,
@@ -32,7 +30,8 @@ export const mapStateToProps = ({flows}) => {
isCheckedOut,
isModalInEditMode,
shouldShowWorkflowsEditor,
- currentFlow
+ currentFlow: data,
+ readonly
};
};
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsListEditorView.jsx b/openecomp-ui/src/sdc-app/flows/FlowsListEditorView.jsx
index 3cea3968ff..c5dbb4f909 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/flows/FlowsListEditorView.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React, {PropTypes, Component} from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -18,6 +33,7 @@ class FlowsListEditorView extends Component {
isModalInEditMode: PropTypes.bool,
isCheckedOut: PropTypes.bool,
shouldShowWorkflowsEditor: PropTypes.bool,
+ readonly: PropTypes.bool,
onAddWorkflowClick: PropTypes.func,
onEditFlowDetailsClick: PropTypes.func,
@@ -55,7 +71,7 @@ class FlowsListEditorView extends Component {
onAdd={onAddWorkflowClick}
filterValue={localFilter}
onFilter={filter => this.setState({localFilter: filter})}
- isCheckedOut={isCheckedOut}>
+ isReadOnlyMode={!isCheckedOut}>
{this.filterList().map(flow => this.renderWorkflowListItem(flow, isCheckedOut))}
</ListEditorView>
@@ -68,7 +84,7 @@ class FlowsListEditorView extends Component {
renderWorkflowEditorModal() {
let { isDisplayModal, isModalInEditMode} = this.props;
return (
- <Modal show={isDisplayModal} animation={true} className='workflows-editor-modal'>
+ <Modal show={isDisplayModal} animation={true} className='onborading-modal workflows-editor-modal'>
<Modal.Header>
<Modal.Title>
{`${isModalInEditMode ? i18n('Edit Workflow') : i18n('Create New Workflow')}`}
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsListReducer.js b/openecomp-ui/src/sdc-app/flows/FlowsListReducer.js
index f025450a58..14bf595050 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsListReducer.js
+++ b/openecomp-ui/src/sdc-app/flows/FlowsListReducer.js
@@ -1,24 +1,19 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from './FlowsConstants.js';
+import {actionTypes, FLOWS_EDITOR_FORM} from './FlowsConstants.js';
export default (state = {}, action) => {
switch (action.type) {
@@ -28,7 +23,8 @@ export default (state = {}, action) => {
flowList: action.results,
flowParticipants: action.participants,
serviceID: action.serviceID,
- diagramType: action.diagramType
+ diagramType: action.diagramType,
+ readonly: action.readonly
};
case actionTypes.ADD_OR_UPDATE_FLOW:
case actionTypes.ARTIFACT_LOADED:
@@ -49,14 +45,6 @@ export default (state = {}, action) => {
serviceID: action.flow.serviceID,
diagramType: action.flow.artifactType || state.diagramType
};
- case actionTypes.CURRENT_FLOW_DATA_CHANGED:
- return {
- ...state,
- currentFlow: {
- ...state.currentFlow,
- ...action.deltaData
- }
- };
case actionTypes.DELETE_FLOW:
return {
...state,
@@ -65,7 +53,21 @@ export default (state = {}, action) => {
case actionTypes.OPEN_FLOW_DETAILS_EDITOR:
return {
...state,
- currentFlow: action.flow,
+ formName: FLOWS_EDITOR_FORM,
+ formReady: null,
+ genericFieldInfo: {
+ artifactName : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ description: {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ }
+ },
+ data: action.flow,
isDisplayModal: true,
isModalInEditMode: Boolean(action.flow && action.flow.uniqueId)
};
@@ -73,20 +75,20 @@ export default (state = {}, action) => {
case actionTypes.CLOSE_FLOW_DETAILS_EDITOR:
return {
...state,
- currentFlow: undefined,
+ data: undefined,
isDisplayModal: false,
isModalInEditMode: false
};
case actionTypes.OPEN_FLOW_DIAGRAM_EDITOR:
return {
...state,
- currentFlow: action.flow,
+ data: action.flow,
shouldShowWorkflowsEditor: false
};
case actionTypes.CLOSE_FLOW_DIAGRAM_EDITOR:
return {
...state,
- currentFlow: undefined,
+ data: undefined,
shouldShowWorkflowsEditor: true
};
case actionTypes.RESET:
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsPunchOut.jsx b/openecomp-ui/src/sdc-app/flows/FlowsPunchOut.jsx
index 958f9a0a2d..873003492b 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsPunchOut.jsx
+++ b/openecomp-ui/src/sdc-app/flows/FlowsPunchOut.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import ReactDOM from 'react-dom';
import Configuration from 'sdc-app/config/Configuration.js';
diff --git a/openecomp-ui/src/sdc-app/flows/FlowsReducersMap.js b/openecomp-ui/src/sdc-app/flows/FlowsReducersMap.js
index b3c0b2e27b..54043498f0 100644
--- a/openecomp-ui/src/sdc-app/flows/FlowsReducersMap.js
+++ b/openecomp-ui/src/sdc-app/flows/FlowsReducersMap.js
@@ -1,25 +1,22 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
import flowListReducer from './FlowsListReducer.js';
+import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js';
export default {
- flows: flowListReducer
+ flows: createPlainDataReducer(flowListReducer)
};
diff --git a/openecomp-ui/src/sdc-app/flows/ImportantLogic.jsx b/openecomp-ui/src/sdc-app/flows/ImportantLogic.jsx
index c4ab41841b..d0a5bf3251 100644
--- a/openecomp-ui/src/sdc-app/flows/ImportantLogic.jsx
+++ b/openecomp-ui/src/sdc-app/flows/ImportantLogic.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React, {Component} from 'react';
import md5 from 'md5';
diff --git a/openecomp-ui/src/sdc-app/flows/SequenceDiagram.jsx b/openecomp-ui/src/sdc-app/flows/SequenceDiagram.jsx
index 9970969884..b0bd40db40 100644
--- a/openecomp-ui/src/sdc-app/flows/SequenceDiagram.jsx
+++ b/openecomp-ui/src/sdc-app/flows/SequenceDiagram.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React, {Component, PropTypes} from 'react';
import Button from 'react-bootstrap/lib/Button.js';
import Sequencer from 'dox-sequence-diagram-ui';
@@ -8,7 +23,7 @@ class SequenceDiagram extends Component {
static propTypes = {
onSave: PropTypes.func.isRequired,
- onClose: PropTypes.func.isRequired,
+ onClose: PropTypes.func,
model: PropTypes.object.isRequired
};
diff --git a/openecomp-ui/src/sdc-app/flows/SequenceDiagramModelHelper.js b/openecomp-ui/src/sdc-app/flows/SequenceDiagramModelHelper.js
index c2e10a6360..c83fdc91f0 100644
--- a/openecomp-ui/src/sdc-app/flows/SequenceDiagramModelHelper.js
+++ b/openecomp-ui/src/sdc-app/flows/SequenceDiagramModelHelper.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import emptyModel from './emptyModel.json';
function mergeLifelines(oldLifelines, newLifelines) {
diff --git a/openecomp-ui/src/sdc-app/heatValidation.app.jsx b/openecomp-ui/src/sdc-app/heatValidation.app.jsx
index eb58a79b25..6ff3c7375c 100644
--- a/openecomp-ui/src/sdc-app/heatValidation.app.jsx
+++ b/openecomp-ui/src/sdc-app/heatValidation.app.jsx
@@ -1,5 +1,19 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import '../../resources/scss/bootstrap.scss';
-import '../../resources/css/font-awesome.min.css';
import 'react-select/dist/react-select.min.css';
import 'dox-sequence-diagram-ui/src/main/webapp/res/sdc-sequencer.scss';
import '../../resources/scss/style.scss';
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/Attachments.js b/openecomp-ui/src/sdc-app/heatvalidation/Attachments.js
new file mode 100644
index 0000000000..d3e30b0df8
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/heatvalidation/Attachments.js
@@ -0,0 +1,44 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {connect} from 'react-redux';
+import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
+import {mapStateToProps as attachmentsMapStateToProps, mapActionsToProps as attachmentsMapActionsToProps} from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js';
+// import AttachmentsView from './AttachmentsView.jsx';
+import AttachmentsView from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx';
+import UploadScreenActionHelper from './UploadScreenActionHelper.js';
+import HeatSetup from './HeatSetup';
+
+export const mapStateToProps = (state) => {
+ let original = attachmentsMapStateToProps(state);
+ return {
+ ...original,
+ HeatSetupComponent: HeatSetup,
+ isReadOnlyMode: false
+ };
+};
+
+const mapActionsToProps = (dispatch, {softwareProductId}) => {
+ let original = attachmentsMapActionsToProps(dispatch, {softwareProductId});
+ return {
+ ...original,
+ onDownload: heatCandidate => UploadScreenActionHelper.downloadHeatFile(dispatch, heatCandidate),
+ onUpload: formData => UploadScreenActionHelper.uploadFile(dispatch, formData),
+ onSave: (heatCandidate) => SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate}),
+ onProcessAndValidate: (heatData, heatDataCache) => UploadScreenActionHelper.processAndValidateHeat(dispatch, heatData, heatDataCache)
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(AttachmentsView);
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/HeatSetup.js b/openecomp-ui/src/sdc-app/heatvalidation/HeatSetup.js
new file mode 100644
index 0000000000..925b0095ba
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/heatvalidation/HeatSetup.js
@@ -0,0 +1,28 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {connect} from 'react-redux';
+import HeatSetupView from '../onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx';
+import UploadScreenActionHelper from './UploadScreenActionHelper.js';
+import {mapStateToProps, mapActionsToProps} from '../onboarding/softwareProduct/attachments/setup/HeatSetup.js';
+
+const mapActionsToPropsExt = (dispatch) => {
+ return {
+ ...mapActionsToProps(dispatch,{}),
+ onProcessAndValidate: (heatData, heatDataCache) => UploadScreenActionHelper.processAndValidateHeat(dispatch, heatData, heatDataCache)
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToPropsExt, null, {withRef: true})(HeatSetupView);
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreen.jsx b/openecomp-ui/src/sdc-app/heatvalidation/UploadScreen.jsx
index 0bb496fc51..2d99c0f497 100644
--- a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreen.jsx
+++ b/openecomp-ui/src/sdc-app/heatvalidation/UploadScreen.jsx
@@ -1,182 +1,32 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import {connect} from 'react-redux';
-import Button from 'react-bootstrap/lib/Button.js';
-import Dropzone from 'react-dropzone';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import ProgressBar from 'nfvo-components/progressBar/ProgressBar.jsx';
-import Modal from 'nfvo-components/modal/Modal.jsx';
-import UploadScreenActionHelper from './UploadScreenActionHelper.js';
-import Attachments from './attachments/Attachments.js';
+import SoftwareProductAttachmentsView from './Attachments.js';
-const mapStateToProps = ({uploadScreen}) => {
- let {upload} = uploadScreen;
- return {uploadScreen: upload};
-};
-
-
-const mapActionsToProps = dispatch => {
- return {
- onUpload: (formData) => UploadScreenActionHelper.uploadFile(dispatch, formData),
- openMainScreen: () => UploadScreenActionHelper.openMainScreen(dispatch)
- };
-};
class UploadScreen extends React.Component {
- state = {
- complete: '10',
- showModal: false,
- fileName: '',
- dragging: false,
- files: []
- };
-
- interval = '';
-
render() {
- let {uploadScreen} = this.props;
- let {showAttachments} = uploadScreen;
return(
<div className='heat-validation-stand-alone'>
- {showAttachments ? this.renderTree() : this.renderUploadScreen()}
- </div>
- );
- }
-
- renderUploadModal() {
- let {complete, showModal, fileName} = this.state;
- return (
- <Modal show={showModal} animation={true}>
- <Modal.Header>
- <Modal.Title>{i18n('Uploading attachments')}</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- <div className='upload-modal-body-content'>
- <div>
- <span className='title'>{i18n('File:')}</span>
- <span className='file-name'>{fileName}</span>
- </div>
- <ProgressBar now={complete} label={`${complete}%`}/>
- <div>{i18n('Upload in progress')}</div>
- </div>
- <Modal.Footer>
- <Button bsStyle='primary' onClick={() => this.onRunBackground()}>
- {i18n('Run in Background')}
- </Button>
- <Button bsStyle='primary' onClick={() => this.onCancel()}>{i18n('Cancel')}</Button>
- </Modal.Footer>
- </Modal.Body>
- </Modal>
- );
- }
-
- renderUploadScreen() {
- return(
- <div className='upload-screen'>
- <div className='row'>
- <div className='title'>
- <h1>HEAT VALIDATION APPLICATION</h1>
- </div>
- </div>
- <div className='row'>
- <div className='col-md-2 col-md-offset-5'>
- <Dropzone
- className={`upload-screen-drop-zone ${this.state.dragging ? 'active-dragging' : ''}`}
- onDrop={files => this.handleImportSubmit(files)}
- onDragEnter={() => this.setState({dragging:true})}
- onDragLeave={() => this.setState({dragging:false})}
- multiple={false}
- disableClick={true}
- ref='fileInput'
- name='fileInput'
- accept='.zip'>
- <div
- className='upload-screen-upload-block'>
- <div className='drag-text'>{i18n('Drag & drop for upload')}</div>
- <div className='or-text'>{i18n('or')}</div>
- <div className='upload-btn primary-btn' onClick={() => this.refs.fileInput.open()}>
- <span className='primary-btn-text'>{i18n('Select file')}</span>
- </div>
- </div>
- </Dropzone>
- </div>
- {this.renderUploadModal()}
- </div>
- </div>
- );
- }
-
- renderTree() {
- let {openMainScreen} = this.props;
- return(
- <div className='attachments-screen'>
- <Attachments/>
- <div className='back-button'>
- <div className='upload-btn primary-btn' onClick={() => openMainScreen()}>
- <span className='primary-btn-text'>{i18n('Back')}</span>
- </div>
- </div>
+ <SoftwareProductAttachmentsView />
</div>
);
}
-
- handleImportSubmit(files) {
- this.setState({
- showModal: true,
- fileName: files[0].name,
- dragging: false,
- complete: '0',
- files
- });
-
-
- this.interval = setInterval(() => {
- if (this.state.complete >= 90) {
- clearInterval(this.interval);
- this.setState({
- showModal: false,
- fileName: ''
- });
- this.startUploading(files);
- } else {
- this.setState({
- complete: (parseInt(this.state.complete) + 10).toString()
- });
- }
- }, 20);
-
- }
-
- onRunBackground() {
- let {files} = this.state;
- clearInterval(this.interval);
- this.startUploading(files);
- this.setState({showModal: false, files: []});
- }
-
- onCancel() {
- clearInterval(this.interval);
- this.setState({
- showModal: false,
- fileName: '',
- files: []
- });
-
- }
-
- startUploading(files) {
- let {onUpload} = this.props;
- if (!(files && files.length)) {
- return;
- }
- let file = files[0];
- let formData = new FormData();
- formData.append('upload', file);
- this.refs.fileInput.value = '';
- onUpload(formData);
- }
-
}
-export default connect(mapStateToProps, mapActionsToProps)(UploadScreen);
+export default UploadScreen;
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenActionHelper.js b/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenActionHelper.js
index 3b8de0f0d4..4e9120956e 100644
--- a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenActionHelper.js
+++ b/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenActionHelper.js
@@ -1,60 +1,204 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
-import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js';
-import {actionTypes} from './UploadScreenConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import isEqual from 'lodash/isEqual.js';
+import cloneDeep from 'lodash/cloneDeep.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
import {actionTypes as softwareProductsActionTypes} from '../onboarding/softwareProduct/SoftwareProductConstants.js';
+import {actionTypes as HeatSetupActions} from '../onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js';
+
+
+
+const options = {
+ headers: {
+ HTTP_CSP_ATTUID: 'validationOnlyVspUser'
+ }
+};
+
+
+function getTimestampString() {
+ let date = new Date();
+ let z = n => n < 10 ? '0' + n : n;
+ return `${date.getFullYear()}-${z(date.getMonth())}-${z(date.getDate())}_${z(date.getHours())}-${z(date.getMinutes())}`;
+}
+
+function fetchVspId() {
+
+ let vspId = sessionStorage.getItem('validationAppVspId');
+ if (vspId) {
+ return Promise.resolve({value: vspId});
+ }else {
+ return RestAPIUtil.fetch('/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/validation-vsp', options)
+ .then(response => {
+ sessionStorage.setItem('validationAppVspId', response.value);
+ return Promise.resolve(response);
+ });
+ }
+
+}
+
+
+function showFileSaveDialog({blob, xhr, defaultFilename, addTimestamp}) {
+ let filename;
+ let contentDisposition = xhr.getResponseHeader('content-disposition');
+ let match = contentDisposition ? contentDisposition.match(/filename=(.*?)(;|$)/) : false;
+ if (match) {
+ filename = match[1];
+ } else {
+ filename = defaultFilename;
+ }
+
+ if (addTimestamp) {
+ filename = filename.replace(/(^.*?)\.([^.]+$)/, `$1_${getTimestampString()}.$2`);
+ }
+
+ let link = document.createElement('a');
+ let url = URL.createObjectURL(blob);
+ link.href = url;
+ link.download = filename;
+ link.style.display = 'none';
+ document.body.appendChild(link);
+ link.click();
+ setTimeout(function(){
+ document.body.removeChild(link);
+ URL.revokeObjectURL(url);
+ }, 0);
+}
+
function uploadFile(formData) {
- return RestAPIUtil.create('/sdc1/feProxy/onboarding-api/v1.0/validation/HEAT/validate', formData);
+ return fetchVspId()
+ .then(response => {
+ return RestAPIUtil.post(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/0.1/orchestration-template-candidate`, formData, options);
+ });
+}
+
+function loadSoftwareProductHeatCandidate(dispatch){
+ return fetchVspId()
+ .then(response => {
+ return RestAPIUtil.fetch(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/0.1/orchestration-template-candidate/manifest`, options)
+ .then(response => dispatch({
+ type: HeatSetupActions.MANIFEST_LOADED,
+ response
+ }));
+ });
+}
+
+function updateHeatCandidate(dispatch, heatCandidate) {
+ return fetchVspId()
+ .then(response => {
+ return RestAPIUtil.put(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/0.1/orchestration-template-candidate/manifest`,
+ heatCandidate.heatData, options)
+ .then(null, error => {
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_ERROR,
+ data: {
+ title: i18n('Save Failed'),
+ modalComponentName: modalContentMapper.SUMBIT_ERROR_RESPONSE,
+ modalComponentProps: {
+ validationResponse: error.responseJSON
+ },
+ cancelButtonText: i18n('Ok')
+ }
+ });
+ return Promise.reject(error);
+ });
+ });
+}
+
+function fetchSoftwareProduct() {
+ return fetchVspId()
+ .then(response => {
+ return RestAPIUtil.fetch(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/0.1`, options);
+ });
+}
+
+function downloadHeatFile() {
+ return fetchVspId()
+ .then(response => {
+ RestAPIUtil.fetch(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/0.1/orchestration-template-candidate`, {
+ ...options,
+ dataType: 'binary'
+ })
+ .done((blob, statusText, xhr) => showFileSaveDialog({
+ blob,
+ xhr,
+ defaultFilename: 'HEAT_file.zip',
+ addTimestamp: true
+ }));
+ });
+}
+
+function processAndValidateHeatCandidate(dispatch) {
+ return fetchVspId()
+ .then(response => {
+ return RestAPIUtil.put(`/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/${response.value}/versions/0.1/orchestration-template-candidate/process`, {}, options)
+ .then(response => {
+ if (response.status === 'Success') {
+ fetchSoftwareProduct().then(response => {
+ dispatch({
+ type: softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED,
+ response
+ });
+ });
+ }
+ });
+ });
}
const UploadScreenActionHelper = {
uploadFile(dispatch, formData) {
-
- Promise.resolve()
+ return Promise.resolve()
.then(() => uploadFile(formData))
.then(response => {
dispatch({
type: softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED,
response
});
-
dispatch({
- type: actionTypes.OPEN_UPLOAD_SCREEN
+ type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
+ payload:{}
});
+ loadSoftwareProductHeatCandidate(dispatch);
})
.catch(error => {
- dispatch({
- type: NotificationConstants.NOTIFY_ERROR,
- data: {title: 'File Upload Failed', msg: error.responseJSON.message}
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_ERROR,
+ data: {
+ title: i18n('File Upload Failed'),
+ msg: error.responseJSON.message,
+ cancelButtonText: i18n('Ok')
+ }
});
});
},
- openMainScreen(dispatch) {
- dispatch({
- type: actionTypes.OPEN_MAIN_SCREEN
- });
- }
+
+ processAndValidateHeat(dispatch, heatData, heatDataCache){
+ return isEqual(heatData, heatDataCache) ? Promise.resolve() :
+ updateHeatCandidate(dispatch, heatData)
+ .then(() => processAndValidateHeatCandidate(dispatch))
+ .then(() => dispatch({type: HeatSetupActions.FILL_HEAT_SETUP_CACHE, payload: cloneDeep(heatData)}));
+ },
+
+ downloadHeatFile(){
+ return downloadHeatFile();
+ },
};
export default UploadScreenActionHelper;
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenConstants.js b/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenConstants.js
deleted file mode 100644
index 2766a975ec..0000000000
--- a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenConstants.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import keyMirror from 'nfvo-utils/KeyMirror.js';
-
-export const actionTypes = keyMirror({
- FILE_UPLOADED: null,
- OPEN_UPLOAD_SCREEN: null,
- OPEN_ATTACHMENTS_SCREEN: null,
- OPEN_MAIN_SCREEN: null
-});
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenReducer.js b/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenReducer.js
deleted file mode 100644
index e73e028233..0000000000
--- a/openecomp-ui/src/sdc-app/heatvalidation/UploadScreenReducer.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import {actionTypes} from './UploadScreenConstants.js';
-
-
-export default (state = {}, action) => {
- switch (action.type) {
- case actionTypes.OPEN_UPLOAD_SCREEN:
- return {...state, showAttachments: true};
- case actionTypes.OPEN_MAIN_SCREEN:
- return {...state, showAttachments: false};
- default:
- return state;
- }
-};
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/attachments/Attachments.js b/openecomp-ui/src/sdc-app/heatvalidation/attachments/Attachments.js
deleted file mode 100644
index 2a6a992844..0000000000
--- a/openecomp-ui/src/sdc-app/heatvalidation/attachments/Attachments.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import {connect} from 'react-redux';
-import AttachmentsView from './AttachmentsView.jsx';
-import AttachmentsActionHelper from './AttachmentsActionHelper.js';
-
-
-const mapStateToProps = ({uploadScreen: {attachments}}) => {
- let {attachmentsTree = false, hoveredNode, selectedNode, errorList} = attachments;
- return {
- attachmentsTree,
- hoveredNode,
- selectedNode,
- errorList
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
-
- toggleExpanded: (path) => AttachmentsActionHelper.toggleExpanded(dispatch, {path}),
- onSelectNode: (nodeName) => AttachmentsActionHelper.onSelectNode(dispatch, {nodeName}),
- onUnselectNode: () => AttachmentsActionHelper.onUnselectNode(dispatch),
-
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(AttachmentsView);
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx b/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx
deleted file mode 100644
index 7e2dda8d47..0000000000
--- a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx
+++ /dev/null
@@ -1,190 +0,0 @@
-import React from 'react';
-import FontAwesome from 'react-fontawesome';
-import classNames from 'classnames';
-import Collapse from 'react-bootstrap/lib/Collapse.js';
-
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import {nodeTypes, mouseActions} from './AttachmentsConstants';
-
-const typeToIcon = Object.freeze({
- heat: 'building-o',
- volume: 'database',
- network: 'cloud',
- artifact: 'gear',
- env: 'server',
- other: 'cube'
-});
-
-const leftPanelWidth = 250;
-
-class SoftwareProductAttachmentsView extends React.Component {
-
- static propTypes = {
- attachmentsTree: React.PropTypes.object.isRequired
- };
- state = {
- treeWidth: '400',
- };
-
- render() {
- let {attachmentsTree, errorList = []} = this.props;
-
- let {treeWidth} = this.state;
- return (
- <div className='software-product-attachments'>
- <div className='software-product-view'>
- <div className='software-product-landing-view-right-side'>
- <div className='software-product-attachments-main'>
- <div className='software-product-attachments-tree' style={{'width' : treeWidth + 'px'}}>
- <div className='tree-wrapper'>
- {
- attachmentsTree && attachmentsTree.children && attachmentsTree.children.map((child, ind) => this.renderNode(child, [ind]))
- }
- </div>
- </div>
- <div className='software-product-attachments-separator' onMouseDown={e => this.onChangeTreeWidth(e)} />
- <div className='software-product-attachments-error-list'>
- {errorList.length ? this.renderErrorList(errorList) : <div className='no-errors'>{attachmentsTree.children ?
- i18n('VALIDATION SUCCESS') : i18n('THERE IS NO HEAT DATA TO PRESENT') }</div>}
- </div>
- </div>
- </div>
- </div>
- </div>
- );
- }
-
-
-
- renderNode(node, path) {
- let isFolder = node.children && node.children.length > 0;
- let {onSelectNode} = this.props;
- return (
- <div key={node.name} className='tree-block-inside'>
- {
- <div onDoubleClick={() => this.props.toggleExpanded(path)} className={this.getTreeRowClassName(node.name)}>
- {
- isFolder &&
- <div onClick={() => this.props.toggleExpanded(path)} className={classNames('tree-node-expander', {'tree-node-expander-collapsed': !node.expanded})}>
- <FontAwesome name='caret-down'/>
- </div>
- }
- {
-
- <span className='tree-node-icon'>
- <FontAwesome name={typeToIcon[node.type]}/>
- </span>
- }
- {
-
- <span onClick={() => onSelectNode(node.name)} className={this.getTreeTextClassName(node)}>
- {node.name}
- </span>
- }
- </div>
- }
- {
- isFolder &&
- <Collapse in={node.expanded}>
- <div className='tree-node-children'>
- {
- node.children.map((child, ind) => this.renderNode(child, [...path, ind]))
- }
- </div>
- </Collapse>
- }
- </div>
- );
- }
-
- createErrorList(errorList, node, parent) {
- if (node.errors) {
- node.errors.forEach(error => errorList.push({
- error,
- name: node.name,
- parentName: parent.name,
- type: node.type
- }));
- }
- if (node.children && node.children.length) {
- node.children.map((child) => this.createErrorList(errorList, child, node));
- }
- }
-
- renderErrorList(errors) {
- let prevError = {};
- let {selectedNode} = this.props;
- return errors.map(error => {
- let isSameNodeError = error.name === prevError.name && error.parentName === prevError.parentName;
- prevError = error;
-
- return (
- <div
- key={error.name + error.errorMessage + error.parentName}
-
- onClick={() => this.selectNode(error.name)}
- className={classNames('error-item', {'clicked': selectedNode === error.name, 'shifted': !isSameNodeError})}>
- <span className={classNames('error-item-file-type', {'strong': !isSameNodeError})}>
- {
- error.hasParent ?
- i18n('{type} {name} in {parentName}: ', {
- type: nodeTypes[error.type],
- name: error.name,
- parentName: error.parentName
- }) :
- i18n('{type} {name}: ', {
- type: nodeTypes[error.type],
- name: error.name
- })
- }
- </span>
- <span className={`error-item-file-type ${error.errorLevel}`}> {error.errorMessage} </span>
- </div>
- );
- });
- }
-
- selectNode(currentSelectedNode) {
- let {onUnselectNode, onSelectNode, selectedNode} = this.props;
- if (currentSelectedNode !== selectedNode) {
- onSelectNode(currentSelectedNode);
- }else{
- onUnselectNode();
- }
-
- }
-
- getTreeRowClassName(name) {
- let {hoveredNode, selectedNode} = this.props;
- return classNames({
- 'tree-node-row': true,
- 'tree-node-selected': name === hoveredNode,
- 'tree-node-clicked': name === selectedNode
- });
- }
-
- getTreeTextClassName(node) {
- let {selectedNode} = this.props;
- return classNames({
- 'tree-element-text': true,
- 'error-status': node.errors,
- 'error-status-selected': node.name === selectedNode
- });
- }
-
- 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);
- }
- }
-}
-
-export default SoftwareProductAttachmentsView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
index d39b2affd3..4945d33b23 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import LicenseModelActionHelper from './licenseModel/LicenseModelActionHelper.js';
import LicenseAgreementActionHelper from './licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
import FeatureGroupsActionHelper from './licenseModel/featureGroups/FeatureGroupsActionHelper.js';
@@ -29,9 +24,12 @@ import SoftwareProductNetworksActionHelper from './softwareProduct/networks/Soft
import SoftwareProductComponentsActionHelper from './softwareProduct/components/SoftwareProductComponentsActionHelper.js';
import SoftwareProductComponentProcessesActionHelper from './softwareProduct/components/processes/SoftwareProductComponentProcessesActionHelper.js';
import SoftwareProductComponentsNetworkActionHelper from './softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js';
+import SoftwareProductDependenciesActionHelper from './softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js';
+import OnboardActionHelper from './onboard/OnboardActionHelper.js';
import SoftwareProductComponentsMonitoringAction from './softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js';
import {actionTypes, enums} from './OnboardingConstants.js';
import {navigationItems as SoftwareProductNavigationItems, actionTypes as SoftwareProductActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import ActivityLogActionHelper from 'nfvo-components/activity-log/ActivityLogActionHelper.js';
import store from 'sdc-app/AppStore.js';
function setCurrentScreen(dispatch, screen, props = {}) {
@@ -39,7 +37,8 @@ function setCurrentScreen(dispatch, screen, props = {}) {
type: actionTypes.SET_CURRENT_SCREEN,
currentScreen: {
screen,
- props
+ props,
+ forceBreadCrumbsUpdate: true
}
});
}
@@ -48,21 +47,61 @@ function getCurrentLicenseModelVersion(licenseModelId) {
return store.getState().licenseModelList.find(({id}) => id === licenseModelId).version;
}
+function getCurrentSoftwareProductVersion(softwareProductId) {
+ return store.getState().softwareProductList.find(({id}) => id === softwareProductId).version;
+}
+
export default {
navigateToOnboardingCatalog(dispatch) {
LicenseModelActionHelper.fetchLicenseModels(dispatch);
+ LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
SoftwareProductActionHelper.fetchSoftwareProductList(dispatch);
+ SoftwareProductActionHelper.fetchFinalizedSoftwareProductList(dispatch);
+ OnboardActionHelper.resetOnboardStore(dispatch);
setCurrentScreen(dispatch, enums.SCREEN.ONBOARDING_CATALOG);
},
+ autoSaveBeforeNavigate(dispatch, {softwareProductId, version, vspComponentId, dataToSave}) {
+ if(softwareProductId) {
+ if(vspComponentId) {
+ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch, {
+ softwareProductId, version, vspComponentId,
+ componentData: dataToSave.componentData,
+ qdata: dataToSave.qdata
+ });
+ }
+ return SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {
+ softwareProduct: dataToSave.softwareProduct,
+ qdata: dataToSave.qdata
+ });
+ }
+ return Promise.resolve();
+ },
+
+ navigateToLicenseModelOverview(dispatch, {licenseModelId, version}) {
+ if (!version) {
+ version = getCurrentLicenseModelVersion(licenseModelId);
+ }
+
+ /**
+ * TODO change to specific rest
+ */
+
+ LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
+ LicenseModelActionHelper.fetchLicenseModelItems(dispatch, {licenseModelId, version}).then(() =>{
+ setCurrentScreen(dispatch, enums.SCREEN.LICENSE_MODEL_OVERVIEW, {licenseModelId, version});
+ });
+
+ });
+ },
navigateToLicenseAgreements(dispatch, {licenseModelId, version}) {
if(!version) {
version = getCurrentLicenseModelVersion(licenseModelId);
}
LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version});
LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
- setCurrentScreen(dispatch, enums.SCREEN.LICENSE_AGREEMENTS, {licenseModelId});
+ setCurrentScreen(dispatch, enums.SCREEN.LICENSE_AGREEMENTS, {licenseModelId, version});
});
},
@@ -71,7 +110,7 @@ export default {
version = getCurrentLicenseModelVersion(licenseModelId);
}
FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version});
- setCurrentScreen(dispatch, enums.SCREEN.FEATURE_GROUPS, {licenseModelId});
+ setCurrentScreen(dispatch, enums.SCREEN.FEATURE_GROUPS, {licenseModelId, version});
},
navigateToEntitlementPools(dispatch, {licenseModelId, version}) {
@@ -79,7 +118,7 @@ export default {
version = getCurrentLicenseModelVersion(licenseModelId);
}
EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
- setCurrentScreen(dispatch, enums.SCREEN.ENTITLEMENT_POOLS, {licenseModelId});
+ setCurrentScreen(dispatch, enums.SCREEN.ENTITLEMENT_POOLS, {licenseModelId, version});
},
navigateToLicenseKeyGroups(dispatch, {licenseModelId, version}) {
@@ -87,13 +126,30 @@ export default {
version = getCurrentLicenseModelVersion(licenseModelId);
}
LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
- setCurrentScreen(dispatch, enums.SCREEN.LICENSE_KEY_GROUPS, {licenseModelId});
+ setCurrentScreen(dispatch, enums.SCREEN.LICENSE_KEY_GROUPS, {licenseModelId, version});
+ },
+
+ navigateToLicenseModelActivityLog(dispatch, {licenseModelId, version}){
+ if(!version) {
+ version = getCurrentLicenseModelVersion(licenseModelId);
+ }
+ ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: licenseModelId, versionId: version.id});
+ setCurrentScreen(dispatch, enums.SCREEN.ACTIVITY_LOG, {licenseModelId, version});
},
navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, licenseModelId, version, licensingVersion}) {
+
+ if (!version) {
+ version = getCurrentSoftwareProductVersion(softwareProductId);
+ }
+
+ SoftwareProductComponentsActionHelper.clearComponentsStore(dispatch);
SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version}).then(response => {
if(!licensingVersion) {
licensingVersion = response[0].licensingVersion;
+ if (!licensingVersion) {
+ licensingVersion = {id: '1.0', label: '1.0'};
+ }
}
if (!licenseModelId) {
licenseModelId = response[0].vendorId;
@@ -101,74 +157,84 @@ export default {
SoftwareProductActionHelper.loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion});
SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
-
+ SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version});
setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, {softwareProductId, licenseModelId, version});
});
},
- navigateToSoftwareProductDetails(dispatch, {softwareProductId}) {
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, {softwareProductId});
+ navigateToSoftwareProductDetails(dispatch, {softwareProductId, version}) {
+ SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DETAILS, {softwareProductId, version});
},
- navigateToSoftwareProductAttachments(dispatch, {softwareProductId}) {
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS, {softwareProductId});
+ navigateToSoftwareProductAttachments(dispatch, {softwareProductId, version}) {
+ SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS, {softwareProductId, version});
},
navigateToSoftwareProductProcesses(dispatch, {softwareProductId, version}) {
if (softwareProductId) {
SoftwareProductProcessesActionHelper.fetchProcessesList(dispatch, {softwareProductId, version});
}
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES, {softwareProductId});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES, {softwareProductId, version});
},
navigateToSoftwareProductNetworks(dispatch, {softwareProductId, version}) {
if (softwareProductId) {
SoftwareProductNetworksActionHelper.fetchNetworksList(dispatch, {softwareProductId, version});
}
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS, {softwareProductId});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS, {softwareProductId, version});
+ },
+
+ navigateToSoftwareProductDependencies(dispatch, {softwareProductId, version}) {
+ SoftwareProductDependenciesActionHelper.fetchDependencies(dispatch, {softwareProductId, version});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES, {softwareProductId, version});
+ },
+
+ navigateToSoftwareProductComponents(dispatch, {softwareProductId, version}) {
+ SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS, {softwareProductId, version});
},
- navigateToSoftwareProductComponents(dispatch, {softwareProductId}) {
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS, {softwareProductId});
+ navigateToSoftwareProductActivityLog(dispatch, {softwareProductId, version}){
+ ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: softwareProductId, versionId: version.id});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG, {softwareProductId, version});
},
navigateToSoftwareProductComponentProcesses(dispatch, {softwareProductId, componentId, version}) {
if (componentId && softwareProductId) {
SoftwareProductComponentProcessesActionHelper.fetchProcessesList(dispatch, {componentId, softwareProductId, version});
}
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES, {softwareProductId, componentId});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES, {softwareProductId, componentId, version});
},
- navigateToSoftwareProductComponentMonitoring(dispatch, {softwareProductId, componentId}){
- if (componentId && softwareProductId) {
- SoftwareProductComponentsMonitoringAction.fetchExistingFiles(dispatch, {componentId, softwareProductId});
+ navigateToSoftwareProductComponentMonitoring(dispatch, {softwareProductId, version, componentId}){
+ if (componentId && softwareProductId && version) {
+ SoftwareProductComponentsMonitoringAction.fetchExistingFiles(dispatch, {componentId, softwareProductId, version});
}
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING, {softwareProductId, componentId});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING, {softwareProductId, componentId, version});
},
- navigateToComponentStorage(dispatch, {softwareProductId, componentId}) {
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE, {softwareProductId, componentId});
+ navigateToComponentStorage(dispatch, {softwareProductId, componentId, version}) {
+ SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE, {softwareProductId, version, componentId});
},
- navigateToComponentCompute(dispatch, {softwareProductId, componentId}) {
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE, {softwareProductId, componentId});
+ navigateToComponentCompute(dispatch, {softwareProductId, componentId, version}) {
+ SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE, {softwareProductId, version, componentId});
},
navigateToComponentNetwork(dispatch, {softwareProductId, componentId, version}) {
SoftwareProductComponentsNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version});
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK, {softwareProductId, componentId});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK, {softwareProductId, version, componentId});
},
navigateToSoftwareProductComponentGeneral(dispatch, {softwareProductId, componentId, version}) {
if (componentId && softwareProductId) {
SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
- SoftwareProductComponentsActionHelper.fetchSoftwareProductComponentQuestionnaire(dispatch, {
- softwareProductId,
- vspComponentId: componentId,
- version
- });
}
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL, {softwareProductId, componentId});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL, {softwareProductId, version, componentId});
},
navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, {softwareProductId, componentId, version}) {
@@ -182,7 +248,9 @@ export default {
});
},
- navigateToComponentLoadBalancing(dispatch, {softwareProductId, componentId}) {
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING, {softwareProductId, componentId});
+ navigateToComponentLoadBalancing(dispatch, {softwareProductId, componentId, version}) {
+ SoftwareProductComponentsActionHelper.fetchSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, version});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING, {softwareProductId, version, componentId});
}
+
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingCatalog.js b/openecomp-ui/src/sdc-app/onboarding/OnboardingCatalog.js
deleted file mode 100644
index 4772c8d9af..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingCatalog.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import {connect} from 'react-redux';
-import {default as OnboardingCatalogView, catalogItemTypes} from './OnboardingCatalogView.jsx';
-import OnboardingActionHelper from './OnboardingActionHelper.js';
-import LicenseModelCreationActionHelper from './licenseModel/creation/LicenseModelCreationActionHelper.js';
-import SoftwareProductCreationActionHelper from './softwareProduct/creation/SoftwareProductCreationActionHelper.js';
-
-
-const mapStateToProps = ({licenseModelList, softwareProductList, softwareProduct: {softwareProductCreation}, licenseModel: {licenseModelCreation}}) => {
-
- let modalToShow;
-
- if(licenseModelCreation.data) {
- modalToShow = catalogItemTypes.LICENSE_MODEL;
- } else if(softwareProductCreation.showModal && softwareProductCreation.data) {
- modalToShow = catalogItemTypes.SOFTWARE_PRODUCT;
- }
-
- return {
- licenseModelList,
- softwareProductList,
- modalToShow
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
- onSelectLicenseModel({id: licenseModelId}) {
- OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId});
- },
- onSelectSoftwareProduct(softwareProduct) {
- let {id: softwareProductId, vendorId: licenseModelId, licensingVersion} = softwareProduct;
- OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, licenseModelId, licensingVersion});
- },
- onAddSoftwareProductClick: () => SoftwareProductCreationActionHelper.open(dispatch),
- onAddLicenseModelClick: () => LicenseModelCreationActionHelper.open(dispatch)
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(OnboardingCatalogView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingCatalogView.jsx b/openecomp-ui/src/sdc-app/onboarding/OnboardingCatalogView.jsx
deleted file mode 100644
index f2a9db1342..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingCatalogView.jsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import React from 'react';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import Modal from 'nfvo-components/modal/Modal.jsx';
-import objectValues from 'lodash/values.js';
-import LicenseModelCreation from './licenseModel/creation/LicenseModelCreation.js';
-import SoftwareProductCreation from './softwareProduct/creation/SoftwareProductCreation.js';
-import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
-import classnames from 'classnames';
-import ExpandableInput from 'nfvo-components/input/ExpandableInput.jsx';
-
-export const catalogItemTypes = Object.freeze({
- LICENSE_MODEL: 'license-model',
- SOFTWARE_PRODUCT: 'software-product'
-});
-
-const catalogItemTypeClasses = {
- LICENSE_MODEL: 'license-model-type',
- SOFTWARE_PRODUCT: 'software-product-type'
-};
-
-class OnboardingCatalogView extends React.Component {
-
- constructor(props) {
- super(props);
- this.state = {searchValue: ''};
- this.handleSearch = this.handleSearch.bind(this);
- }
-
- handleSearch(event){
- this.setState({searchValue: event.target.value});
- }
-
- static propTypes = {
- licenseModelList: React.PropTypes.array,
- softwareProductList: React.PropTypes.array,
- modalToShow: React.PropTypes.oneOf(objectValues(catalogItemTypes)),
- onSelectLicenseModel: React.PropTypes.func.isRequired,
- onSelectSoftwareProduct: React.PropTypes.func.isRequired,
- onAddLicenseModelClick: React.PropTypes.func.isRequired,
- onAddSoftwareProductClick: React.PropTypes.func.isRequired
- };
-
- getModalDetails() {
- const {modalToShow} = this.props;
- switch (modalToShow) {
- case catalogItemTypes.LICENSE_MODEL:
- return {
- title: i18n('New License Model'),
- element: <LicenseModelCreation/>
- };
- case catalogItemTypes.SOFTWARE_PRODUCT:
- return {
- title: i18n('New Software Product'),
- element: <SoftwareProductCreation/>
- };
- }
- }
-
- render() {
- const modalDetails = this.getModalDetails();
- const {licenseModelList, softwareProductList, onSelectLicenseModel, onSelectSoftwareProduct, onAddLicenseModelClick, onAddSoftwareProductClick, modalToShow} = this.props;
-
- return (
- <div className='catalog-view'>
- <div className='catalog-header'>
- <div className='catalog-header-title'>{i18n('Onboarding Catalog')}</div>
- <ExpandableInput
- onChange={this.handleSearch}
- iconType='search'/>
- </div>
- <div className='catalog-list'>
-
- <div className='create-catalog-item tile'>
- <div className='plus-section'>
- <div className='plus-icon-button'/>
- <span>{i18n('ADD')}</span>
- </div>
- <div className='primary-btn new-license-model'>
- <span
- className='primary-btn-text'
- onClick={() => onAddLicenseModelClick()}>{i18n('New License Model')}</span></div>
- <div className='primary-btn'>
- <span
- className='primary-btn-text'
- onClick={() => onAddSoftwareProductClick()}>{i18n('New Vendor Software Product')}</span>
- </div>
- </div>
- {licenseModelList.filter(vlm => vlm.vendorName.toLowerCase().indexOf(this.state.searchValue.toLowerCase()) > -1).map(licenseModel => this.renderTile(
- {
- ...licenseModel,
- name: licenseModel.vendorName
- },
- catalogItemTypeClasses.LICENSE_MODEL,
- () => onSelectLicenseModel(licenseModel))
- )}
- {softwareProductList.filter(vsp => vsp.name.toLowerCase().indexOf(this.state.searchValue.toLowerCase()) > -1).map(softwareProduct => this.renderTile(softwareProduct,
- catalogItemTypeClasses.SOFTWARE_PRODUCT,
- () => onSelectSoftwareProduct(softwareProduct))
- )}
- </div>
- <Modal
- show={Boolean(modalDetails)}
- className={`${this.getCatalogItemTypeClassByItemType(modalToShow)}-modal`}>
- <Modal.Header>
- <Modal.Title>{modalDetails && modalDetails.title}</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- {
- modalDetails && modalDetails.element
- }
- </Modal.Body>
- </Modal>
- </div>
- );
-
- }
-
- getCatalogItemTypeClassByItemType(catalogItemType) {
- switch (catalogItemType) {
- case catalogItemTypes.LICENSE_MODEL:
- return catalogItemTypeClasses.LICENSE_MODEL;
- case catalogItemTypes.SOFTWARE_PRODUCT:
- return catalogItemTypeClasses.SOFTWARE_PRODUCT;
- }
- }
-
- renderTile(catalogItemData, catalogItemTypeClass, onSelect) {
- let {status: itemStatus} = VersionControllerUtils.getCheckOutStatusKindByUserID(catalogItemData.status, catalogItemData.lockingUser);
- return (
- <div className='catalog-tile tile' key={catalogItemData.id} onClick={() => onSelect()}>
- <div className={`catalog-tile-type ${catalogItemTypeClass}`}/>
- <div className='catalog-tile-icon'>
- <div className={`icon ${catalogItemTypeClass}-icon`}></div>
- </div>
- <div className='catalog-tile-content'>
- <div className='catalog-tile-item-details'>
- <div className='catalog-tile-item-name'>{catalogItemData.name}</div>
- <div className='catalog-tile-item-version'>V {catalogItemData.version}</div>
- </div>
- <div className={classnames('catalog-tile-check-in-status', {'sprite-new checkout-editable-status-icon': itemStatus === 'Locked'})}>
- </div>
- </div>
- </div>
- );
- }
-}
-export default OnboardingCatalogView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingConstants.js b/openecomp-ui/src/sdc-app/onboarding/OnboardingConstants.js
index d9c177f606..7811950073 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
@@ -29,16 +24,21 @@ export const enums = keyMirror({
BREADCRUMS: {
LICENSE_MODEL: 'LICENSE_MODEL',
+ LICENSE_MODEL_OVERVIEW: 'LICENSE_MODEL_OVERVIEW',
LICENSE_AGREEMENTS: 'LICENSE_AGREEMENTS',
FEATURE_GROUPS: 'FEATURE_GROUPS',
ENTITLEMENT_POOLS: 'ENTITLEMENT_POOLS',
LICENSE_KEY_GROUPS: 'LICENSE_KEY_GROUPS',
+ ACTIVITY_LOG: 'ACTIVITY_LOG',
SOFTWARE_PRODUCT: 'SOFTWARE_PRODUCT',
+ SOFTWARE_PRODUCT_LANDING_PAGE: 'SOFTWARE_PRODUCT_LANDING_PAGE',
SOFTWARE_PRODUCT_DETAILS: 'SOFTWARE_PRODUCT_DETAILS',
SOFTWARE_PRODUCT_ATTACHMENTS: 'SOFTWARE_PRODUCT_ATTACHMENTS',
SOFTWARE_PRODUCT_PROCESSES: 'SOFTWARE_PRODUCT_PROCESSES',
SOFTWARE_PRODUCT_NETWORKS: 'SOFTWARE_PRODUCT_NETWORKS',
+ SOFTWARE_PRODUCT_DEPENDENCIES: 'SOFTWARE_PRODUCT_DEPENDENCIES',
+ SOFTWARE_PRODUCT_ACTIVITY_LOG: 'SOFTWARE_PRODUCT_ACTIVITY_LOG',
SOFTWARE_PRODUCT_COMPONENTS: 'SOFTWARE_PRODUCT_COMPONENTS',
SOFTWARE_PRODUCT_COMPONENT_PROCESSES: 'SOFTWARE_PRODUCT_COMPONENT_PROCESSES',
SOFTWARE_PRODUCT_COMPONENT_STORAGE: 'SOFTWARE_PRODUCT_COMPONENT_STORAGE',
@@ -50,16 +50,20 @@ export const enums = keyMirror({
SCREEN: {
ONBOARDING_CATALOG: null,
+ LICENSE_MODEL_OVERVIEW: null,
LICENSE_AGREEMENTS: null,
FEATURE_GROUPS: null,
ENTITLEMENT_POOLS: null,
LICENSE_KEY_GROUPS: null,
+ ACTIVITY_LOG: null,
SOFTWARE_PRODUCT_LANDING_PAGE: null,
SOFTWARE_PRODUCT_DETAILS: null,
SOFTWARE_PRODUCT_ATTACHMENTS: null,
SOFTWARE_PRODUCT_PROCESSES: null,
SOFTWARE_PRODUCT_NETWORKS: null,
+ SOFTWARE_PRODUCT_DEPENDENCIES: null,
+ SOFTWARE_PRODUCT_ACTIVITY_LOG: null,
SOFTWARE_PRODUCT_COMPONENTS: null,
SOFTWARE_PRODUCT_COMPONENT_PROCESSES: null,
SOFTWARE_PRODUCT_COMPONENT_COMPUTE: null,
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx b/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
index c4627b11b3..e8a844b03f 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import ReactDOM from 'react-dom';
import {connect} from 'react-redux';
@@ -9,8 +24,12 @@ import Application from 'sdc-app/Application.jsx';
import store from 'sdc-app/AppStore.js';
import Configuration from 'sdc-app/config/Configuration.js';
-import OnboardingCatalog from './OnboardingCatalog.js';
+import Onboard from './onboard/Onboard.js';
import LicenseModel from './licenseModel/LicenseModel.js';
+import LicenseModelOverview from './licenseModel/overview/LicenseModelOverview.js';
+import ActivityLog from 'nfvo-components/activity-log/ActivityLog.js';
+import {doesHeatDataExist} from './softwareProduct/attachments/SoftwareProductAttachmentsUtils.js';
+
import LicenseAgreementListEditor from './licenseModel/licenseAgreement/LicenseAgreementListEditor.js';
import FeatureGroupListEditor from './licenseModel/featureGroups/FeatureGroupListEditor.js';
import LicenseKeyGroupsListEditor from './licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js';
@@ -21,6 +40,7 @@ import SoftwareProductDetails from './softwareProduct/details/SoftwareProductDe
import SoftwareProductAttachments from './softwareProduct/attachments/SoftwareProductAttachments.js';
import SoftwareProductProcesses from './softwareProduct/processes/SoftwareProductProcesses.js';
import SoftwareProductNetworks from './softwareProduct/networks/SoftwareProductNetworks.js';
+import SoftwareProductDependencies from './softwareProduct/dependencies/SoftwareProductDependencies.js';
import SoftwareProductComponentsList from './softwareProduct/components/SoftwareProductComponentsList.js';
import SoftwareProductComponentProcessesList from './softwareProduct/components/processes/SoftwareProductComponentProcessesList.js';
import SoftwareProductComponentStorage from './softwareProduct/components/storage/SoftwareProductComponentStorage.js';
@@ -30,8 +50,12 @@ import SoftwareProductComponentsCompute from './softwareProduct/components/compu
import SoftwareProductComponentLoadBalancing from './softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancing.js';
import SoftwareProductComponentsMonitoring from './softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js';
import {navigationItems as SoftwareProductNavigationItems, actionTypes as SoftwareProductActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import {statusEnum as VCItemStatus} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+
+import HeatSetupActionHelper from './softwareProduct/attachments/setup/HeatSetupActionHelper.js';
-import {enums} from './OnboardingConstants.js';
+import {actionTypes, enums} from './OnboardingConstants.js';
import OnboardingActionHelper from './OnboardingActionHelper.js';
@@ -64,17 +88,21 @@ class OnboardingView extends React.Component {
{(() => {
switch (screen) {
case enums.SCREEN.ONBOARDING_CATALOG:
- return <OnboardingCatalog {...props}/>;
+ return <Onboard {...props}/>;
case enums.SCREEN.LICENSE_AGREEMENTS:
case enums.SCREEN.FEATURE_GROUPS:
case enums.SCREEN.ENTITLEMENT_POOLS:
case enums.SCREEN.LICENSE_KEY_GROUPS:
+ case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+ case enums.SCREEN.ACTIVITY_LOG:
return (
<LicenseModel currentScreen={currentScreen}>
{
(()=>{
switch(screen) {
+ case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+ return <LicenseModelOverview {...props}/>;
case enums.SCREEN.LICENSE_AGREEMENTS:
return <LicenseAgreementListEditor {...props}/>;
case enums.SCREEN.FEATURE_GROUPS:
@@ -83,6 +111,8 @@ class OnboardingView extends React.Component {
return <EntitlementPoolsListEditor {...props}/>;
case enums.SCREEN.LICENSE_KEY_GROUPS:
return <LicenseKeyGroupsListEditor {...props}/>;
+ case enums.SCREEN.ACTIVITY_LOG:
+ return <ActivityLog {...props}/>;
}
})()
}
@@ -94,6 +124,7 @@ class OnboardingView extends React.Component {
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_COMPONENTS:
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
@@ -102,6 +133,7 @@ class OnboardingView extends React.Component {
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+ case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
return (
<SoftwareProduct currentScreen={currentScreen}>
{
@@ -112,11 +144,13 @@ class OnboardingView extends React.Component {
case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
return <SoftwareProductDetails {...props}/>;
case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
- return <SoftwareProductAttachments className='no-padding-content-area' {...props} />;
+ return <SoftwareProductAttachments className='no-padding-content-area' {...props} />;
case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
return <SoftwareProductProcesses {...props}/>;
case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
return <SoftwareProductNetworks {...props}/>;
+ case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
+ return <SoftwareProductDependencies {...props} />;
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
return <SoftwareProductComponentsList {...props}/>;
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
@@ -133,6 +167,8 @@ class OnboardingView extends React.Component {
return <SoftwareProductComponentLoadBalancing{...props}/>;
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
return <SoftwareProductComponentsMonitoring {...props}/>;
+ case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
+ return <ActivityLog {...props}/>;
}
})()
}
@@ -184,151 +220,195 @@ export default class OnboardingPunchOut {
handleData(data) {
let {breadcrumbs: {selectedKeys = []} = {}} = data;
let dispatch = action => store.dispatch(action);
- let {softwareProductList, softwareProduct: {softwareProductEditor: {data: {id: currentSoftwareProductId, version: currentSoftwareProductVersion} = {}}},
- licenseModelList, licenseModel: {licenseModelEditor: {data: {id: currentLicenseModelId, version: currentLicenseModelVersion} = {}}}} = store.getState();
-
+ let {currentScreen, softwareProductList, softwareProduct: {softwareProductEditor: {data: vspData = {}},
+ softwareProductComponents = {}, softwareProductQuestionnaire = {}},
+ licenseModelList, licenseModel: {licenseModelEditor: {data: {id: currentLicenseModelId, version: currentLicenseModelVersion} = {}}}} = store.getState();
+ let {id: currentSoftwareProductId, version: currentSoftwareProductVersion} = vspData;
+ let {componentEditor: {data: componentData = {}, qdata: componentQData = {}}} = softwareProductComponents;
if (this.programmaticBreadcrumbsUpdate) {
this.prevSelectedKeys = selectedKeys;
this.programmaticBreadcrumbsUpdate = false;
return;
}
-
if (!isEqual(selectedKeys, this.prevSelectedKeys)) {
this.breadcrumbsPrefixSelected = isEqual(selectedKeys, this.prevSelectedKeys && this.prevSelectedKeys.slice(0, selectedKeys.length));
- this.prevSelectedKeys = selectedKeys;
- if (selectedKeys.length === 0) {
- OnboardingActionHelper.navigateToOnboardingCatalog(dispatch);
- } else if (selectedKeys.length === 1 || selectedKeys[1] === enums.BREADCRUMS.LICENSE_MODEL) {
- let [licenseModelId, , licenseModelScreen] = selectedKeys;
- if (!licenseModelScreen) {
- licenseModelScreen = enums.BREADCRUMS.LICENSE_AGREEMENTS;
- }
- if(currentLicenseModelId !== licenseModelId) {
- currentLicenseModelVersion = licenseModelList.find(lm => lm.id === licenseModelId).version;
- }
- switch (licenseModelScreen) {
- case enums.BREADCRUMS.LICENSE_AGREEMENTS:
- OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId, version: currentLicenseModelVersion});
- break;
- case enums.BREADCRUMS.FEATURE_GROUPS:
- OnboardingActionHelper.navigateToFeatureGroups(dispatch, {licenseModelId, version: currentLicenseModelVersion});
- break;
- case enums.BREADCRUMS.ENTITLEMENT_POOLS:
- OnboardingActionHelper.navigateToEntitlementPools(dispatch, {licenseModelId, version: currentLicenseModelVersion});
- break;
- case enums.BREADCRUMS.LICENSE_KEY_GROUPS:
- OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, {licenseModelId, version: currentLicenseModelVersion});
- break;
- }
- } else if (selectedKeys.length <= 4 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT) {
- let [licenseModelId, , softwareProductId, softwareProductScreen] = selectedKeys;
- let softwareProduct = softwareProductId ?
- softwareProductList.find(({id}) => id === softwareProductId) :
- softwareProductList.find(({vendorId}) => vendorId === licenseModelId);
- if (!softwareProductId) {
- softwareProductId = softwareProduct.id;
- }
- if(currentSoftwareProductId !== softwareProductId) {
- currentSoftwareProductVersion = softwareProduct.version;
- }
- switch (softwareProductScreen) {
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_DETAILS:
- OnboardingActionHelper.navigateToSoftwareProductDetails(dispatch, {softwareProductId});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS:
- OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_PROCESSES:
- OnboardingActionHelper.navigateToSoftwareProductProcesses(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_NETWORKS:
- OnboardingActionHelper.navigateToSoftwareProductNetworks(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS:
- OnboardingActionHelper.navigateToSoftwareProductComponents(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
- dispatch({
- type: SoftwareProductActionTypes.TOGGLE_NAVIGATION_ITEM,
- mapOfExpandedIds: {
- [SoftwareProductNavigationItems.COMPONENTS]: true
- }
- });
- break;
- default:
- OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
- break;
- }
- }else if (selectedKeys.length === 5 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT && selectedKeys[3] === enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS) {
- let [licenseModelId, , softwareProductId, , componentId] = selectedKeys;
- let softwareProduct = softwareProductId ?
- softwareProductList.find(({id}) => id === softwareProductId) :
- softwareProductList.find(({vendorId}) => vendorId === licenseModelId);
- if (!softwareProductId) {
- softwareProductId = softwareProduct.id;
- }
- if(currentSoftwareProductId !== softwareProductId) {
- currentSoftwareProductVersion = softwareProduct.version;
- }
- OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, {softwareProductId, componentId, version: currentSoftwareProductVersion});
- }else if (selectedKeys.length === 6 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT && selectedKeys[3] === enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS) {
- let [licenseModelId, , softwareProductId, , componentId, componentScreen] = selectedKeys;
- let softwareProduct = softwareProductId ?
- softwareProductList.find(({id}) => id === softwareProductId) :
- softwareProductList.find(({vendorId}) => vendorId === licenseModelId);
- if (!softwareProductId) {
- softwareProductId = softwareProduct.id;
- }
- if(currentSoftwareProductId !== softwareProductId) {
- currentSoftwareProductVersion = softwareProduct.version;
- }
- switch (componentScreen) {
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
- OnboardingActionHelper.navigateToSoftwareProductComponentGeneral(dispatch, {softwareProductId, componentId, version: currentSoftwareProductVersion});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
- OnboardingActionHelper.navigateToComponentCompute(dispatch, {softwareProductId, componentId});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
- OnboardingActionHelper.navigateToComponentLoadBalancing(dispatch, {softwareProductId, componentId});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
- OnboardingActionHelper.navigateToComponentNetwork(dispatch, {softwareProductId, componentId});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
- OnboardingActionHelper.navigateToComponentStorage(dispatch, {softwareProductId, componentId});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
- OnboardingActionHelper.navigateToSoftwareProductComponentProcesses(dispatch, {softwareProductId, componentId});
- break;
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
- OnboardingActionHelper.navigateToSoftwareProductComponentMonitoring(dispatch, {softwareProductId, componentId});
- break;
- }
- } else {
- console.error('Unknown breadcrumbs path: ', selectedKeys);
+ const [, screenType, prevVspId, , prevComponentId] = this.prevSelectedKeys || [];
+ let preNavigate = Promise.resolve();
+ if(screenType === enums.BREADCRUMS.SOFTWARE_PRODUCT && vspData.status === VCItemStatus.CHECK_OUT_STATUS && VersionControllerUtils.isCheckedOutByCurrentUser(vspData)) {
+ let dataToSave = prevVspId ? prevComponentId ? {componentData, qdata: componentQData} : {softwareProduct: vspData, qdata: softwareProductQuestionnaire.qdata} : {};
+ preNavigate = OnboardingActionHelper.autoSaveBeforeNavigate(dispatch, {
+ softwareProductId: prevVspId,
+ version: currentSoftwareProductVersion,
+ vspComponentId: prevComponentId,
+ dataToSave
+ });
}
+
+ let {currentScreen: {props: {softwareProductId}}, softwareProduct: {softwareProductAttachments: {heatSetup, heatSetupCache}}} = store.getState();
+ let heatSetupPopupPromise = currentScreen.screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS ?
+ HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) :
+ Promise.resolve();
+ Promise.all([preNavigate, heatSetupPopupPromise]).then(() => {
+ this.prevSelectedKeys = selectedKeys;
+ if (selectedKeys.length === 0) {
+ OnboardingActionHelper.navigateToOnboardingCatalog(dispatch);
+ } else if (selectedKeys.length === 1 || selectedKeys[1] === enums.BREADCRUMS.LICENSE_MODEL) {
+ let [licenseModelId, , licenseModelScreen] = selectedKeys;
+ if (!licenseModelScreen) {
+ licenseModelScreen = enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW;
+ }
+ if (currentLicenseModelId !== licenseModelId) {
+ currentLicenseModelVersion = licenseModelList.find(lm => lm.id === licenseModelId).version;
+ }
+ switch (licenseModelScreen) {
+ case enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW:
+ OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, {licenseModelId, version: currentLicenseModelVersion});
+ break;
+ case enums.BREADCRUMS.LICENSE_AGREEMENTS:
+ OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId, version: currentLicenseModelVersion});
+ break;
+ case enums.BREADCRUMS.FEATURE_GROUPS:
+ OnboardingActionHelper.navigateToFeatureGroups(dispatch, {licenseModelId, version: currentLicenseModelVersion});
+ break;
+ case enums.BREADCRUMS.ENTITLEMENT_POOLS:
+ OnboardingActionHelper.navigateToEntitlementPools(dispatch, {licenseModelId, version: currentLicenseModelVersion});
+ break;
+ case enums.BREADCRUMS.LICENSE_KEY_GROUPS:
+ OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, {licenseModelId, version: currentLicenseModelVersion});
+ break;
+ case enums.BREADCRUMS.ACTIVITY_LOG:
+ OnboardingActionHelper.navigateToLicenseModelActivityLog(dispatch, {licenseModelId, version: currentLicenseModelVersion});
+ break;
+ }
+ } else if (selectedKeys.length <= 4 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT) {
+ let [licenseModelId, , softwareProductId, softwareProductScreen] = selectedKeys;
+ let softwareProduct = softwareProductId ?
+ softwareProductList.find(({id}) => id === softwareProductId) :
+ softwareProductList.find(({vendorId}) => vendorId === licenseModelId);
+ if (!softwareProductId) {
+ softwareProductId = softwareProduct.id;
+ }
+ if (currentSoftwareProductId !== softwareProductId) {
+ currentSoftwareProductVersion = softwareProduct.version;
+ }
+ switch (softwareProductScreen) {
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_LANDING_PAGE:
+ OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_DETAILS:
+ OnboardingActionHelper.navigateToSoftwareProductDetails(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS:
+ OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_PROCESSES:
+ OnboardingActionHelper.navigateToSoftwareProductProcesses(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_NETWORKS:
+ OnboardingActionHelper.navigateToSoftwareProductNetworks(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES:
+ OnboardingActionHelper.navigateToSoftwareProductDependencies(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_ACTIVITY_LOG:
+ OnboardingActionHelper.navigateToSoftwareProductActivityLog(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS:
+ OnboardingActionHelper.navigateToSoftwareProductComponents(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ dispatch({
+ type: SoftwareProductActionTypes.TOGGLE_NAVIGATION_ITEM,
+ mapOfExpandedIds: {
+ [SoftwareProductNavigationItems.COMPONENTS]: true
+ }
+ });
+ break;
+ default:
+ OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version: currentSoftwareProductVersion});
+ break;
+ }
+ } else if (selectedKeys.length === 5 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT && selectedKeys[3] === enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS) {
+ let [licenseModelId, , softwareProductId, , componentId] = selectedKeys;
+ let softwareProduct = softwareProductId ?
+ softwareProductList.find(({id}) => id === softwareProductId) :
+ softwareProductList.find(({vendorId}) => vendorId === licenseModelId);
+ if (!softwareProductId) {
+ softwareProductId = softwareProduct.id;
+ }
+ if (currentSoftwareProductId !== softwareProductId) {
+ currentSoftwareProductVersion = softwareProduct.version;
+ }
+ OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, {softwareProductId, componentId, version: currentSoftwareProductVersion});
+ } else if (selectedKeys.length === 6 && selectedKeys[1] === enums.BREADCRUMS.SOFTWARE_PRODUCT && selectedKeys[3] === enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS) {
+ let [licenseModelId, , softwareProductId, , componentId, componentScreen] = selectedKeys;
+ let softwareProduct = softwareProductId ?
+ softwareProductList.find(({id}) => id === softwareProductId) :
+ softwareProductList.find(({vendorId}) => vendorId === licenseModelId);
+ if (!softwareProductId) {
+ softwareProductId = softwareProduct.id;
+ }
+ if (currentSoftwareProductId !== softwareProductId) {
+ currentSoftwareProductVersion = softwareProduct.version;
+ }
+ switch (componentScreen) {
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
+ OnboardingActionHelper.navigateToSoftwareProductComponentGeneral(dispatch, {softwareProductId, componentId, version: currentSoftwareProductVersion});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
+ OnboardingActionHelper.navigateToComponentCompute(dispatch, {softwareProductId, componentId});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
+ OnboardingActionHelper.navigateToComponentLoadBalancing(dispatch, {softwareProductId, componentId});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
+ OnboardingActionHelper.navigateToComponentNetwork(dispatch, {softwareProductId, componentId});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
+ OnboardingActionHelper.navigateToComponentStorage(dispatch, {softwareProductId, componentId});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
+ OnboardingActionHelper.navigateToSoftwareProductComponentProcesses(dispatch, {softwareProductId, componentId});
+ break;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
+ OnboardingActionHelper.navigateToSoftwareProductComponentMonitoring(dispatch, {softwareProductId, componentId});
+ break;
+ }
+ } else {
+ console.error('Unknown breadcrumbs path: ', selectedKeys);
+ }
+ }).catch(() => {
+ store.dispatch({
+ type: actionTypes.SET_CURRENT_SCREEN,
+ currentScreen: {
+ ...currentScreen,
+ forceBreadCrumbsUpdate: true
+ }
+ });
+ });
}
}
handleStoreChange() {
- let {currentScreen, licenseModelList, softwareProductList} = store.getState();
- let breadcrumbsData = {currentScreen, licenseModelList, softwareProductList};
-
- if (!isEqual(breadcrumbsData, this.prevBreadcrumbsData) || this.breadcrumbsPrefixSelected) {
+ let {currentScreen, licenseModelList, softwareProductList,
+ softwareProduct: {softwareProductComponents: {componentsList}, softwareProductAttachments: {heatSetup}}} = store.getState();
+ let breadcrumbsData = {currentScreen, licenseModelList, softwareProductList, componentsList, heatSetup};
+ if (currentScreen.forceBreadCrumbsUpdate || !isEqual(breadcrumbsData, this.prevBreadcrumbsData) || this.breadcrumbsPrefixSelected) {
this.prevBreadcrumbsData = breadcrumbsData;
this.breadcrumbsPrefixSelected = false;
this.programmaticBreadcrumbsUpdate = true;
-
let breadcrumbs = this.buildBreadcrumbs(breadcrumbsData);
this.onEvent('breadcrumbsupdated', breadcrumbs);
+ store.dispatch({
+ type: actionTypes.SET_CURRENT_SCREEN,
+ currentScreen: {
+ ...currentScreen,
+ forceBreadCrumbsUpdate: false
+ }
+ });
}
}
- buildBreadcrumbs({currentScreen: {screen, props}, licenseModelList, softwareProductList}) {
- let componentsList;
- if(props.componentId) {
- componentsList = store.getState().softwareProduct.softwareProductComponents.componentsList;
- }
+ buildBreadcrumbs({currentScreen: {screen, props}, licenseModelList, softwareProductList, componentsList, heatSetup}) {
let screenToBreadcrumb;
switch (screen) {
case enums.SCREEN.ONBOARDING_CATALOG:
@@ -338,11 +418,15 @@ export default class OnboardingPunchOut {
case enums.SCREEN.FEATURE_GROUPS:
case enums.SCREEN.ENTITLEMENT_POOLS:
case enums.SCREEN.LICENSE_KEY_GROUPS:
+ case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+ case enums.SCREEN.ACTIVITY_LOG:
screenToBreadcrumb = {
[enums.SCREEN.LICENSE_AGREEMENTS]: enums.BREADCRUMS.LICENSE_AGREEMENTS,
[enums.SCREEN.FEATURE_GROUPS]: enums.BREADCRUMS.FEATURE_GROUPS,
[enums.SCREEN.ENTITLEMENT_POOLS]: enums.BREADCRUMS.ENTITLEMENT_POOLS,
- [enums.SCREEN.LICENSE_KEY_GROUPS]: enums.BREADCRUMS.LICENSE_KEY_GROUPS
+ [enums.SCREEN.LICENSE_KEY_GROUPS]: enums.BREADCRUMS.LICENSE_KEY_GROUPS,
+ [enums.SCREEN.LICENSE_MODEL_OVERVIEW]: enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW,
+ [enums.SCREEN.ACTIVITY_LOG]: enums.BREADCRUMS.ACTIVITY_LOG
};
return [
{
@@ -365,6 +449,9 @@ export default class OnboardingPunchOut {
}, {
selectedKey: screenToBreadcrumb[screen],
menuItems: [{
+ key: enums.BREADCRUMS.LICENSE_MODEL_OVERVIEW,
+ displayText: i18n('Overview')
+ },{
key: enums.BREADCRUMS.LICENSE_AGREEMENTS,
displayText: i18n('License Agreements')
}, {
@@ -376,6 +463,9 @@ export default class OnboardingPunchOut {
}, {
key: enums.BREADCRUMS.LICENSE_KEY_GROUPS,
displayText: i18n('License Key Groups')
+ }, {
+ key: enums.BREADCRUMS.ACTIVITY_LOG,
+ displayText: i18n('Activity Log')
}]
}
];
@@ -385,6 +475,8 @@ export default class OnboardingPunchOut {
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_COMPONENT_PROCESSES:
@@ -395,11 +487,14 @@ export default class OnboardingPunchOut {
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
screenToBreadcrumb = {
+ [enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE]: enums.BREADCRUMS.SOFTWARE_PRODUCT_LANDING_PAGE,
[enums.SCREEN.SOFTWARE_PRODUCT_DETAILS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_DETAILS,
[enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS,
[enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES]: enums.BREADCRUMS.SOFTWARE_PRODUCT_PROCESSES,
[enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_NETWORKS,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS
+ [enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES]: enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
+ [enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG]: enums.BREADCRUMS.SOFTWARE_PRODUCT_ACTIVITY_LOG
};
let componentScreenToBreadcrumb = {
[enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES]: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_PROCESSES,
@@ -438,24 +533,46 @@ export default class OnboardingPunchOut {
displayText: name
}))
},
- ...(screen === enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE ? [] : [{
+ ...(/*screen === enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE ? [] :*/ [{
selectedKey: screenToBreadcrumb[screen] || enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
menuItems: [{
+ key: enums.BREADCRUMS.SOFTWARE_PRODUCT_LANDING_PAGE,
+ displayText: i18n('Overview')
+ }, {
key: enums.BREADCRUMS.SOFTWARE_PRODUCT_DETAILS,
displayText: i18n('General')
}, {
- key: enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS,
- displayText: i18n('Attachments')
- }, {
key: enums.BREADCRUMS.SOFTWARE_PRODUCT_PROCESSES,
displayText: i18n('Process Details')
}, {
key: enums.BREADCRUMS.SOFTWARE_PRODUCT_NETWORKS,
displayText: i18n('Networks')
}, {
+ key: enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES,
+ displayText: i18n('Components Dependencies')
+ }, {
+ key: enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS,
+ displayText: i18n('Attachments')
+ }, {
+ key: enums.BREADCRUMS.SOFTWARE_PRODUCT_ACTIVITY_LOG,
+ displayText: i18n('Activity Log')
+ }, {
key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS,
displayText: i18n('Components')
- }]
+ }].filter(item => {
+ let isHeatData = doesHeatDataExist(heatSetup);
+ let isComponentsData = componentsList.length > 0;
+ switch (item.key) {
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_ATTACHMENTS:
+ return isHeatData;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENTS:
+ return isComponentsData;
+ case enums.BREADCRUMS.SOFTWARE_PRODUCT_DEPENDENCIES:
+ return isComponentsData;
+ default:
+ return true;
+ }
+ })
}])
];
if(props.componentId) {
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingReducers.js b/openecomp-ui/src/sdc-app/onboarding/OnboardingReducers.js
index 9af2427243..46fc58db95 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingReducers.js
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingReducers.js
@@ -1,26 +1,21 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes, enums} from './OnboardingConstants.js';
-export const currentScreenReducer = (state = {screen: enums.SCREEN.ONBOARDING_CATALOG, props: {}}, action) => {
+export const currentScreenReducer = (state = {forceBreadCrumbsUpdate: false, screen: enums.SCREEN.ONBOARDING_CATALOG, props: {}}, action) => {
if (action.type === actionTypes.SET_CURRENT_SCREEN) {
return action.currentScreen;
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingReducersMap.js b/openecomp-ui/src/sdc-app/onboarding/OnboardingReducersMap.js
index 92d53a3d4f..9428dd5829 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingReducersMap.js
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingReducersMap.js
@@ -1,36 +1,34 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {currentScreenReducer} from './OnboardingReducers.js';
import licenseModelListReducer from './licenseModel/LicenseModelListReducer.js';
import finalizedLicenseModelListReducer from './licenseModel/FinalizedLicenseModelListReducer.js';
import licenseModelReducer from './licenseModel/LicenseModelReducer.js';
import softwareProductReducer from './softwareProduct/SoftwareProductReducer.js';
import softwareProductListReducer from './softwareProduct/SoftwareProductListReducer.js';
-
+import finalizedSoftwareProductReducer from './softwareProduct/FinalizedSoftwareProductReducer.js';
+import onboardReducer from './onboard/OnboardReducer.js';
export default {
currentScreen: currentScreenReducer,
licenseModelList: licenseModelListReducer,
finalizedLicenseModelList: finalizedLicenseModelListReducer,
+ finalizedSoftwareProductList: finalizedSoftwareProductReducer,
licenseModel: licenseModelReducer,
softwareProduct: softwareProductReducer,
- softwareProductList: softwareProductListReducer
+ softwareProductList: softwareProductListReducer,
+ onboard: onboardReducer
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js
index a851e77dc8..cc9d9c536d 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './LicenseModelConstants.js';
export default (state = [], action) => {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js
index ad91a0da65..e21b0a81b0 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js
@@ -1,30 +1,24 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import {statusEnum as versionStatusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx';
-
+import ActivityLogActionHelper from 'nfvo-components/activity-log/ActivityLogActionHelper.js';
import {enums} from 'sdc-app/onboarding/OnboardingConstants.js';
import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
@@ -45,6 +39,11 @@ const buildNavigationBarProps = (licenseModel, screen) => {
name: vendorName,
items: [
{
+ id: navigationItems.LICENSE_MODEL_OVERVIEW,
+ name: i18n('Overview'),
+ meta
+ },
+ {
id: navigationItems.LICENSE_AGREEMENTS,
name: i18n('License Agreements'),
meta
@@ -63,15 +62,22 @@ const buildNavigationBarProps = (licenseModel, screen) => {
id: navigationItems.LICENSE_KEY_GROUPS,
name: i18n('License Key Groups'),
meta
+ },
+ {
+ id: navigationItems.ACTIVITY_LOG,
+ name: i18n('Activity Log'),
+ meta
}
]
}];
const activeItemId = ({
+ [enums.SCREEN.LICENSE_MODEL_OVERVIEW]: navigationItems.LICENSE_MODEL_OVERVIEW,
[enums.SCREEN.LICENSE_AGREEMENTS]: navigationItems.LICENSE_AGREEMENTS,
[enums.SCREEN.FEATURE_GROUPS]: navigationItems.FEATURE_GROUPS,
[enums.SCREEN.ENTITLEMENT_POOLS]: navigationItems.ENTITLEMENT_POOLS,
- [enums.SCREEN.LICENSE_KEY_GROUPS]: navigationItems.LICENSE_KEY_GROUPS
+ [enums.SCREEN.LICENSE_KEY_GROUPS]: navigationItems.LICENSE_KEY_GROUPS,
+ [enums.SCREEN.ACTIVITY_LOG]: navigationItems.ACTIVITY_LOG
})[screen];
return {
@@ -82,9 +88,7 @@ const buildNavigationBarProps = (licenseModel, screen) => {
const buildVersionControllerProps = (licenseModel) => {
let {version, viewableVersions, status: currentStatus, lockingUser} = licenseModel;
- let {status, isCheckedOut} = (currentStatus === versionStatusEnum.CHECK_OUT_STATUS) ?
- VersionControllerUtils.getCheckOutStatusKindByUserID(currentStatus, lockingUser) :
- {status: currentStatus, isCheckedOut: false};
+ let {status, isCheckedOut} = VersionControllerUtils.getCheckOutStatusKindByUserID(currentStatus, lockingUser);
return {
version,
@@ -104,29 +108,46 @@ const mapStateToProps = ({licenseModel: {licenseModelEditor}}, {currentScreen: {
const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {licenseModelId}}}) => {
+
return {
- onVersionControllerAction: action =>
- LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action}).then(() => {
+ onVersionControllerAction: (action, version) =>
+ LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action, version}).then((newVersion) => {
switch(screen) {
+ case enums.SCREEN.LICENSE_MODEL_OVERVIEW:
+ /**
+ * TODO change to specific rest
+ */
+ LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: newVersion});
+ break;
case enums.SCREEN.LICENSE_AGREEMENTS:
- LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId});
+ LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: newVersion});
break;
case enums.SCREEN.FEATURE_GROUPS:
- FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId});
+ FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version: newVersion});
break;
case enums.SCREEN.ENTITLEMENT_POOLS:
- EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId});
+ EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version: newVersion});
break;
case enums.SCREEN.LICENSE_KEY_GROUPS:
- LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId});
+ LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version: newVersion});
+ break;
+ case enums.SCREEN.ACTIVITY_LOG:
+ ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: licenseModelId, versionId: newVersion.id});
break;
}
}),
- onVersionSwitching: version => LicenseAgreementActionHelper.switchVersion(dispatch, {licenseModelId, version}),
- onClose: () => OnboardingActionHelper.navigateToOnboardingCatalog(dispatch),
+ onVersionSwitching: version => {
+ LicenseModelActionHelper.switchVersion(dispatch, {licenseModelId, version});
+ if(screen === enums.SCREEN.ACTIVITY_LOG) {
+ ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: licenseModelId, versionId: version.id});
+ }
+ },
onNavigate: ({id, meta: {version}}) => {
switch(id) {
+ case navigationItems.LICENSE_MODEL_OVERVIEW:
+ OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, {licenseModelId, version});
+ break;
case navigationItems.LICENSE_AGREEMENTS:
OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId, version});
break;
@@ -139,6 +160,9 @@ const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {licenseMod
case navigationItems.LICENSE_KEY_GROUPS:
OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, {licenseModelId, version});
break;
+ case navigationItems.ACTIVITY_LOG:
+ OnboardingActionHelper.navigateToLicenseModelActivityLog(dispatch, {licenseModelId, version});
+ break;
}
}
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js
index a379a2c40f..186f1cbc7b 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js
@@ -1,29 +1,28 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes} from './LicenseModelConstants.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
import {actionsEnum as vcActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js';
+import LicenseAgreementActionHelper from './licenseAgreement/LicenseAgreementActionHelper.js';
+import FeatureGroupsActionHelper from './featureGroups/FeatureGroupsActionHelper.js';
+import EntitlementPoolsActionHelper from './entitlementPools/EntitlementPoolsActionHelper.js';
+import LicenseKeyGroupsActionHelper from './licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
function baseUrl() {
const restPrefix = Configuration.get('restPrefix');
@@ -39,12 +38,32 @@ function fetchFinalizedLicenseModels() {
}
function fetchLicenseModelById(licenseModelId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl()}${licenseModelId}${versionQuery}`);
+ const {id: versionId} = version;
+ return RestAPIUtil.fetch(`${baseUrl()}${licenseModelId}/versions/${versionId}`);
+}
+
+function putLicenseModelAction(id, action, version) {
+ const {id: versionId} = version;
+ return RestAPIUtil.put(`${baseUrl()}${id}/versions/${versionId}/actions`, {action: action});
+}
+
+function putLicenseModel(licenseModel) {
+ let {id, vendorName, description, iconRef, version: {id: versionId}} = licenseModel;
+ return RestAPIUtil.put(`${baseUrl()}${id}/versions/${versionId}`, {
+ vendorName,
+ description,
+ iconRef
+ });
+}
+
+function adjustMinorVersion(version, value) {
+ let ar = version.split('.');
+ return ar[0] + '.' + (parseInt(ar[1]) + value);
}
-function putLicenseModelAction(id, action) {
- return RestAPIUtil.save(`${baseUrl()}${id}/actions`, {action: action});
+function adjustMajorVersion(version, value) {
+ let ar = version.split('.');
+ return (parseInt(ar[0]) + value) + '.0';
}
const LicenseModelActionHelper = {
@@ -67,13 +86,11 @@ const LicenseModelActionHelper = {
},
fetchLicenseModelById(dispatch, {licenseModelId, version}) {
- return fetchLicenseModelById(licenseModelId, version).then(response => {
- if(version) {
- response.version = version;
- }
+
+ return fetchLicenseModelById(licenseModelId, version).then(response => {
dispatch({
type: actionTypes.LICENSE_MODEL_LOADED,
- response
+ response: {...response, version}
});
});
},
@@ -85,17 +102,68 @@ const LicenseModelActionHelper = {
});
},
- performVCAction(dispatch, {licenseModelId, action}) {
- return putLicenseModelAction(licenseModelId, action).then(() => {
+ fetchLicenseModelItems(dispatch, {licenseModelId, version}) {
+ return Promise.all([
+ LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version}),
+ FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version}),
+ EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}),
+ LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version})
+ ]);
+ },
+
+ performVCAction(dispatch, {licenseModelId, action, version}) {
+ return putLicenseModelAction(licenseModelId, action, version).then(() => {
if(action === vcActionsEnum.SUBMIT){
dispatch({
- type: NotificationConstants.NOTIFY_SUCCESS,
- data: {title: i18n('Submit Succeeded'), msg: i18n('This license model successfully submitted'), timeout: 2000}
+ type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
+ data: {
+ title: i18n('Submit Succeeded'),
+ msg: i18n('This license model successfully submitted'),
+ cancelButtonText: i18n('OK'),
+ timeout: 2000
+ }
});
}
- return LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId});
+
+ let newVersionId = version.id;
+ /*
+ TODO Temorary switch to change version label
+ */
+ switch(action) {
+ case vcActionsEnum.CHECK_OUT:
+ newVersionId = adjustMinorVersion(version.label, 1);
+ break;
+ case vcActionsEnum.UNDO_CHECK_OUT:
+ newVersionId = adjustMinorVersion(version.label, -1);
+ break;
+ case vcActionsEnum.SUBMIT:
+ newVersionId = adjustMajorVersion(version.label, 1);
+ }
+
+ LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version:{id: newVersionId, label: newVersionId}});
+ return Promise.resolve({id: newVersionId, label: newVersionId});
+ });
+ },
+
+ switchVersion(dispatch, {licenseModelId, version}) {
+ LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version: {id: version.id, label: version.label}}).then(() => {
+ LicenseModelActionHelper.fetchLicenseModelItems(dispatch, {licenseModelId, version});
+ });
+ },
+
+ saveLicenseModel(dispatch, {licenseModel}) {
+ return putLicenseModel(licenseModel).then(() => {
+ dispatch({
+ type: actionTypes.ADD_LICENSE_MODEL,
+ licenseModel
+ });
+ dispatch({
+ type: actionTypes.LICENSE_MODEL_LOADED,
+ response: licenseModel
+ });
});
}
+
};
export default LicenseModelActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
index 13fa9f5284..4ba10c3a68 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
@@ -29,8 +24,10 @@ export const actionTypes = keyMirror({
});
export const navigationItems = keyMirror({
- LICENSE_AGREEMENTS: 'License Agreements',
- FEATURE_GROUPS: 'Feature Groups',
- ENTITLEMENT_POOLS: 'Entitlement Pools',
- LICENSE_KEY_GROUPS: 'License Key Groups'
+ LICENSE_MODEL_OVERVIEW: 'overview',
+ LICENSE_AGREEMENTS: 'license-agreements',
+ FEATURE_GROUPS: 'feature-groups',
+ ENTITLEMENT_POOLS: 'entitlement-pools',
+ LICENSE_KEY_GROUPS: 'license-key-groups',
+ ACTIVITY_LOG: 'activity-log'
});
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js
index e92e32aa9e..add5ac6a98 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js
@@ -1,28 +1,23 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './LicenseModelConstants.js';
export default (state = {}, action) => {
switch (action.type) {
- case actionTypes.LICENSE_MODEL_LOADED:
+ case actionTypes.LICENSE_MODEL_LOADED:
return {
...state,
data: action.response
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js
index 8874c4ce21..fd73b462a3 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './LicenseModelConstants.js';
export default (state = [], action) => {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
index 5982b9f8ab..9a2d114bdc 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
@@ -1,66 +1,85 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {combineReducers} from 'redux';
+import activityLogReducer from 'nfvo-components/activity-log/ActivityLogReducer.js';
+
import licenseModelCreationReducer from './creation/LicenseModelCreationReducer.js';
import licenseModelEditorReducer from './LicenseModelEditorReducer.js';
import licenseAgreementListReducer from './licenseAgreement/LicenseAgreementListReducer.js';
import licenseAgreementEditorReducer from './licenseAgreement/LicenseAgreementEditorReducer.js';
-import {actionTypes as licenseAgreementActionTypes} from './licenseAgreement/LicenseAgreementConstants.js';
import featureGroupsEditorReducer from './featureGroups/FeatureGroupsEditorReducer.js';
import featureGroupsListReducer from './featureGroups/FeatureGroupsListReducer.js';
-import {actionTypes as featureGroupsActionConstants} from './featureGroups/FeatureGroupsConstants';
import entitlementPoolsListReducer from './entitlementPools/EntitlementPoolsListReducer.js';
import entitlementPoolsEditorReducer from './entitlementPools/EntitlementPoolsEditorReducer.js';
-import {actionTypes as entitlementPoolsConstants} from './entitlementPools/EntitlementPoolsConstants';
import licenseKeyGroupsEditorReducer from './licenseKeyGroups/LicenseKeyGroupsEditorReducer.js';
import licenseKeyGroupsListReducer from './licenseKeyGroups/LicenseKeyGroupsListReducer.js';
-import {actionTypes as licenseKeyGroupsConstants} from './licenseKeyGroups/LicenseKeyGroupsConstants.js';
+
+import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js';
+
+import {actionTypes as licenseModelOverviewConstants, selectedButton, VLM_DESCRIPTION_FORM} from './overview/LicenseModelOverviewConstants.js';
export default combineReducers({
- licenseModelCreation: licenseModelCreationReducer,
+ licenseModelCreation: createPlainDataReducer(licenseModelCreationReducer),
licenseModelEditor: licenseModelEditorReducer,
licenseAgreement: combineReducers({
- licenseAgreementEditor: licenseAgreementEditorReducer,
- licenseAgreementList: licenseAgreementListReducer,
- licenseAgreementToDelete: (state = false, action) => action.type === licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM ? action.licenseAgreementToDelete : state
+ licenseAgreementEditor: createPlainDataReducer(licenseAgreementEditorReducer),
+ licenseAgreementList: licenseAgreementListReducer
}),
featureGroup: combineReducers({
- featureGroupEditor: featureGroupsEditorReducer,
- featureGroupsList: featureGroupsListReducer,
- featureGroupToDelete: (state = false, action) => action.type === featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM ? action.featureGroupToDelete : state
+ featureGroupEditor: createPlainDataReducer(featureGroupsEditorReducer),
+ featureGroupsList: featureGroupsListReducer
}),
entitlementPool: combineReducers({
- entitlementPoolEditor: entitlementPoolsEditorReducer,
- entitlementPoolsList: entitlementPoolsListReducer,
- entitlementPoolToDelete: (state = false, action) => action.type === entitlementPoolsConstants.ENTITLEMENT_POOLS_DELETE_CONFIRM ? action.entitlementPoolToDelete : state
+ entitlementPoolEditor: createPlainDataReducer(entitlementPoolsEditorReducer),
+ entitlementPoolsList: entitlementPoolsListReducer
}),
licenseKeyGroup: combineReducers({
- licenseKeyGroupsEditor: licenseKeyGroupsEditorReducer,
- licenseKeyGroupsList: licenseKeyGroupsListReducer,
- licenseKeyGroupToDelete: (state = false, action) => action.type === licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM ? action.licenseKeyGroupToDelete : state
+ licenseKeyGroupsEditor: createPlainDataReducer(licenseKeyGroupsEditorReducer),
+ licenseKeyGroupsList: licenseKeyGroupsListReducer
}),
+ licenseModelOverview: combineReducers({
+ selectedTab: (state = selectedButton.VLM_LIST_VIEW, action) => action.type === licenseModelOverviewConstants.LICENSE_MODEL_OVERVIEW_TAB_SELECTED ? action.buttonTab : state,
+ descriptionEditor: createPlainDataReducer(function(state = false, action) {
+ if (action.type === licenseModelOverviewConstants.LM_DATA_CHANGED) {
+ return {
+ ...state,
+ data : {
+ description : action.description
+ },
+ formReady: null,
+ formName: VLM_DESCRIPTION_FORM,
+ genericFieldInfo: {
+ 'description': {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}]
+ }
+ }
+ };
+ //return action.description;
+ } else {
+ return state;
+ }
+ }
+ )}),
+ activityLog: activityLogReducer
});
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
index 63d0f27b6a..d85618c85f 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
@@ -1,40 +1,50 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
import LicenseModelCreationActionHelper from './LicenseModelCreationActionHelper.js';
import LicenseModelCreationView from './LicenseModelCreationView.jsx';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+
+export const mapStateToProps = ({licenseModelList, licenseModel: {licenseModelCreation}}) => {
+ let {genericFieldInfo} = licenseModelCreation;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
-const mapStateToProps = ({licenseModel: {licenseModelCreation}}) => licenseModelCreation;
+ let VLMNames = {};
+ for (let i = 0; i < licenseModelList.length; i++) {
+ VLMNames[licenseModelList[i].vendorName] = licenseModelList[i].id;
+ }
+
+ return {...licenseModelCreation, isFormValid: isFormValid, VLMNames};
+};
-const mapActionsToProps = (dispatch) => {
+export const mapActionsToProps = (dispatch) => {
return {
- onDataChanged: deltaData => LicenseModelCreationActionHelper.dataChanged(dispatch, {deltaData}),
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onCancel: () => LicenseModelCreationActionHelper.close(dispatch),
onSubmit: (licenseModel) => {
LicenseModelCreationActionHelper.close(dispatch);
- LicenseModelCreationActionHelper.createLicenseModel(dispatch, {licenseModel}).then(licenseModelId => {
- OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId});
+ LicenseModelCreationActionHelper.createLicenseModel(dispatch, {licenseModel}).then(response => {
+ LicenseModelActionHelper.fetchLicenseModels(dispatch).then(() => {
+ OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, {licenseModelId: response.value});
+ });
});
- }
+ },
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js
index c2a0409bd2..51f5b7f276 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js
@@ -1,27 +1,24 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
-import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
import {actionTypes} from './LicenseModelCreationConstants.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
function baseUrl() {
const restPrefix = Configuration.get('restPrefix');
@@ -29,7 +26,7 @@ function baseUrl() {
}
function createLicenseModel(licenseModel) {
- return RestAPIUtil.create(baseUrl(), {
+ return RestAPIUtil.post(baseUrl(), {
vendorName: licenseModel.vendorName,
description: licenseModel.description,
iconRef: 'icon'
@@ -43,30 +40,28 @@ export default {
dispatch({
type: actionTypes.OPEN
});
+
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_SHOW,
+ data: {
+ modalComponentName: modalContentMapper.LICENSE_MODEL_CREATION,
+ title: i18n('New License Model')
+ }
+ });
},
close(dispatch){
dispatch({
type: actionTypes.CLOSE
});
- },
- dataChanged(dispatch, {deltaData}){
dispatch({
- type: actionTypes.DATA_CHANGED,
- deltaData
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
});
},
createLicenseModel(dispatch, {licenseModel}){
- return createLicenseModel(licenseModel).then(response => {
- LicenseModelActionHelper.addLicenseModel(dispatch, {
- licenseModel: {
- ...licenseModel,
- id: response.value
- }
- });
- return response.value;
- });
+ return createLicenseModel(licenseModel);
}
+
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js
index 603d177048..28f1175676 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js
@@ -1,27 +1,23 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
OPEN: null,
- CLOSE: null,
- DATA_CHANGED: null
+ CLOSE: null
});
+
+export const LICENSE_MODEL_CREATION_FORM_NAME = 'LMCREATIONFORM';
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js
index a54d1b3089..879d356de2 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js
@@ -1,42 +1,43 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from './LicenseModelCreationConstants.js';
+import {actionTypes, LICENSE_MODEL_CREATION_FORM_NAME} from './LicenseModelCreationConstants.js';
export default (state = {}, action) => {
switch (action.type) {
case actionTypes.OPEN:
return {
...state,
- data: {}
+ formReady: null,
+ formName: LICENSE_MODEL_CREATION_FORM_NAME,
+ data: {},
+ genericFieldInfo: {
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}]
+ },
+ 'vendorName' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}]
+ }
+ }
};
case actionTypes.CLOSE:
return {};
- case actionTypes.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
- }
- };
default:
return state;
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx
index 4dccc9e1c4..80040460c0 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx
@@ -1,7 +1,24 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+import Validator from 'nfvo-utils/Validator.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import {LICENSE_MODEL_CREATION_FORM_NAME} from './LicenseModelCreationConstants.js';
const LicenseModelPropType = React.PropTypes.shape({
id: React.PropTypes.string,
@@ -13,39 +30,49 @@ class LicenseModelCreationView extends React.Component {
static propTypes = {
data: LicenseModelPropType,
+ VLMNames: React.PropTypes.object,
onDataChanged: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired,
+ onValidateForm: React.PropTypes.func.isRequired,
onCancel: React.PropTypes.func.isRequired
};
render() {
- let {data = {}, onDataChanged} = this.props;
+ let {data = {}, onDataChanged, genericFieldInfo} = this.props;
let {vendorName, description} = data;
return (
<div>
- <ValidationForm
+ {genericFieldInfo && <Form
ref='validationForm'
hasButtons={true}
onSubmit={ () => this.submit() }
onReset={ () => this.props.onCancel() }
- labledButtons={true}>
- <ValidationInput
+ labledButtons={true}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.validate() }>
+ <Input
value={vendorName}
label={i18n('Vendor Name')}
- ref='vendor-name'
- onChange={vendorName => onDataChanged({vendorName})}
- validations={{maxLength: 25, required: true}}
+ data-test-id='vendor-name'
+ onChange={vendorName => onDataChanged({vendorName}, LICENSE_MODEL_CREATION_FORM_NAME, {vendorName: name => this.validateName(name)})}
+ isValid={genericFieldInfo.vendorName.isValid}
+ errorText={genericFieldInfo.vendorName.errorText}
type='text'
+ isRequired={true}
className='field-section'/>
- <ValidationInput
+ <Input
+ isRequired={true}
value={description}
label={i18n('Description')}
- ref='description'
- onChange={description => onDataChanged({description})}
- validations={{maxLength: 1000, required: true}}
+ data-test-id='vendor-description'
+ overlayPos='bottom'
+ onChange={description => onDataChanged({description}, LICENSE_MODEL_CREATION_FORM_NAME)}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
type='textarea'
className='field-section'/>
- </ValidationForm>
+ </Form>}
</div>
);
}
@@ -55,6 +82,18 @@ class LicenseModelCreationView extends React.Component {
const {data:licenseModel} = this.props;
this.props.onSubmit(licenseModel);
}
+
+ validateName(value) {
+ const {data: {id}, VLMNames} = this.props;
+ const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: VLMNames});
+
+ return !isExists ? {isValid: true, errorText: ''} :
+ {isValid: false, errorText: i18n('License model by the name \'' + value + '\' already exists. License model name must be unique')};
+ }
+
+ validate() {
+ this.props.onValidateForm(LICENSE_MODEL_CREATION_FORM_NAME);
+ }
}
export default LicenseModelCreationView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
index 631597a5b0..fe95b034dd 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
@@ -1,40 +1,35 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes as entitlementPoolsActionTypes } from './EntitlementPoolsConstants.js';
import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
-function baseUrl(licenseModelId) {
+function baseUrl(licenseModelId, version) {
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/entitlement-pools`;
+ const {id: versionId} = version;
+ return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/entitlement-pools`;
}
-function fetchEntitlementPoolsList(licenseModelId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+function fetchEntitlementPoolsList(licenseModelId, version) {
+ return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
}
-function postEntitlementPool(licenseModelId, entitlementPool) {
- return RestAPIUtil.create(baseUrl(licenseModelId), {
+function postEntitlementPool(licenseModelId, entitlementPool, version) {
+ return RestAPIUtil.post(baseUrl(licenseModelId, version), {
name: entitlementPool.name,
description: entitlementPool.description,
thresholdValue: entitlementPool.thresholdValue,
@@ -49,8 +44,8 @@ function postEntitlementPool(licenseModelId, entitlementPool) {
}
-function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool) {
- return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${entitlementPool.id}`, {
+function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool, version) {
+ return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${entitlementPool.id}`, {
name: entitlementPool.name,
description: entitlementPool.description,
thresholdValue: entitlementPool.thresholdValue,
@@ -64,8 +59,8 @@ function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlement
});
}
-function deleteEntitlementPool(licenseModelId, entitlementPoolId) {
- return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${entitlementPoolId}`);
+function deleteEntitlementPool(licenseModelId, entitlementPoolId, version) {
+ return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}`);
}
@@ -84,8 +79,8 @@ export default {
});
},
- deleteEntitlementPool(dispatch, {licenseModelId, entitlementPoolId}) {
- return deleteEntitlementPool(licenseModelId, entitlementPoolId).then(() => {
+ deleteEntitlementPool(dispatch, {licenseModelId, entitlementPoolId, version}) {
+ return deleteEntitlementPool(licenseModelId, entitlementPoolId, version).then(() => {
dispatch({
type: entitlementPoolsActionTypes.DELETE_ENTITLEMENT_POOL,
entitlementPoolId
@@ -106,9 +101,9 @@ export default {
});
},
- saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool}) {
+ saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool, version}) {
if (previousEntitlementPool) {
- return putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool).then(() => {
+ return putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool, version).then(() => {
dispatch({
type: entitlementPoolsActionTypes.EDIT_ENTITLEMENT_POOL,
entitlementPool
@@ -116,11 +111,12 @@ export default {
});
}
else {
- return postEntitlementPool(licenseModelId, entitlementPool).then(response => {
+ return postEntitlementPool(licenseModelId, entitlementPool, version).then(response => {
dispatch({
type: entitlementPoolsActionTypes.ADD_ENTITLEMENT_POOL,
entitlementPool: {
...entitlementPool,
+ referencingFeatureGroups: [],
id: response.value
}
});
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx
deleted file mode 100644
index 04f038f5f0..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import {connect} from 'react-redux';
-import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
-import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-function renderMsg(entitlementPoolToDelete) {
- let poolName = entitlementPoolToDelete ? entitlementPoolToDelete.name : '';
- let msg = i18n('Are you sure you want to delete "{poolName}"?', {poolName});
- let subMsg = entitlementPoolToDelete
- && entitlementPoolToDelete.referencingFeatureGroups
- && entitlementPoolToDelete.referencingFeatureGroups.length > 0 ?
- i18n('This entitlement pool is associated with one or more feature groups') :
- '';
- return (
- <div>
- <p>{msg}</p>
- <p>{subMsg}</p>
- </div>
- );
-};
-
-const mapStateToProps = ({licenseModel: {entitlementPool}}, {licenseModelId}) => {
- let {entitlementPoolToDelete} = entitlementPool;
- const show = entitlementPoolToDelete !== false;
- return {
- show,
- title: 'Warning!',
- type: 'warning',
- msg: renderMsg(entitlementPoolToDelete),
- confirmationDetails: {entitlementPoolToDelete, licenseModelId}
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
- onConfirmed: ({entitlementPoolToDelete, licenseModelId}) => {
- EntitlementPoolsActionHelper.deleteEntitlementPool(dispatch, {
- licenseModelId,
- entitlementPoolId: entitlementPoolToDelete.id
- });
- EntitlementPoolsActionHelper.hideDeleteConfirm(dispatch);
- },
- onDeclined: () => {
- EntitlementPoolsActionHelper.hideDeleteConfirm(dispatch);
- }
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
index 8a855076f3..ba0b238b17 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
@@ -1,25 +1,21 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
export const actionTypes = keyMirror({
@@ -27,7 +23,6 @@ export const actionTypes = keyMirror({
ADD_ENTITLEMENT_POOL: null,
EDIT_ENTITLEMENT_POOL: null,
DELETE_ENTITLEMENT_POOL: null,
- ENTITLEMENT_POOLS_DELETE_CONFIRM: null,
entitlementPoolsEditor: {
OPEN: null,
@@ -107,6 +102,14 @@ export const optionsInputValues = {
]
};
+export const extractValue = (item) => {
+ if (item === undefined) {return '';} //TODO fix it later
+ return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+};
+export const extractUnits = (units) => {
+ if (units === undefined) {return '';} //TODO fix it later
+ return units === 'Absolute' ? '' : '%';
+};
-
+export const SP_ENTITLEMENT_POOL_FORM = 'SPENTITLEMENTPOOL';
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
index d5bd07e929..f89cf8fbb5 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
@@ -1,52 +1,60 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
import EntitlementPoolsEditorView from './EntitlementPoolsEditorView.jsx';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
const mapStateToProps = ({licenseModel: {entitlementPool}}) => {
- let {data} = entitlementPool.entitlementPoolEditor;
-
- let previousData;
+ let {data, genericFieldInfo, formReady} = entitlementPool.entitlementPoolEditor;
+
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
+ let previousData, EPNames = {};
const entitlementPoolId = data ? data.id : null;
if(entitlementPoolId) {
previousData = entitlementPool.entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId);
}
+ const list = entitlementPool.entitlementPoolsList;
+ for (let i = 0; i < list.length; i++) {
+ EPNames[list[i].name] = list[i].id;
+ }
+
return {
data,
- previousData
+ genericFieldInfo,
+ previousData,
+ isFormValid,
+ formReady,
+ EPNames
};
};
-const mapActionsToProps = (dispatch, {licenseModelId}) => {
+const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
- onDataChanged: deltaData => EntitlementPoolsActionHelper.entitlementPoolsEditorDataChanged(dispatch, {deltaData}),
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onCancel: () => EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch),
onSubmit: ({previousEntitlementPool, entitlementPool}) => {
EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch);
- EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool});
- }
+ EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool, version});
+ },
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
index 86e97ecf8d..db1a3a97ca 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
@@ -1,30 +1,79 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes, defaultState} from './EntitlementPoolsConstants.js';
+import {actionTypes, defaultState, SP_ENTITLEMENT_POOL_FORM} from './EntitlementPoolsConstants.js';
export default (state = {}, action) => {
switch (action.type) {
case actionTypes.entitlementPoolsEditor.OPEN:
return {
...state,
+ formReady: null,
+ formName: SP_ENTITLEMENT_POOL_FORM,
+ genericFieldInfo: {
+ 'name' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
+ },
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}]
+ },
+ 'manufacturerReferenceNumber' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 100}]
+ },
+ 'increments' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 120}]
+ },
+ 'operationalScope' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ 'thresholdUnits' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ 'thresholdValue' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ 'entitlementMetric' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ 'aggregationFunction' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ 'time' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ }
+ },
data: action.entitlementPool ? {...action.entitlementPool} : defaultState.ENTITLEMENT_POOLS_EDITOR_DATA
};
case actionTypes.entitlementPoolsEditor.DATA_CHANGED:
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
index 77c5a12e03..d484437015 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
@@ -1,14 +1,31 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-
import i18n from 'nfvo-utils/i18n/i18n.js';
+import Validator from 'nfvo-utils/Validator.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
-import {optionsInputValues as EntitlementPoolsOptionsInputValues, thresholdUnitType} from './EntitlementPoolsConstants.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+import {optionsInputValues as EntitlementPoolsOptionsInputValues, thresholdUnitType, SP_ENTITLEMENT_POOL_FORM} from './EntitlementPoolsConstants.js';
import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
-
const EntitlementPoolPropType = React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string,
@@ -33,11 +50,172 @@ const EntitlementPoolPropType = React.PropTypes.shape({
})
});
+const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, validateName, validateChoiceWithOther, validateTimeOtherValue, thresholdValueValidation}) => {
+ let {
+ name, description, manufacturerReferenceNumber, operationalScope , aggregationFunction, thresholdUnits, thresholdValue,
+ increments, time, entitlementMetric} = data;
+
+ return (
+ <GridSection>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={name => onDataChanged({name}, SP_ENTITLEMENT_POOL_FORM, {name: validateName})}
+ isValid={genericFieldInfo.name.isValid}
+ isRequired={true}
+ errorText={genericFieldInfo.name.errorText}
+ label={i18n('Name')}
+ value={name}
+ data-test-id='create-ep-name'
+ type='text'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <InputOptions
+ onInputChange={()=>{}}
+ isMultiSelect={true}
+
+ isRequired={true}
+ onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
+ SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})}
+ onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
+ other: operationalScope}}, SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})}
+ label={i18n('Operational Scope')}
+ data-test-id='create-ep-operational-scope'
+ type='select'
+ multiSelectedEnum={operationalScope && operationalScope.choices}
+ otherValue={operationalScope && operationalScope.other}
+ values={EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE}
+ isValid={genericFieldInfo.operationalScope.isValid}
+ errorText={genericFieldInfo.operationalScope.errorText} />
+ </GridItem>
+ <GridItem colSpan={2} stretch>
+ <Input
+ onChange={description => onDataChanged({description}, SP_ENTITLEMENT_POOL_FORM)}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ label={i18n('Description')}
+ value={description}
+ isRequired={true}
+ data-test-id='create-ep-description'
+ type='textarea'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <div className='threshold-section'>
+ <Input
+ isRequired={true}
+ onChange={e => {
+ // setting the unit to the correct value
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onDataChanged({thresholdUnits: val}, SP_ENTITLEMENT_POOL_FORM);
+ // TODO make sure that the value is valid too
+ onDataChanged({thresholdValue: thresholdValue}, SP_ENTITLEMENT_POOL_FORM,{thresholdValue : thresholdValueValidation});}
+
+ }
+ value={thresholdUnits}
+ label={i18n('Threshold Units')}
+ data-test-id='create-ep-threshold-units'
+ isValid={genericFieldInfo.thresholdUnits.isValid}
+ errorText={genericFieldInfo.thresholdUnits.errorText}
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ type='select' >
+ {EntitlementPoolsOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+
+ <Input
+ className='entitlement-pools-form-row-threshold-value'
+ onChange={thresholdValue => onDataChanged({thresholdValue}, SP_ENTITLEMENT_POOL_FORM,
+ {thresholdValue : thresholdValueValidation})}
+ label={i18n('Threshold Value')}
+ isValid={genericFieldInfo.thresholdValue.isValid}
+ errorText={genericFieldInfo.thresholdValue.errorText}
+ data-test-id='create-ep-threshold-value'
+ value={thresholdValue}
+ isRequired={true}
+ type='text'/>
+ </div>
+ <InputOptions
+ onInputChange={()=>{}}
+ isMultiSelect={false}
+ isRequired={true}
+ onEnumChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: entitlementMetric, other: ''}},
+ SP_ENTITLEMENT_POOL_FORM, {entitlementMetric: validateChoiceWithOther})}
+ onOtherChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: optionInputOther.OTHER,
+ other: entitlementMetric}}, SP_ENTITLEMENT_POOL_FORM, {entitlementMetric: validateChoiceWithOther})}
+ label={i18n('Entitlement Metric')}
+ data-test-id='create-ep-entitlement-metric'
+ type='select'
+ required={true}
+ selectedEnum={entitlementMetric && entitlementMetric.choice}
+ otherValue={entitlementMetric && entitlementMetric.other}
+ values={EntitlementPoolsOptionsInputValues.ENTITLEMENT_METRIC}
+ isValid={genericFieldInfo.entitlementMetric.isValid}
+ errorText={genericFieldInfo.entitlementMetric.errorText} />
+ <InputOptions
+ onInputChange={()=>{}}
+ isMultiSelect={false}
+ isRequired={true}
+ onEnumChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: aggregationFunction, other: ''}},
+ SP_ENTITLEMENT_POOL_FORM, {aggregationFunction: validateChoiceWithOther})}
+ onOtherChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: optionInputOther.OTHER,
+ other: aggregationFunction}}, SP_ENTITLEMENT_POOL_FORM, {aggregationFunction: validateChoiceWithOther})}
+ label={i18n('Aggregate Function')}
+ data-test-id='create-ep-aggregate-function'
+ type='select'
+ required={true}
+ selectedEnum={aggregationFunction && aggregationFunction.choice}
+ otherValue={aggregationFunction && aggregationFunction.other}
+ values={EntitlementPoolsOptionsInputValues.AGGREGATE_FUNCTION}
+ isValid={genericFieldInfo.aggregationFunction.isValid}
+ errorText={genericFieldInfo.aggregationFunction.errorText} />
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber}, SP_ENTITLEMENT_POOL_FORM)}
+ label={i18n('Manufacturer Reference Number')}
+ value={manufacturerReferenceNumber}
+ isRequired={true}
+ data-test-id='create-ep-reference-number'
+ type='text'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <InputOptions
+ onInputChange={()=>{}}
+ isMultiSelect={false}
+ isRequired={true}
+ onEnumChange={time => onDataChanged({time:{choice: time, other: ''}},
+ SP_ENTITLEMENT_POOL_FORM, {time: validateChoiceWithOther})}
+ onOtherChange={time => onDataChanged({time:{choice: optionInputOther.OTHER,
+ other: time}}, SP_ENTITLEMENT_POOL_FORM, {time: validateTimeOtherValue})}
+ label={i18n('Time')}
+ data-test-id='create-ep-time'
+ type='select'
+ required={true}
+ selectedEnum={time && time.choice}
+ otherValue={time && time.other}
+ values={EntitlementPoolsOptionsInputValues.TIME}
+ isValid={genericFieldInfo.time.isValid}
+ errorText={genericFieldInfo.time.errorText} />
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={increments => onDataChanged({increments}, SP_ENTITLEMENT_POOL_FORM)}
+ label={i18n('Increments')}
+ value={increments}
+ data-test-id='create-ep-increments'
+ type='text'/>
+ </GridItem>
+ </GridSection>
+ );
+};
+
class EntitlementPoolsEditorView extends React.Component {
static propTypes = {
data: EntitlementPoolPropType,
previousData: EntitlementPoolPropType,
+ EPNames: React.PropTypes.object,
isReadOnlyMode: React.PropTypes.bool,
onDataChanged: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired,
@@ -49,119 +227,88 @@ class EntitlementPoolsEditorView extends React.Component {
};
render() {
- let {data = {}, onDataChanged, isReadOnlyMode} = this.props;
- let {
- name, description, manufacturerReferenceNumber, operationalScope, aggregationFunction, thresholdUnits, thresholdValue,
- increments, time, entitlementMetric} = data;
- let thresholdValueValidation = thresholdUnits === thresholdUnitType.PERCENTAGE ? {numeric: true, required: true, maxValue: 100} : {numeric: true, required: true};
- let timeValidation = time && time.choice === optionInputOther.OTHER ? {numeric: true, required: true} : {required: true};
+ let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo} = this.props;
+
return (
- <ValidationForm
- ref='validationForm'
- hasButtons={true}
- onSubmit={ () => this.submit() }
- onReset={ () => this.props.onCancel() }
- labledButtons={true}
- isReadOnlyMode={isReadOnlyMode}
- className='entitlement-pools-form'>
- <div className='entitlement-pools-form-row'>
- <ValidationInput
- onChange={name => onDataChanged({name})}
- label={i18n('Name')}
- value={name}
- validations={{maxLength: 120, required: true}}
- type='text'/>
+ <div>
+ {
+ genericFieldInfo && <Form
+ ref='validationForm'
+ hasButtons={true}
+ onSubmit={ () => this.submit() }
+ onReset={ () => this.props.onCancel() }
+ labledButtons={true}
+ isReadOnlyMode={isReadOnlyMode}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM) }
+ className='entitlement-pools-form'>
+ <EntitlementPoolsFormContent
+ data={data}
+ genericFieldInfo={genericFieldInfo}
+ onDataChanged={onDataChanged}
+ validateName={(value)=> this.validateName(value)}
+ validateTimeOtherValue ={(value)=> this.validateTimeOtherValue(value)}
+ validateChoiceWithOther={(value)=> this.validateChoiceWithOther(value)}
+ thresholdValueValidation={(value, state)=> this.thresholdValueValidation(value, state)}/>
+ </Form>
+ }
+ </div>
+ );
+ }
- <ValidationInput
- isMultiSelect={true}
- onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}})}
- onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], other: operationalScope}})}
- multiSelectedEnum={operationalScope && operationalScope.choices}
- label={i18n('Operational Scope')}
- otherValue={operationalScope && operationalScope.other}
- validations={{required: true}}
- values={EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE}/>
+ submit() {
+ const {data: entitlementPool, previousData: previousEntitlementPool} = this.props;
+ this.props.onSubmit({entitlementPool, previousEntitlementPool});
+ }
- </div>
- <div className='entitlement-pools-form-row'>
- <ValidationInput
- onChange={description => onDataChanged({description})}
- label={i18n('Description')}
- value={description}
- validations={{maxLength: 1000, required: true}}
- type='textarea'/>
- <div className='entitlement-pools-form-row-group'>
- <div className='entitlement-pools-form-row'>
- <ValidationInput
- onEnumChange={thresholdUnits => onDataChanged({thresholdUnits})}
- selectedEnum={thresholdUnits}
- label={i18n('Threshold Value')}
- type='select'
- values={EntitlementPoolsOptionsInputValues.THRESHOLD_UNITS}
- validations={{required: true}}/>
- <ValidationInput
- className='entitlement-pools-form-row-threshold-value'
- onChange={thresholdValue => onDataChanged({thresholdValue})}
- value={thresholdValue}
- validations={thresholdValueValidation}
- type='text'/>
- </div>
-
- <ValidationInput
- onEnumChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: entitlementMetric, other: ''}})}
- onOtherChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: optionInputOther.OTHER, other: entitlementMetric}})}
- selectedEnum={entitlementMetric && entitlementMetric.choice}
- otherValue={entitlementMetric && entitlementMetric.other}
- label={i18n('Entitlement Metric')}
- validations={{required: true}}
- values={EntitlementPoolsOptionsInputValues.ENTITLEMENT_METRIC}/>
- <ValidationInput
- onEnumChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: aggregationFunction, other: ''}})}
- onOtherChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: optionInputOther.OTHER, other: aggregationFunction}})}
- selectedEnum={aggregationFunction && aggregationFunction.choice}
- otherValue={aggregationFunction && aggregationFunction.other}
- validations={{required: true}}
- label={i18n('Aggregate Function')}
- values={EntitlementPoolsOptionsInputValues.AGGREGATE_FUNCTION}/>
-
- </div>
- </div>
- <div className='entitlement-pools-form-row'>
+ validateName(value) {
+ const {data: {id}, EPNames} = this.props;
+ const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: EPNames});
- <ValidationInput
- onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber})}
- label={i18n('Manufacturer Reference Number')}
- value={manufacturerReferenceNumber}
- validations={{maxLength: 100, required: true}}
- type='text'/>
+ return !isExists ? {isValid: true, errorText: ''} :
+ {isValid: false, errorText: i18n('Entitlement pool by the name \'' + value + '\' already exists. Entitlement pool name must be unique')};
+ }
- <ValidationInput
- onEnumChange={time => onDataChanged({time:{choice: time, other: ''}})}
- onOtherChange={time => onDataChanged({time:{choice: optionInputOther.OTHER, other: time}})}
- selectedEnum={time && time.choice}
- otherValue={time && time.other}
- validations={timeValidation}
- label={i18n('Time')}
- values={EntitlementPoolsOptionsInputValues.TIME}/>
- </div>
- <div className='entitlement-pools-form-row'>
- <ValidationInput
- onChange={increments => onDataChanged({increments})}
- label={i18n('Increments')}
- value={increments}
- validations={{maxLength: 120}}
- type='text'/>
+ validateTimeOtherValue(value) {
+ return Validator.validate('time', value.other, [{type: 'required', data: true}, {type: 'numeric', data: true}]);
+ }
- </div>
- </ValidationForm>
- );
+ validateChoiceWithOther(value) {
+ let chosen = value.choice;
+ // if we have an empty multiple select we have a problem since it's required
+ if (value.choices) {
+ if (value.choices.length === 0) {
+ return Validator.validate('field', '', [{type: 'required', data: true}]);
+ } else {
+ // continuing validation with the first chosen value in case we have the 'Other' field
+ chosen = value.choices[0];
+ }
+ }
+ if (chosen !== optionInputOther.OTHER) {
+ return Validator.validate('field', chosen, [{type: 'required', data: true}]);
+ } else { // when 'Other' was chosen, validate other value
+ return Validator.validate('field', value.other, [{type: 'required', data: true}]);
+ }
}
- submit() {
- const {data: entitlementPool, previousData: previousEntitlementPool} = this.props;
- this.props.onSubmit({entitlementPool, previousEntitlementPool});
+ thresholdValueValidation(value, state) {
+
+ let unit = state.data.thresholdUnits;
+ if (unit === thresholdUnitType.PERCENTAGE) {
+ return Validator.validate('thresholdValue', value, [
+ {type: 'required', data: true},
+ {type: 'numeric', data: true},
+ {type: 'maximum', data: 100},
+ {type: 'minimum', data: 0}]);
+ } else {
+ return Validator.validate('thresholdValue', value, [
+ {type: 'numeric', data: true},
+ {type: 'required', data: true}]);
+ }
}
+
}
export default EntitlementPoolsEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
index 4b21a2fea8..993ed48f2b 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
@@ -1,27 +1,24 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+import i18n from 'nfvo-utils/i18n/i18n.js';
import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
-import EntitlementPoolsListEditorView from './EntitlementPoolsListEditorView.jsx';
+import EntitlementPoolsListEditorView, {generateConfirmationMsg} from './EntitlementPoolsListEditorView.jsx';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js';
const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}}) => {
let {entitlementPoolsList} = entitlementPool;
@@ -39,13 +36,21 @@ const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}})
};
};
-const mapActionsToProps = (dispatch, {licenseModelId}) => {
+const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
onAddEntitlementPoolClick: () => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch),
onEditEntitlementPoolClick: entitlementPool => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {entitlementPool}),
- onDeleteEntitlementPool: entitlementPool => EntitlementPoolsActionHelper.openDeleteEntitlementPoolConfirm(dispatch, {
- licenseModelId,
- entitlementPool
+ onDeleteEntitlementPool: entitlementPool => dispatch({
+ type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: generateConfirmationMsg(entitlementPool),
+ title: i18n('Warning'),
+ onConfirmed: ()=>EntitlementPoolsActionHelper.deleteEntitlementPool(dispatch, {
+ licenseModelId,
+ entitlementPoolId: entitlementPool.id,
+ version
+ })
+ }
})
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
index 52df102503..07a6f21a1a 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -6,10 +21,7 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import EntitlementPoolsEditor from './EntitlementPoolsEditor.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
-import {optionsInputValues} from './EntitlementPoolsConstants';
-import EntitlementPoolsConfirmationModal from './EntitlementPoolsConfirmationModal.jsx';
-
+import {extractUnits, extractValue} from './EntitlementPoolsConstants';
class EntitlementPoolsListEditorView extends React.Component {
static propTypes = {
@@ -33,35 +45,33 @@ class EntitlementPoolsListEditorView extends React.Component {
};
render() {
- let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
+ let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = this.props;
let {onAddEntitlementPoolClick} = this.props;
const {localFilter} = this.state;
return (
<div className='entitlement-pools-list-editor'>
<ListEditorView
- title={i18n('Entitlement Pools for {vendorName} License Model', {vendorName})}
+ title={i18n('Entitlement Pools', {vendorName})}
plusButtonTitle={i18n('Add Entitlement Pool')}
onAdd={onAddEntitlementPoolClick}
filterValue={localFilter}
- onFilter={filter => this.setState({localFilter: filter})}
+ onFilter={value => this.setState({localFilter: value})}
isReadOnlyMode={isReadOnlyMode}>
{this.filterList().map(entitlementPool => this.renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode))}
</ListEditorView>
- <Modal show={isDisplayModal} bsSize='large' animation={true} className='entitlement-pools-modal'>
+ <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal entitlement-pools-modal'>
<Modal.Header>
<Modal.Title>{`${isModalInEditMode ? i18n('Edit Entitlement Pool') : i18n('Create New Entitlement Pool')}`}</Modal.Title>
</Modal.Header>
<Modal.Body>
{
isDisplayModal && (
- <EntitlementPoolsEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
+ <EntitlementPoolsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
)
}
</Modal.Body>
</Modal>
-
- <EntitlementPoolsConfirmationModal licenseModelId={licenseModelId}/>
</div>
);
}
@@ -92,14 +102,15 @@ class EntitlementPoolsListEditorView extends React.Component {
className='list-editor-item-view'
isReadOnlyMode={isReadOnlyMode}>
<div className='list-editor-item-view-field'>
+
<div className='title'>{i18n('Name')}</div>
- <div className='text name'>{name}</div>
+ <div ><div className='textEllipses text name'>{name}</div></div>
</div>
<div className='list-editor-item-view-field'>
<div className='title'>{i18n('Entitlement')}</div>
- <div className='entitlement-parameters'>{`${this.extractValue(aggregationFunction)} ${this.extractValue(entitlementMetric)} per ${this.extractValue(time)}`}</div>
- <div className='entitlement-pools-count'>{`${thresholdValue ? thresholdValue : ''} ${this.extractUnits(thresholdUnits)}`}</div>
+ <div className='entitlement-parameters'>{`${extractValue(aggregationFunction)} ${extractValue(entitlementMetric)} per ${extractValue(time)}`}</div>
+ <div className='entitlement-pools-count'>{`${thresholdValue ? thresholdValue : ''} ${extractUnits(thresholdUnits)}`}</div>
</div>
<div className='list-editor-item-view-field'>
@@ -115,18 +126,22 @@ class EntitlementPoolsListEditorView extends React.Component {
);
}
-
-
- extractUnits(units) {
- if (units === undefined) {return '';} //TODO fix it later
- return units === 'Absolute' ? '' : '%';
- }
-
- extractValue(item) {
- if (item === undefined) {return '';} //TODO fix it later
-
- return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
- }
}
export default EntitlementPoolsListEditorView;
+
+export function generateConfirmationMsg(entitlementPoolToDelete) {
+ let poolName = entitlementPoolToDelete ? entitlementPoolToDelete.name : '';
+ let msg = i18n('Are you sure you want to delete "{poolName}"?', {poolName});
+ let subMsg = entitlementPoolToDelete
+ && entitlementPoolToDelete.referencingFeatureGroups
+ && entitlementPoolToDelete.referencingFeatureGroups.length > 0 ?
+ i18n('This entitlement pool is associated with one or more feature groups') :
+ '';
+ return (
+ <div>
+ <p>{msg}</p>
+ <p>{subMsg}</p>
+ </div>
+ );
+}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js
index 63e351fce7..fefd823207 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './EntitlementPoolsConstants';
export default (state = [], action) => {
switch (action.type) {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
index c2b269bcf9..c6249c98ca 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
@@ -1,66 +1,78 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js';
import FeatureGroupEditorView from './FeatureGroupEditorView.jsx';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-const mapStateToProps = ({licenseModel: {featureGroup, entitlementPool, licenseKeyGroup}}) => {
-
+export const mapStateToProps = ({licenseModel: {featureGroup, entitlementPool, licenseKeyGroup}}) => {
+ let {entitlementPoolsList = []} = entitlementPool;
+ let {licenseKeyGroupsList = []} = licenseKeyGroup;
const {featureGroupEditor} = featureGroup;
+ let {data, selectedTab, genericFieldInfo, formReady} = featureGroupEditor;
+ const featureGroupId = data ? data.id : null;
+ const list = featureGroup.featureGroupsList;
- let {data, selectedTab, selectedEntitlementPoolsButtonTab, selectedLicenseKeyGroupsButtonTab} = featureGroupEditor;
+ let previousData, FGNames = {}, isFormValid = true, invalidTabs = [];
- let previousData;
- const featureGroupId = data ? data.id : null;
if (featureGroupId) {
- previousData = featureGroup.featureGroupsList.find(featureGroup => featureGroup.id === featureGroupId);
+ previousData = list.find(featureGroup => featureGroup.id === featureGroupId);
+ }
+
+ for (let i = 0; i < list.length; i++) {
+ FGNames[list[i].name] = list[i].id;
+ }
+
+ for (let field in genericFieldInfo) {
+ if (!genericFieldInfo[field].isValid) {
+ isFormValid = false;
+ let tabId = genericFieldInfo[field].tabId;
+ if (invalidTabs.indexOf(tabId) === -1) {
+ invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId;
+ }
+ }
}
- let {entitlementPoolsList = []} = entitlementPool;
- let {licenseKeyGroupsList = []} = licenseKeyGroup;
return {
data,
previousData,
selectedTab,
- selectedEntitlementPoolsButtonTab,
- selectedLicenseKeyGroupsButtonTab,
entitlementPoolsList,
- licenseKeyGroupsList
+ licenseKeyGroupsList,
+ isFormValid,
+ formReady,
+ genericFieldInfo,
+ invalidTabs,
+ FGNames
};
};
-const mapActionsToProps = (dispatch, {licenseModelId}) => {
+const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onTabSelect: tab => FeatureGroupsActionHelper.selectEntitlementPoolsEditorTab(dispatch, {tab}),
- onEntitlementPoolsButtonTabSelect: buttonTab => FeatureGroupsActionHelper.selectFeatureGroupsEditorEntitlementPoolsButtonTab(dispatch, {buttonTab}),
- onLicenseKeyGroupsButtonTabSelect: buttonTab => FeatureGroupsActionHelper.selectFeatureGroupsEditorLicenseKeyGroupsButtonTab(dispatch, {buttonTab}),
- onDataChanged: deltaData => FeatureGroupsActionHelper.featureGroupsEditorDataChanged(dispatch, {deltaData}),
onSubmit: (previousFeatureGroup, featureGroup) => {
FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch);
- FeatureGroupsActionHelper.saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup});
- }
+ FeatureGroupsActionHelper.saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup, version});
+ },
+ onCancel: () => FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch),
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
};
};
export default connect(mapStateToProps, mapActionsToProps)(FeatureGroupEditorView);
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
index 6fecd16b71..5ae22cba95 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
@@ -1,27 +1,125 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import ValidationTabs from 'nfvo-components/input/validation/ValidationTabs.jsx';
-import ValidationTab from 'nfvo-components/input/validation/ValidationTab.jsx';
-import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
-import Button from 'react-bootstrap/lib/Button.js';
-
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+import Tabs from 'nfvo-components/input/validation/Tabs.jsx';
+import Tab from 'react-bootstrap/lib/Tab.js';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
-import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
-import ListEditorViewItem from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import Input from 'nfvo-components/input/validation/Input.jsx';
import i18n from 'nfvo-utils/i18n/i18n.js';
+import Validator from 'nfvo-utils/Validator.js';
-import {state as FeatureGroupStateConstants} from './FeatureGroupsConstants.js';
+import {state as FeatureGroupStateConstants, FG_EDITOR_FORM} from './FeatureGroupsConstants.js';
const FeatureGroupsPropType = React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string,
description: React.PropTypes.string,
partNumber: React.PropTypes.string,
- entitlementPoolsIds: React.PropTypes.array(React.PropTypes.string),
- licenseKeyGroupsIds: React.PropTypes.array(React.PropTypes.string)
+ entitlementPoolsIds: React.PropTypes.arrayOf(React.PropTypes.string),
+ licenseKeyGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string)
});
+const GeneralTab = ({data = {}, onDataChanged, genericFieldInfo, validateName}) => {
+ let {name, description, partNumber} = data;
+ return (
+ <GridSection>
+ <GridItem colSpan={2}>
+ <Input
+ groupClassName='field-section'
+ onChange={name => onDataChanged({name}, FG_EDITOR_FORM, {name: validateName})}
+ label={i18n('Name')}
+ data-test-id='create-fg-name'
+ value={name}
+ name='feature-group-name'
+ type='text'
+ isRequired={true}
+ isValid={genericFieldInfo.name.isValid}
+ errorText={genericFieldInfo.name.errorText} />
+ <Input
+ groupClassName='field-section'
+ className='description-field'
+ onChange={description => onDataChanged({description}, FG_EDITOR_FORM)}
+ data-test-id='create-fg-description'
+ label={i18n('Description')}
+ value={description}
+ name='feature-group-description'
+ type='textarea'
+ isRequired={true}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText} />
+ <Input
+ groupClassName='field-section'
+ onChange={partNumber => onDataChanged({partNumber}, FG_EDITOR_FORM)}
+ label={i18n('Part Number')}
+ data-test-id='create-fg-part-number'
+ value={partNumber}
+ isRequired={true}
+ type='text'
+ isValid={genericFieldInfo.partNumber.isValid}
+ errorText={genericFieldInfo.partNumber.errorText} />
+ </GridItem>
+ </GridSection>
+ );
+};
+
+const EntitlementPoolsTab = ({entitlementPoolsList, data, onDataChanged, isReadOnlyMode}) => {
+ const dualBoxFilterTitle = {
+ left: i18n('Available Entitlement Pools'),
+ right: i18n('Selected Entitlement Pools')
+ };
+ if (entitlementPoolsList.length > 0) {
+ return (
+ <DualListboxView
+ isReadOnlyMode={isReadOnlyMode}
+ filterTitle={dualBoxFilterTitle}
+ selectedValuesList={data.entitlementPoolsIds}
+ availableList={entitlementPoolsList}
+ onChange={ selectedValuesList => onDataChanged( { entitlementPoolsIds: selectedValuesList }, FG_EDITOR_FORM )}/>
+ );
+ } else {
+ return (
+ <p>{i18n('There is no available entitlement pools')}</p>
+ );
+ }
+};
+
+const LKGTab = ({licenseKeyGroupsList, data, onDataChanged, isReadOnlyMode}) => {
+ const dualBoxFilterTitle = {
+ left: i18n('Available License Key Groups'),
+ right: i18n('Selected License Key Groups')
+ };
+ if (licenseKeyGroupsList.length > 0) {
+ return (
+ <DualListboxView
+ isReadOnlyMode={isReadOnlyMode}
+ filterTitle={dualBoxFilterTitle}
+ selectedValuesList={data.licenseKeyGroupsIds}
+ availableList={licenseKeyGroupsList}
+ onChange={ selectedValuesList => onDataChanged( { licenseKeyGroupsIds: selectedValuesList }, FG_EDITOR_FORM )}/>
+ );
+ } else {
+ return (
+ <p>{i18n('There is no available licsense key groups')}</p>
+ );
+ }
+};
+
class FeatureGroupEditorView extends React.Component {
@@ -29,6 +127,7 @@ class FeatureGroupEditorView extends React.Component {
data: FeatureGroupsPropType,
previousData: FeatureGroupsPropType,
isReadOnlyMode: React.PropTypes.bool,
+ FGNames: React.PropTypes.object,
onSubmit: React.PropTypes.func,
onCancel: React.PropTypes.func,
@@ -36,11 +135,6 @@ class FeatureGroupEditorView extends React.Component {
selectedTab: React.PropTypes.number,
onTabSelect: React.PropTypes.func,
- selectedEntitlementPoolsButtonTab: React.PropTypes.number,
- selectedLicenseKeyGroupsButtonTab: React.PropTypes.number,
- onEntitlementPoolsButtonTabSelect: React.PropTypes.func,
- onLicenseKeyGroupsButtonTabSelect: React.PropTypes.func,
-
entitlementPoolsList: DualListboxView.propTypes.availableList,
licenseKeyGroupsList: DualListboxView.propTypes.availableList
};
@@ -49,8 +143,6 @@ class FeatureGroupEditorView extends React.Component {
static defaultProps = {
data: {},
selectedTab: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL,
- selectedEntitlementPoolsButtonTab: FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS,
- selectedLicenseKeyGroupsButtonTab: FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS
};
state = {
@@ -60,24 +152,39 @@ class FeatureGroupEditorView extends React.Component {
render() {
- let {selectedTab, onTabSelect, isReadOnlyMode} = this.props;
+ let {selectedTab, onTabSelect, isReadOnlyMode, invalidTabs, data, onDataChanged, genericFieldInfo, entitlementPoolsList, licenseKeyGroupsList} = this.props;
return (
- <ValidationForm
+ <div>
+ { genericFieldInfo && <Form
ref='validationForm'
hasButtons={true}
onSubmit={ () => this.submit() }
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm(FG_EDITOR_FORM) }
onReset={ () => this.props.onCancel() }
labledButtons={true}
isReadOnlyMode={isReadOnlyMode}
name='feature-group-validation-form'
className='feature-group-form'>
- <ValidationTabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect}>
- {this.renderGeneralTab()}
- {this.renderEntitlementPoolsTab()}
- {this.renderLicenseKeyGroupsTab()}
- </ValidationTabs>
-
- </ValidationForm>
+ <Tabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect} invalidTabs={invalidTabs} id='vlmFGValTabs' >
+ <Tab eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')} >
+ <GeneralTab data={data} onDataChanged={onDataChanged} genericFieldInfo={genericFieldInfo} validateName={(value)=> this.validateName(value)}/>
+ </Tab>
+ <Tab
+ eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
+ title={i18n('Entitlement Pools')} >
+ <EntitlementPoolsTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} entitlementPoolsList={entitlementPoolsList} />
+ </Tab>
+ <Tab
+ eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENSE_KEY_GROUPS}
+ title={i18n('License Key Groups')} >
+ <LKGTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} licenseKeyGroupsList={licenseKeyGroupsList} />
+ </Tab>
+ </Tabs>
+
+ </Form> }
+ </div>
);
}
@@ -86,254 +193,14 @@ class FeatureGroupEditorView extends React.Component {
this.props.onSubmit(previousFeatureGroup, featureGroup);
}
- renderGeneralTab() {
- let {data = {}, onDataChanged} = this.props;
- let {name, description, partNumber} = data;
- return (
- <ValidationTab eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')}>
- <div>
- <ValidationInput
- groupClassName='field-section'
- onChange={name => onDataChanged({name})}
- ref='name'
- label={i18n('Name')}
- value={name}
- name='feature-group-name'
- validations={{maxLength: 120, required: true}}
- type='text'/>
- <ValidationInput
- groupClassName='field-section'
- className='description-field'
- onChange={description => onDataChanged({description})}
- ref='description'
- label={i18n('Description')}
- value={description}
- name='feature-group-description'
- validations={{maxLength: 1000, required: true}}
- type='textarea'/>
- <ValidationInput
- groupClassName='field-section'
- onChange={partNumber => onDataChanged({partNumber})}
- label={i18n('Part Number')}
- value={partNumber}
- validations={{required: true}}
- type='text'/>
- </div>
- </ValidationTab>
- );
- }
-
- renderEntitlementPoolsTab() {
- let {selectedEntitlementPoolsButtonTab, onEntitlementPoolsButtonTabSelect, entitlementPoolsList} = this.props;
- if (entitlementPoolsList.length > 0) {
- return (
- <ValidationTab
- eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
- title={i18n('Entitlement Pools')}>
- <ButtonGroup>
- {
- this.renderButtonsTab(
- FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS,
- selectedEntitlementPoolsButtonTab,
- i18n('Associated Entitlement Pools'),
- onEntitlementPoolsButtonTabSelect
- )
- }
- {
- this.renderButtonsTab(
- FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.AVAILABLE_ENTITLEMENT_POOLS,
- selectedEntitlementPoolsButtonTab,
- i18n('Available Entitlement Pools'),
- onEntitlementPoolsButtonTabSelect
- )
- }
- </ButtonGroup>
- {this.renderEntitlementPoolsButtonTabContent(selectedEntitlementPoolsButtonTab)}
- </ValidationTab>
- );
- } else {
- return (
- <ValidationTab
- eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
- title={i18n('Entitlement Pools')}>
- <p>{i18n('There is no available entitlement pools.')}</p>
- </ValidationTab>
- );
- }
- }
-
- renderLicenseKeyGroupsTab() {
- let {selectedLicenseKeyGroupsButtonTab, onLicenseKeyGroupsButtonTabSelect, licenseKeyGroupsList} = this.props;
- if (licenseKeyGroupsList.length > 0) {
- return (
- <ValidationTab
- eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS}
- title={i18n('License Key Groups')}>
- <ButtonGroup>
- {
- this.renderButtonsTab(
- FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS,
- selectedLicenseKeyGroupsButtonTab,
- i18n('Associated License Key Groups'),
- onLicenseKeyGroupsButtonTabSelect
- )
- }
- {
- this.renderButtonsTab(
- FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.AVAILABLE_LICENSE_KEY_GROUPS,
- selectedLicenseKeyGroupsButtonTab,
- i18n('Available License Key Groups'),
- onLicenseKeyGroupsButtonTabSelect
- )
- }
- </ButtonGroup>
- {this.renderLicenseKeyGroupsTabContent(selectedLicenseKeyGroupsButtonTab)}
- </ValidationTab>
- );
- } else {
- return (
- <ValidationTab
- eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS}
- title={i18n('License Key Groups')}>
- <p>{i18n('There is no available license key groups')}</p>
- </ValidationTab>);
- }
- }
-
- renderButtonsTab(buttonTab, selectedButtonTab, title, onClick) {
- const isSelected = buttonTab === selectedButtonTab;
- return (
- <Button
- className='button-tab'
- active={isSelected}
- onClick={() => !isSelected && onClick(buttonTab)}>
- { title }
- </Button>
- );
- }
-
- renderEntitlementPoolsButtonTabContent(selectedFeatureGroupsButtonTab) {
- const {entitlementPoolsList = [], data: {entitlementPoolsIds = []}} = this.props;
- let dualBoxTitle = {
- left: i18n('Available Entitlement Pools'),
- right: i18n('Selected Entitlement Pools')
- };
-
- if (entitlementPoolsList.length) {
- const {localEntitlementPoolsListFilter} = this.state;
- let selectedEntitlementPools = entitlementPoolsIds.map(entitlementPoolId => entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId));
-
- switch (selectedFeatureGroupsButtonTab) {
- case FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS:
- if (selectedEntitlementPools.length) {
- return (
- <ListEditorView
- className='thinner-list'
- filterValue={localEntitlementPoolsListFilter}
- onFilter={localEntitlementPoolsListFilter => this.setState({localEntitlementPoolsListFilter})}>
- {this.filterAssociatedItems(selectedEntitlementPools, localEntitlementPoolsListFilter)
- .map(entitlementPool => this.renderAssociatedListItem(entitlementPool
- , FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS))}
- </ListEditorView>
- );
- }
- else {
- return (
- <div>
- <br/>{i18n('There are currently no entitlement pools associated with this feature group. Click "Available Entitlement Pools" to associate.')}
- </div>
- );
- }
- case FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.AVAILABLE_ENTITLEMENT_POOLS:
- return (
- <DualListboxView
- filterTitle={dualBoxTitle}
- selectedValuesList={entitlementPoolsIds}
- availableList={entitlementPoolsList}
- onChange={ selectedValuesList => this.props.onDataChanged( { entitlementPoolsIds: selectedValuesList } )}/>
- );
- }
- }
- }
-
- renderLicenseKeyGroupsTabContent(selectedFeatureGroupsButtonTab) {
- const {licenseKeyGroupsList = [], data: {licenseKeyGroupsIds = []}} = this.props;
- let dualBoxFilterTitle = {
- left: i18n('Available License Key Groups'),
- right: i18n('Selected License Key Groups')
- };
-
- if (licenseKeyGroupsList.length) {
- const {localLicenseKeyGroupsListFilter} = this.state;
- let selectedLicenseKeyGroups = licenseKeyGroupsIds.map(licenseKeyGroupId => licenseKeyGroupsList.find(licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId));
-
- switch (selectedFeatureGroupsButtonTab) {
- case FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS:
- if (selectedLicenseKeyGroups.length) {
- return (
- <ListEditorView
- className='thinner-list'
- filterValue={localLicenseKeyGroupsListFilter}
- onFilter={localLicenseKeyGroupsListFilter => this.setState({localLicenseKeyGroupsListFilter})}>
- {this.filterAssociatedItems(selectedLicenseKeyGroups, localLicenseKeyGroupsListFilter)
- .map(licenseKeyGroup => this.renderAssociatedListItem(licenseKeyGroup
- , FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS))}
- </ListEditorView>
- );
- } else {
- return (
- <div className='no-items-msg'>
- {i18n('There are currently no license key groups associated with this feature group. Click "Available License Key Groups" to associate.')}
- </div>
- );
- }
- case FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.AVAILABLE_LICENSE_KEY_GROUPS:
- return (
- <DualListboxView
- filterTitle={dualBoxFilterTitle}
- selectedValuesList={this.props.data.licenseKeyGroupsIds}
- availableList={this.props.licenseKeyGroupsList}
- onChange={ selectedValuesList => this.props.onDataChanged( { licenseKeyGroupsIds: selectedValuesList } )}/>
- );
- }
- }
- }
-
-
- renderAssociatedListItem(listItem, itemType) {
- let {isReadOnlyMode} = this.props;
- return (
- <ListEditorViewItem
- key={listItem.id}
- onDelete={() => this.deleteAssociatedItem(listItem.id, itemType)}
- isReadOnlyMode={isReadOnlyMode}>
- <div className='name'>{listItem.name}</div>
- <div className='description'>{listItem.description}</div>
- </ListEditorViewItem>
- );
- }
-
- filterAssociatedItems(list, localList) {
- if (localList) {
- const filter = new RegExp(escape(localList), 'i');
- return list.filter(({name = '', description = ''}) => name.match(filter) || description.match(filter));
- }
- else {
- return list;
- }
- }
-
- deleteAssociatedItem(id, type) {
- const {data: {licenseKeyGroupsIds = [], entitlementPoolsIds = []}} = this.props;
- if (type === FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS) {
- this.props.onDataChanged({licenseKeyGroupsIds: licenseKeyGroupsIds.filter(listId => listId !== id)});
- } else {
- this.props.onDataChanged({entitlementPoolsIds: entitlementPoolsIds.filter(listId => listId !== id)});
- }
+ validateName(value) {
+ const {data: {id}, FGNames} = this.props;
+ const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: FGNames});
+ return !isExists ? {isValid: true, errorText: ''} :
+ {isValid: false, errorText: i18n('Feature group by the name \'' + value + '\' already exists. Feature group name must be unique')};
}
}
export default FeatureGroupEditorView;
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js
index 9ea5a31490..83473a30bb 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js
@@ -1,35 +1,33 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+
import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js';
-import FeatureGroupListEditorView from './FeatureGroupListEditorView.jsx';
+import FeatureGroupListEditorView, {generateConfirmationMsg} from './FeatureGroupListEditorView.jsx';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js';
-const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) => {
+export const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) => {
const {featureGroupEditor: {data}, featureGroupsList} = featureGroup;
- let {vendorName} = licenseModelEditor.data;
+ let {vendorName, version} = licenseModelEditor.data;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data);
-
return {
vendorName,
+ version,
featureGroupsModal: {
show: Boolean(data),
editMode: Boolean(data && data.id)
@@ -42,13 +40,19 @@ const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) =>
const mapActionsToProps = (dispatch, {licenseModelId}) => {
return {
- onDeleteFeatureGroupClick: (featureGroup) => FeatureGroupsActionHelper.openDeleteFeatureGroupConfirm(dispatch, {licenseModelId, featureGroup}),
- onCancelFeatureGroupsEditor: () => FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch),
-
- onAddFeatureGroupClick: () => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId}),
- onEditFeatureGroupClick: featureGroup => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {
+ onDeleteFeatureGroupClick: (featureGroup, version) => dispatch({
+ type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: generateConfirmationMsg(featureGroup),
+ title: i18n('Warning'),
+ onConfirmed: ()=>FeatureGroupsActionHelper.deleteFeatureGroup(dispatch, {featureGroupId: featureGroup.id, licenseModelId, version})
+ }
+ }),
+ onAddFeatureGroupClick: (actualVersion) => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId, version: actualVersion}),
+ onEditFeatureGroupClick: (featureGroup, actualVersion) => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {
featureGroup,
- licenseModelId
+ licenseModelId,
+ version: actualVersion
})
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
index d998f9216f..bc0f5c71c0 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -6,7 +21,6 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import FeatureGroupEditor from './FeatureGroupEditor.js';
-import FeatureGroupsConfirmationModal from './FeatureGroupsConfirmationModal.jsx';
class FeatureGroupListEditorView extends React.Component {
static propTypes = {
@@ -37,46 +51,45 @@ class FeatureGroupListEditorView extends React.Component {
};
render() {
- let {vendorName, licenseModelId, featureGroupsModal, isReadOnlyMode, onAddFeatureGroupClick} = this.props;
+ let {vendorName, licenseModelId, featureGroupsModal, isReadOnlyMode, onAddFeatureGroupClick, version} = this.props;
const {localFilter} = this.state;
-
return (
<div className='feature-groups-list-editor'>
<ListEditorView
- title={i18n('Feature Groups for {vendorName} License Model', {vendorName})}
+ title={i18n('Feature Groups', {vendorName})}
plusButtonTitle={i18n('Add Feature Group')}
filterValue={localFilter}
- onFilter={filter => this.setState({localFilter: filter})}
- onAdd={() => onAddFeatureGroupClick()}
+ onFilter={value => this.setState({localFilter: value})}
+ onAdd={() => onAddFeatureGroupClick(version)}
isReadOnlyMode={isReadOnlyMode}>
- {this.filterList().map(listItem => this.renderFeatureGroupListItem(listItem, isReadOnlyMode))}
+ {this.filterList().map(listItem => this.renderFeatureGroupListItem(listItem, isReadOnlyMode, version))}
</ListEditorView>
- <Modal show={featureGroupsModal.show} bsSize='large' animation={true} className='feature-group-modal'>
- <Modal.Header>
- <Modal.Title>{`${featureGroupsModal.editMode ? i18n('Edit Feature Group') : i18n('Create New Feature Group')}`}</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- <FeatureGroupEditor
- onCancel={() => this.closeFeatureGroupsEditor()}
- licenseModelId={licenseModelId}
- isReadOnlyMode={isReadOnlyMode}/>
- </Modal.Body>
- </Modal>
-
- <FeatureGroupsConfirmationModal licenseModelId={licenseModelId}/>
+ {featureGroupsModal.show && <Modal show={featureGroupsModal.show} bsSize='large' animation={true}
+ className='onborading-modal feature-group-modal'>
+ <Modal.Header>
+ <Modal.Title>{`${featureGroupsModal.editMode ? i18n('Edit Feature Group') : i18n('Create New Feature Group')}`}</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <FeatureGroupEditor
+ version={version}
+ licenseModelId={licenseModelId}
+ isReadOnlyMode={isReadOnlyMode}/>
+ </Modal.Body>
+ </Modal>
+ }
</div>
);
}
- renderFeatureGroupListItem(listItem, isReadOnlyMode) {
+ renderFeatureGroupListItem(listItem, isReadOnlyMode, version) {
let {name, description, entitlementPoolsIds = [], licenseKeyGroupsIds = []} = listItem;
return (
<ListEditorItemView
key={listItem.id}
- onDelete={() => this.deleteFeatureGroupItem(listItem)}
- onSelect={() => this.editFeatureGroupItem(listItem)}
+ onDelete={() => this.deleteFeatureGroupItem(listItem, version)}
+ onSelect={() => this.editFeatureGroupItem(listItem, version)}
className='list-editor-item-view'
isReadOnlyMode={isReadOnlyMode}>
<div className='list-editor-item-view-field'>
@@ -120,17 +133,28 @@ class FeatureGroupListEditorView extends React.Component {
}
}
- closeFeatureGroupsEditor() {
- this.props.onCancelFeatureGroupsEditor();
- }
-
- editFeatureGroupItem(featureGroup) {
- this.props.onEditFeatureGroupClick(featureGroup);
+ editFeatureGroupItem(featureGroup, version) {
+ this.props.onEditFeatureGroupClick(featureGroup, version);
}
- deleteFeatureGroupItem(featureGroup) {
- this.props.onDeleteFeatureGroupClick(featureGroup);
+ deleteFeatureGroupItem(featureGroup, version) {
+ this.props.onDeleteFeatureGroupClick(featureGroup, version);
}
}
export default FeatureGroupListEditorView;
+
+export function generateConfirmationMsg(featureGroupToDelete) {
+ let name = featureGroupToDelete ? featureGroupToDelete.name : '';
+ let msg = i18n('Are you sure you want to delete "{name}"?', {name});
+ let subMsg = featureGroupToDelete.referencingLicenseAgreements
+ && featureGroupToDelete.referencingLicenseAgreements.length > 0 ?
+ i18n('This feature group is associated with one ore more license agreements') :
+ '';
+ return (
+ <div>
+ <p>{msg}</p>
+ <p>{subMsg}</p>
+ </div>
+ );
+}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
index 3776c01263..a2015787a6 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes as featureGroupsActionConstants} from './FeatureGroupsConstants.js';
@@ -25,22 +20,22 @@ import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseMod
import EntitlementPoolsActionHelper from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js';
import LicenseKeyGroupsActionHelper from 'sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
-function baseUrl(licenseModelId) {
+function baseUrl(licenseModelId, version) {
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/feature-groups`;
+ const {id: versionId} = version;
+ return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/feature-groups`;
}
function fetchFeatureGroupsList(licenseModelId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+ return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
}
-function deleteFeatureGroup(licenseModelId, featureGroupId) {
- return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${featureGroupId}`);
+function deleteFeatureGroup(licenseModelId, featureGroupId, version) {
+ return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${featureGroupId}`);
}
-function addFeatureGroup(licenseModelId, featureGroup) {
- return RestAPIUtil.create(baseUrl(licenseModelId), {
+function addFeatureGroup(licenseModelId, featureGroup, version) {
+ return RestAPIUtil.post(baseUrl(licenseModelId, version), {
name: featureGroup.name,
description: featureGroup.description,
partNumber: featureGroup.partNumber,
@@ -49,13 +44,13 @@ function addFeatureGroup(licenseModelId, featureGroup) {
});
}
-function updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup) {
+function updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup, version) {
const {licenseKeyGroupsIds = []} = featureGroup;
const {licenseKeyGroupsIds: prevLicenseKeyGroupsIds = []} = previousFeatureGroup;
const {entitlementPoolsIds = []} = featureGroup;
const {entitlementPoolsIds: prevEntitlementPoolsIds = []} = previousFeatureGroup;
- return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${featureGroup.id}`, {
+ return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${featureGroup.id}`, {
name: featureGroup.name,
description: featureGroup.description,
partNumber: featureGroup.partNumber,
@@ -75,28 +70,37 @@ export default {
}));
},
- deleteFeatureGroup(dispatch, {licenseModelId, featureGroupId}) {
- return deleteFeatureGroup(licenseModelId, featureGroupId).then(() => dispatch({
+ deleteFeatureGroup(dispatch, {licenseModelId, featureGroupId, version}) {
+ return deleteFeatureGroup(licenseModelId, featureGroupId, version).then(() => dispatch({
type: featureGroupsActionConstants.DELETE_FEATURE_GROUPS,
featureGroupId
}));
},
- saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup}) {
+ saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup, version}) {
if (previousFeatureGroup) {
- return updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup).then(() => dispatch({
- type: featureGroupsActionConstants.EDIT_FEATURE_GROUPS,
- featureGroup
- }));
+ return updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup, version).then(() =>{
+ dispatch({
+ type: featureGroupsActionConstants.EDIT_FEATURE_GROUPS,
+ featureGroup
+ });
+ EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
+ LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
+ });
}
else {
- return addFeatureGroup(licenseModelId, featureGroup).then(response => dispatch({
- type: featureGroupsActionConstants.ADD_FEATURE_GROUPS,
- featureGroup: {
- ...featureGroup,
- id: response.value
- }
- }));
+ return addFeatureGroup(licenseModelId, featureGroup, version).then(response => {
+ dispatch({
+ type: featureGroupsActionConstants.ADD_FEATURE_GROUPS,
+ featureGroup: {
+ ...featureGroup,
+ id: response.value,
+ referencingLicenseAgreements: []
+ }
+ });
+ EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
+ LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
+ });
}
},
@@ -107,23 +111,9 @@ export default {
});
},
- selectFeatureGroupsEditorEntitlementPoolsButtonTab(dispatch, {buttonTab}) {
- dispatch({
- type: featureGroupsActionConstants.featureGroupsEditor.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB,
- buttonTab
- });
- },
-
- selectFeatureGroupsEditorLicenseKeyGroupsButtonTab(dispatch, {buttonTab}) {
- dispatch({
- type: featureGroupsActionConstants.featureGroupsEditor.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB,
- buttonTab
- });
- },
-
- openFeatureGroupsEditor(dispatch, {featureGroup, licenseModelId}) {
- EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId});
- LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId});
+ openFeatureGroupsEditor(dispatch, {featureGroup, licenseModelId, version}) {
+ EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
+ LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
dispatch({
type: featureGroupsActionConstants.featureGroupsEditor.OPEN,
featureGroup
@@ -136,26 +126,6 @@ export default {
});
},
- featureGroupsEditorDataChanged(dispatch, {deltaData}) {
- dispatch({
- type: featureGroupsActionConstants.featureGroupsEditor.DATA_CHANGED,
- deltaData
- });
- },
-
- hideDeleteConfirm(dispatch) {
- dispatch({
- type: featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM,
- featureGroupToDelete: false
- });
- },
-
- openDeleteFeatureGroupConfirm(dispatch, {featureGroup}) {
- dispatch({
- type: featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM,
- featureGroupToDelete: featureGroup
- });
- },
switchVersion(dispatch, {licenseModelId, version}) {
LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx
deleted file mode 100644
index 142ec3c4c8..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import React from 'react';
-import {connect} from 'react-redux';
-import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
-import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-function renderMsg(featureGroupToDelete) {
- let name = featureGroupToDelete ? featureGroupToDelete.name : '';
- let msg = i18n('Are you sure you want to delete "{name}"?', {name});
- let subMsg = featureGroupToDelete
- && featureGroupToDelete.referencingLicenseAgreements
- && featureGroupToDelete.referencingLicenseAgreements.length > 0 ?
- i18n('This feature group is associated with one ore more license agreements') :
- '';
- return (
- <div>
- <p>{msg}</p>
- <p>{subMsg}</p>
- </div>
- );
-};
-
-const mapStateToProps = ({licenseModel: {featureGroup}}, {licenseModelId}) => {
- let {featureGroupToDelete} = featureGroup;
- const show = featureGroupToDelete !== false;
- return {
- show,
- title: 'Warning!',
- type: 'warning',
- msg: renderMsg(featureGroupToDelete),
- confirmationDetails: {featureGroupToDelete, licenseModelId}
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
- onConfirmed: ({featureGroupToDelete, licenseModelId}) => {
- FeatureGroupsActionHelper.deleteFeatureGroup(dispatch, {featureGroupId: featureGroupToDelete.id, licenseModelId});
- FeatureGroupsActionHelper.hideDeleteConfirm(dispatch);
- },
- onDeclined: () => {
- FeatureGroupsActionHelper.hideDeleteConfirm(dispatch);
- }
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js
index e02c54595d..4c5a94f239 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
@@ -25,8 +20,6 @@ export const actionTypes = keyMirror({
ADD_FEATURE_GROUPS: null,
EDIT_FEATURE_GROUPS: null,
DELETE_FEATURE_GROUPS: null,
- FEATURE_GROUPS_DELETE_CONFIRM: null,
-
ENTITLEMENT_POOLS_LIST_LOADED: null,
@@ -34,27 +27,16 @@ export const actionTypes = keyMirror({
OPEN: null,
CLOSE: null,
DATA_CHANGED: null,
- SELECT_TAB: null,
- SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: null,
- SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB: null
+ SELECT_TAB: null
}
});
+export const FG_EDITOR_FORM = 'FG_EDITOR_FORM';
+
export const state = keyMirror({
SELECTED_FEATURE_GROUP_TAB: {
GENERAL: 1,
ENTITLEMENT_POOLS: 2,
- LICENCE_KEY_GROUPS: 3
- },
- SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: {
- ASSOCIATED_ENTITLEMENT_POOLS: 1,
- AVAILABLE_ENTITLEMENT_POOLS: 2
- },
- SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB: {
- ASSOCIATED_LICENSE_KEY_GROUPS: 1,
- AVAILABLE_LICENSE_KEY_GROUPS: 2
- },
+ LICENSE_KEY_GROUPS: 3
+ }
});
-
-
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
index 576a5358e6..001bd20d44 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
@@ -1,24 +1,20 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-import {actionTypes} from './FeatureGroupsConstants.js';
+import {actionTypes, FG_EDITOR_FORM, state as FeatureGroupStateConstants} from './FeatureGroupsConstants.js';
@@ -27,14 +23,28 @@ export default (state = {}, action) => {
case actionTypes.featureGroupsEditor.OPEN:
return {
...state,
- data: action.featureGroup || {}
- };
- case actionTypes.featureGroupsEditor.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
+ data: action.featureGroup || {},
+ formReady: null,
+ formName: FG_EDITOR_FORM,
+ genericFieldInfo: {
+ 'description': {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}],
+ tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
+ },
+ 'partNumber': {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}],
+ tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
+ },
+ 'name': {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}],
+ tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
+ }
}
};
case actionTypes.featureGroupsEditor.CLOSE:
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js
index 5cf3248919..3b5f1c55e4 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './FeatureGroupsConstants.js';
export default (state = [], action) => {
switch (action.type) {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js
index 9616b60b76..efc4fb758f 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js
@@ -1,41 +1,36 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes as licenseAgreementActionTypes} from './LicenseAgreementConstants.js';
import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
-function baseUrl(licenseModelId) {
+function baseUrl(licenseModelId, version) {
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/license-agreements`;
+ const {id: versionId} = version;
+ return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-agreements`;
}
function fetchLicenseAgreementList(licenseModelId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+ return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
}
-function postLicenseAgreement(licenseModelId, licenseAgreement) {
- return RestAPIUtil.create(baseUrl(licenseModelId), {
+function postLicenseAgreement(licenseModelId, licenseAgreement, version) {
+ return RestAPIUtil.post(baseUrl(licenseModelId, version), {
name: licenseAgreement.name,
description: licenseAgreement.description,
licenseTerm: licenseAgreement.licenseTerm,
@@ -44,10 +39,10 @@ function postLicenseAgreement(licenseModelId, licenseAgreement) {
});
}
-function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement) {
+function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement, version) {
const {featureGroupsIds = []} = licenseAgreement;
const {featureGroupsIds: prevFeatureGroupsIds = []} = previousLicenseAgreement;
- return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${licenseAgreement.id}`, {
+ return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseAgreement.id}`, {
name: licenseAgreement.name,
description: licenseAgreement.description,
licenseTerm: licenseAgreement.licenseTerm,
@@ -57,8 +52,8 @@ function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAg
});
}
-function deleteLicenseAgreement(licenseModelId, licenseAgreementId) {
- return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${licenseAgreementId}`);
+function deleteLicenseAgreement(licenseModelId, licenseAgreementId, version) {
+ return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseAgreementId}`);
}
export default {
@@ -70,21 +65,14 @@ export default {
}));
},
- openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement}) {
- FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId});
+ openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement, version}) {
+ FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version});
dispatch({
type: licenseAgreementActionTypes.licenseAgreementEditor.OPEN,
licenseAgreement
});
},
- licenseAgreementEditorDataChanged(dispatch, {deltaData}) {
- dispatch({
- type: licenseAgreementActionTypes.licenseAgreementEditor.DATA_CHANGED,
- deltaData
- });
- },
-
closeLicenseAgreementEditor(dispatch) {
dispatch({
type: licenseAgreementActionTypes.licenseAgreementEditor.CLOSE
@@ -92,9 +80,9 @@ export default {
},
- saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement}) {
+ saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement, version}) {
if (previousLicenseAgreement) {
- return putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement).then(() => {
+ return putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement, version).then(() => {
dispatch({
type: licenseAgreementActionTypes.EDIT_LICENSE_AGREEMENT,
licenseAgreement
@@ -102,7 +90,7 @@ export default {
});
}
else {
- return postLicenseAgreement(licenseModelId, licenseAgreement).then(response => {
+ return postLicenseAgreement(licenseModelId, licenseAgreement, version).then(response => {
dispatch({
type: licenseAgreementActionTypes.ADD_LICENSE_AGREEMENT,
licenseAgreement: {
@@ -114,8 +102,8 @@ export default {
}
},
- deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId}) {
- return deleteLicenseAgreement(licenseModelId, licenseAgreementId).then(() => {
+ deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId, version}) {
+ return deleteLicenseAgreement(licenseModelId, licenseAgreementId, version).then(() => {
dispatch({
type: licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT,
licenseAgreementId
@@ -130,31 +118,9 @@ export default {
});
},
- selectLicenseAgreementEditorFeatureGroupsButtonTab(dispatch, {buttonTab}) {
- dispatch({
- type: licenseAgreementActionTypes.licenseAgreementEditor.SELECT_FEATURE_GROUPS_BUTTONTAB,
- buttonTab
- });
- },
-
- hideDeleteConfirm(dispatch) {
- dispatch({
- type: licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM,
- licenseAgreementToDelete: false
- });
- },
-
- openDeleteLicenseAgreementConfirm(dispatch, {licenseAgreement} ) {
- dispatch({
- type: licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM,
- licenseAgreementToDelete: licenseAgreement
- });
- },
-
switchVersion(dispatch, {licenseModelId, version}) {
LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
this.fetchLicenseAgreementList(dispatch, {licenseModelId, version});
});
}
};
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx
deleted file mode 100644
index 42f2407696..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react';
-import {connect} from 'react-redux';
-import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
-import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-function renderMsg(licenseAgreementToDelete) {
- let name = licenseAgreementToDelete ? licenseAgreementToDelete.name : '';
- let msg = i18n('Are you sure you want to delete "{name}"?', {name});
- return(
- <div>
- <p>{msg}</p>
- </div>
- );
-};
-
-const mapStateToProps = ({licenseModel: {licenseAgreement}}, {licenseModelId}) => {
- let {licenseAgreementToDelete} = licenseAgreement;
- const show = licenseAgreementToDelete !== false;
- return {
- show,
- title: 'Warning!',
- type: 'warning',
- msg: renderMsg(licenseAgreementToDelete),
- confirmationDetails: {licenseAgreementToDelete, licenseModelId}
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
- onConfirmed: ({licenseAgreementToDelete, licenseModelId}) => {
-
- LicenseAgreementActionHelper.deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId: licenseAgreementToDelete.id});
- LicenseAgreementActionHelper.hideDeleteConfirm(dispatch);
- },
- onDeclined: () => {
- LicenseAgreementActionHelper.hideDeleteConfirm(dispatch);
- }
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
index af5c454e22..998d5f0e8d 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
@@ -1,52 +1,43 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
export const actionTypes = keyMirror({
LICENSE_AGREEMENT_LIST_LOADED: null,
ADD_LICENSE_AGREEMENT: null,
EDIT_LICENSE_AGREEMENT: null,
DELETE_LICENSE_AGREEMENT: null,
- LICENSE_AGREEMENT_DELETE_CONFIRM: null,
licenseAgreementEditor: {
OPEN: null,
CLOSE: null,
DATA_CHANGED: null,
- SELECT_TAB: null,
- SELECT_FEATURE_GROUPS_BUTTONTAB: null,
+ SELECT_TAB: null
}
});
+export const LA_EDITOR_FORM = 'LA_EDITOR_FORM';
+
export const enums = keyMirror({
SELECTED_LICENSE_AGREEMENT_TAB: {
GENERAL: 1,
FEATURE_GROUPS: 2
- },
-
- SELECTED_FEATURE_GROUPS_BUTTONTAB: {
- ASSOCIATED_FEATURE_GROUPS: 1,
- AVAILABLE_FEATURE_GROUPS: 2
}
});
@@ -64,3 +55,11 @@ export const optionsInputValues = {
{enum: 'Unlimited', title: 'Unlimited'}
]
};
+
+export const extractValue = (item) => {
+ if (item === undefined) {
+ return '';
+ } //TODO fix it later
+
+ return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
index 6a3e4dbc73..aada8ddca1 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
@@ -1,31 +1,29 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
import LicenseAgreementEditorView from './LicenseAgreementEditorView.jsx';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}}) => {
- let {data, selectedTab, selectedFeatureGroupsButtonTab} = licenseAgreement.licenseAgreementEditor;
+ let {data, selectedTab, genericFieldInfo, formReady} = licenseAgreement.licenseAgreementEditor;
+ const list = licenseAgreement.licenseAgreementList;
+ const LANames = {};
let previousData;
const licenseAgreementId = data ? data.id : null;
@@ -33,27 +31,47 @@ export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}}
previousData = licenseAgreement.licenseAgreementList.find(licenseAgreement => licenseAgreement.id === licenseAgreementId);
}
+ for (let i = 0; i < list.length; i++) {
+ LANames[list[i].name] = list[i].id;
+ }
+
const {featureGroupsList = []} = featureGroup;
+ let isFormValid = true;
+ let invalidTabs = [];
+ for (let field in genericFieldInfo) {
+ if (!genericFieldInfo[field].isValid) {
+ isFormValid = false;
+ let tabId = genericFieldInfo[field].tabId;
+ if (invalidTabs.indexOf(tabId) === -1) {
+ invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId;
+ }
+ }
+ }
+
return {
data,
previousData,
selectedTab,
- selectedFeatureGroupsButtonTab,
- featureGroupsList
+ featureGroupsList,
+ LANames,
+ genericFieldInfo,
+ isFormValid,
+ formReady,
+ invalidTabs
};
};
-export const mapActionsToProps = (dispatch, {licenseModelId}) => {
+export const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
- onDataChanged: deltaData => LicenseAgreementActionHelper.licenseAgreementEditorDataChanged(dispatch, {deltaData}),
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onTabSelect: tab => LicenseAgreementActionHelper.selectLicenseAgreementEditorTab(dispatch, {tab}),
- onFeatureGroupsButtonTabSelect: buttonTab => LicenseAgreementActionHelper.selectLicenseAgreementEditorFeatureGroupsButtonTab(dispatch, {buttonTab}),
onCancel: () => LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch),
onSubmit: ({previousLicenseAgreement, licenseAgreement}) => {
LicenseAgreementActionHelper.closeLicenseAgreementEditor(dispatch);
- LicenseAgreementActionHelper.saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement});
- }
+ LicenseAgreementActionHelper.saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement, version});
+ },
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
index 74e2f6e8c1..e02935c579 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
@@ -1,40 +1,55 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes, defaultState} from './LicenseAgreementConstants.js';
+import {actionTypes, defaultState, LA_EDITOR_FORM, enums as LicenseAgreementEnums} from './LicenseAgreementConstants.js';
export default (state = {}, action) => {
switch (action.type) {
case actionTypes.licenseAgreementEditor.OPEN:
return {
...state,
+ formReady: null,
+ formName: LA_EDITOR_FORM,
+ genericFieldInfo: {
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}],
+ tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
+ },
+ 'requirementsAndConstrains' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 1000}],
+ tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
+ },
+ 'licenseTerm' : {
+ isValid: true,
+ errorText: '',
+ validations: [],
+ tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
+ },
+ 'name' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}],
+ tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
+ }
+ },
data: action.licenseAgreement ? { ...action.licenseAgreement } : defaultState.LICENSE_AGREEMENT_EDITOR_DATA
};
- case actionTypes.licenseAgreementEditor.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
- }
- };
case actionTypes.licenseAgreementEditor.CLOSE:
return {};
case actionTypes.licenseAgreementEditor.SELECT_TAB:
@@ -42,11 +57,6 @@ export default (state = {}, action) => {
...state,
selectedTab: action.tab
};
- case actionTypes.licenseAgreementEditor.SELECT_FEATURE_GROUPS_BUTTONTAB:
- return {
- ...state,
- selectedFeatureGroupsButtonTab: action.buttonTab
- };
default:
return state;
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
index b21f943fed..67a3333a3a 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
@@ -1,17 +1,36 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
-import Button from 'react-bootstrap/lib/Button.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationTabs from 'nfvo-components/input/validation/ValidationTabs.jsx';
-import ValidationTab from 'nfvo-components/input/validation/ValidationTab.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import Tabs from 'nfvo-components/input/validation/Tabs.jsx';
+import Tab from 'react-bootstrap/lib/Tab.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
-import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
-import ListEditorViewItem from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import i18n from 'nfvo-utils/i18n/i18n.js';
+import Validator from 'nfvo-utils/Validator.js';
-import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues} from './LicenseAgreementConstants.js';
+import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues, LA_EDITOR_FORM} from './LicenseAgreementConstants.js';
+const dualBoxFilterTitle = {
+ left: i18n('Available Feature Groups'),
+ right: i18n('Selected Feature Groups')
+};
const LicenseAgreementPropType = React.PropTypes.shape({
id: React.PropTypes.string,
@@ -19,14 +38,77 @@ const LicenseAgreementPropType = React.PropTypes.shape({
description: React.PropTypes.string,
requirementsAndConstrains: React.PropTypes.string,
licenseTerm: React.PropTypes.object,
- featureGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string)
+ featureGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string),
+ version: React.PropTypes.object
});
+
+const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName, validateLTChoice}) => {
+ let {name, description, requirementsAndConstrains, licenseTerm} = data;
+ return (
+ <GridSection>
+ <GridItem colSpan={2}>
+ <Input
+ isValid={genericFieldInfo.name.isValid}
+ errorText={genericFieldInfo.name.errorText}
+ onChange={name => onDataChanged({name}, LA_EDITOR_FORM, { name: validateName })}
+ label={i18n('Name')}
+ value={name}
+ data-test-id='create-la-name'
+ name='license-agreement-name'
+ isRequired={true}
+ type='text'/>
+ <Input
+ isValid={genericFieldInfo.requirementsAndConstrains.isValid}
+ errorText={genericFieldInfo.requirementsAndConstrains.errorText}
+ onChange={requirementsAndConstrains => onDataChanged({requirementsAndConstrains}, LA_EDITOR_FORM)}
+ label={i18n('Requirements and Constraints')}
+ value={requirementsAndConstrains}
+ data-test-id='create-la-requirements-constants'
+ name='license-agreement-requirements-and-constraints'
+ type='textarea'/>
+ <Input
+ label={i18n('License Term')}
+ type='select'
+ value={licenseTerm && licenseTerm.choice}
+ isRequired={true}
+ onChange={e => {
+ const selectedIndex = e.target.selectedIndex;
+ const licenseTerm = e.target.options[selectedIndex].value;
+ onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}}, LA_EDITOR_FORM, { licenseTerm: validateLTChoice });
+ }}
+ isValid={genericFieldInfo.licenseTerm.isValid}
+ errorText={genericFieldInfo.licenseTerm.errorText}
+ className='input-options-select'
+ groupClassName='bootstrap-input-options'
+ data-test-id='create-la-license-term' >
+ {LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+ </GridItem>
+ <GridItem colSpan={2} stretch>
+ <Input
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ onChange={description => onDataChanged({description}, LA_EDITOR_FORM)}
+ label={i18n('Description')}
+ value={description}
+ overlayPos='bottom'
+ data-test-id='create-la-description'
+ name='license-agreement-description'
+ isRequired={true}
+ type='textarea'/>
+ </GridItem>
+ </GridSection>
+ );
+};
+
class LicenseAgreementEditorView extends React.Component {
static propTypes = {
data: LicenseAgreementPropType,
previousData: LicenseAgreementPropType,
+ LANames: React.PropTypes.object,
isReadOnlyMode: React.PropTypes.bool,
onDataChanged: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired,
@@ -42,7 +124,6 @@ class LicenseAgreementEditorView extends React.Component {
static defaultProps = {
selectedTab: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL,
- selectedFeatureGroupsButtonTab: LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS,
data: {}
};
@@ -51,21 +132,44 @@ class LicenseAgreementEditorView extends React.Component {
};
render() {
- let {selectedTab, onTabSelect, isReadOnlyMode} = this.props;
+ let {selectedTab, onTabSelect, isReadOnlyMode, featureGroupsList, data, onDataChanged, genericFieldInfo} = this.props;
return (
- <ValidationForm
- ref='validationForm'
- hasButtons={true}
- onSubmit={ () => this.submit() }
- onReset={ () => this.props.onCancel() }
- labledButtons={true}
- isReadOnlyMode={isReadOnlyMode}
- className='license-agreement-form'>
- <ValidationTabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect}>
- {this.renderGeneralTab()}
- {this.renderFeatureGroupsTab()}
- </ValidationTabs>
- </ValidationForm>
+ <div>
+ {genericFieldInfo && <Form
+ ref='validationForm'
+ hasButtons={true}
+ onSubmit={ () => this.submit() }
+ onReset={ () => this.props.onCancel() }
+ labledButtons={true}
+ isReadOnlyMode={isReadOnlyMode}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm(LA_EDITOR_FORM) }
+ className='license-agreement-form'>
+ <Tabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect} invalidTabs={this.props.invalidTabs} >
+ <Tab
+ eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL}
+ data-test-id='general-tab'
+ title={i18n('General')}>
+ <GeneralTabContent data={data} genericFieldInfo={genericFieldInfo} onDataChanged={onDataChanged} validateLTChoice={(value)=>this.validateLTChoice(value)}
+ validateName={(value)=>this.validateName(value)}/>
+ </Tab>
+ <Tab
+ eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
+ data-test-id='feature-group-tab'
+ title={i18n('Feature Groups')}>
+ {featureGroupsList.length > 0 ?
+ <DualListboxView
+ isReadOnlyMode={isReadOnlyMode}
+ filterTitle={dualBoxFilterTitle}
+ selectedValuesList={data.featureGroupsIds}
+ availableList={featureGroupsList}
+ onChange={ selectedValuesList => onDataChanged( { featureGroupsIds: selectedValuesList }, LA_EDITOR_FORM )}/> :
+ <p>{i18n('There is no available feature groups')}</p>}
+ </Tab>
+ </Tabs>
+ </Form>}
+ </div>
);
}
@@ -74,173 +178,19 @@ class LicenseAgreementEditorView extends React.Component {
this.props.onSubmit({licenseAgreement, previousLicenseAgreement});
}
- renderGeneralTab() {
- let {data = {}, onDataChanged} = this.props;
- let {name, description, requirementsAndConstrains, licenseTerm} = data;
- return (
- <ValidationTab
- eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL}
- title={i18n('General')}>
- <div className='license-agreement-form-row'>
- <div className='license-agreement-form-col'>
- <ValidationInput
- onChange={name => onDataChanged({name})}
- label={i18n('Name')}
- value={name}
- name='license-agreement-name'
- validations={{maxLength: 25, required: true}}
- type='text'/>
- <ValidationInput
- onChange={requirementsAndConstrains => onDataChanged({requirementsAndConstrains})}
- label={i18n('Requirements and Constraints')}
- value={requirementsAndConstrains}
- name='license-agreement-requirements-and-constraints'
- validations={{maxLength: 1000}}
- type='textarea'/>
- </div>
- <ValidationInput
- onChange={description => onDataChanged({description})}
- label={i18n('Description')}
- value={description}
- name='license-agreement-description'
- validations={{maxLength: 1000, required: true}}
- type='textarea'/>
- </div>
- <div className='license-agreement-form-row'>
- <ValidationInput
- onEnumChange={licenseTerm => onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}})}
- selectedEnum={licenseTerm && licenseTerm.choice}
- validations={{required: true}}
- type='select'
- label={i18n('License Term')}
- values={LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE}/>
- </div>
- </ValidationTab>
- );
- }
-
- renderFeatureGroupsTab() {
- let {onFeatureGroupsButtonTabSelect, selectedFeatureGroupsButtonTab, featureGroupsList} = this.props;
- if (featureGroupsList.length > 0) {
- return (
- <ValidationTab
- eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
- title={i18n('Feature Groups')}>
- <ButtonGroup>
- {
- this.renderFeatureGroupsButtonTab(
- LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS,
- selectedFeatureGroupsButtonTab,
- i18n('Associated Feature Groups'),
- onFeatureGroupsButtonTabSelect
- )
- }
- {
- this.renderFeatureGroupsButtonTab(
- LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS,
- selectedFeatureGroupsButtonTab,
- i18n('Available Feature Groups'),
- onFeatureGroupsButtonTabSelect
- )
- }
- </ButtonGroup>
- {this.renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab)}
- </ValidationTab>
- );
- } else {
- return (
- <ValidationTab
- eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
- title={i18n('Feature Groups')}>
- <p>{i18n('There is no available feature groups')}</p>
- </ValidationTab>
- );
+ validateLTChoice(value) {
+ if (!value.choice) {
+ return {isValid: false, errorText: i18n('Field is required')};
}
+ return {isValid: true, errorText: ''};
}
- renderFeatureGroupsButtonTabContent(selectedFeatureGroupsButtonTab) {
- const {featureGroupsList = [], data: {featureGroupsIds = []}} = this.props;
- const {localFeatureGroupsListFilter} = this.state;
- let selectedFeatureGroups = featureGroupsIds.map(featureGroupId => featureGroupsList.find(featureGroup => featureGroup.id === featureGroupId));
-
- const dualBoxFilterTitle = {
- left: i18n('Available Feature Groups'),
- right: i18n('Selected Feature Groups')
- };
-
- switch (selectedFeatureGroupsButtonTab) {
- case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.ASSOCIATED_FEATURE_GROUPS:
- if (!selectedFeatureGroups.length) {
- return (
- <div className='no-items-msg'>
- {i18n('There are currently no feature groups associated with this license agreement. Click "Available Feature Groups" to associate.')}
- </div>
- );
- }
- if (featureGroupsList.length) {
- return (
- <ListEditorView
- className='thinner-list'
- filterValue={localFeatureGroupsListFilter}
- onFilter={localFeatureGroupsListFilter => this.setState({localFeatureGroupsListFilter})}>
- {this.filterAssociatedFeatureGroupsList(selectedFeatureGroups).map(featureGroup => this.renderAssociatedFeatureGroupListItem(featureGroup))}
- </ListEditorView>
- );
- }
- return;
- case LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS:
- return (
- <DualListboxView
- filterTitle={dualBoxFilterTitle}
- selectedValuesList={this.props.data.featureGroupsIds}
- availableList={this.props.featureGroupsList}
- onChange={ selectedValuesList => this.props.onDataChanged( { featureGroupsIds: selectedValuesList } )}/>
- );
- }
- }
+ validateName(value) {
+ const {data: {id}, LANames} = this.props;
+ const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LANames});
- renderFeatureGroupsButtonTab(buttonTab, selectedButtonTab, title, onClick) {
- const isSelected = buttonTab === selectedButtonTab;
- return (
- <Button
- className='button-tab'
- active={isSelected}
- onClick={() => !isSelected && onClick(buttonTab)}>
- { title }
- </Button>
- );
- }
-
- renderAssociatedFeatureGroupListItem({id, name, entitlementPoolsIds = [], licenseKeyGroupsIds = []}) {
- const {onDataChanged, data: {featureGroupsIds}, isReadOnlyMode} = this.props;
- return (
- <ListEditorViewItem
- key={id}
- onDelete={() => onDataChanged({featureGroupsIds: featureGroupsIds.filter(featureGroupId => featureGroupId !== id)})}
- isReadOnlyMode={isReadOnlyMode}>
- <div className='name'>{name}</div>
- <div className='inner-objects-count'>{
- i18n(
- 'Entitlement Pools({entitlementPoolsCounter}), License Key Groups({licenseKeyGroupsCount})',
- {
- entitlementPoolsCounter: entitlementPoolsIds.length,
- licenseKeyGroupsCount: licenseKeyGroupsIds.length
- }
- )
- }</div>
- </ListEditorViewItem>
- );
- }
-
- filterAssociatedFeatureGroupsList(featureGroupsList) {
- let {localFeatureGroupsListFilter} = this.state;
- if (localFeatureGroupsListFilter) {
- const filter = new RegExp(escape(localFeatureGroupsListFilter), 'i');
- return featureGroupsList.filter(({name}) => name.match(filter));
- }
- else {
- return featureGroupsList;
- }
+ return !isExists ? {isValid: true, errorText: ''} :
+ {isValid: false, errorText: i18n('License Agreement by the name \'' + value + '\' already exists. License agreement name must be unique')};
}
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js
index ca18bfab79..373694f2bf 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js
@@ -1,39 +1,35 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
-import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js';
import LicenseAgreementListEditorView from './LicenseAgreementListEditorView.jsx';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
-import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
+import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js';
const mapStateToProps = ({licenseModel: {licenseAgreement, licenseModelEditor}}) => {
let {licenseAgreementList} = licenseAgreement;
let {data} = licenseAgreement.licenseAgreementEditor;
- let {vendorName} = licenseModelEditor.data;
+ let {vendorName, version} = licenseModelEditor.data;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data);
return {
vendorName,
+ version,
licenseAgreementList,
isReadOnlyMode,
isDisplayModal: Boolean(data),
@@ -43,16 +39,16 @@ const mapStateToProps = ({licenseModel: {licenseAgreement, licenseModelEditor}})
const mapActionsToProps = (dispatch, {licenseModelId}) => {
return {
- onAddLicenseAgreementClick: () => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId}),
- onEditLicenseAgreementClick: licenseAgreement => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement}),
- onDeleteLicenseAgreement: licenseAgreement => LicenseAgreementActionHelper.openDeleteLicenseAgreementConfirm(dispatch, {licenseAgreement}),
- onCallVCAction: action => {
- LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action}).then(() => {
- LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId});
- });
- },
- switchLicenseModelVersion: version => LicenseAgreementActionHelper.switchVersion(dispatch, {licenseModelId, version}),
- onClose: () => OnboardingActionHelper.navigateToOnboardingCatalog(dispatch)
+ onAddLicenseAgreementClick: (version) => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, version}),
+ onEditLicenseAgreementClick: (licenseAgreement, version) => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement, version}),
+ onDeleteLicenseAgreement: (licenseAgreement, version) => dispatch({
+ type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n('Are you sure you want to delete "{name}"?', {name: licenseAgreement.name}),
+ title: i18n('Warning'),
+ onConfirmed: ()=>LicenseAgreementActionHelper.deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId: licenseAgreement.id, version})
+ }
+ })
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
index 4d7e704ba3..776b04b8eb 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
@@ -1,15 +1,26 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-
import i18n from 'nfvo-utils/i18n/i18n.js';
import Modal from 'nfvo-components/modal/Modal.jsx';
import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import LicenseAgreementEditor from './LicenseAgreementEditor.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
-import {optionsInputValues} from './LicenseAgreementConstants';
-import LicenseAgreementConfirmationModal from './LicenseAgreementConfirmationModal.jsx';
-
+import {extractValue} from './LicenseAgreementConstants';
class LicenseAgreementListEditorView extends React.Component {
static propTypes = {
@@ -22,7 +33,6 @@ class LicenseAgreementListEditorView extends React.Component {
onAddLicenseAgreementClick: React.PropTypes.func,
onEditLicenseAgreementClick: React.PropTypes.func,
onDeleteLicenseAgreement: React.PropTypes.func,
- onCallVCAction: React.PropTypes.func
};
static defaultProps = {
@@ -34,35 +44,33 @@ class LicenseAgreementListEditorView extends React.Component {
};
render() {
- const {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
+ const {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = this.props;
const {onAddLicenseAgreementClick} = this.props;
const {localFilter} = this.state;
return (
<div className='license-agreement-list-editor'>
- <ListEditorView
- title={i18n('License Agreements for {vendorName} License Model', {vendorName})}
- plusButtonTitle={i18n('Add License Agreement')}
- onAdd={onAddLicenseAgreementClick}
- filterValue={localFilter}
- onFilter={filter => this.setState({localFilter: filter})}
- isReadOnlyMode={isReadOnlyMode}>
- {this.filterList().map(licenseAgreement => this.renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode))}
- </ListEditorView>
- <Modal show={isDisplayModal} bsSize='large' animation={true} className='license-agreement-modal'>
+ <ListEditorView
+ title={i18n('License Agreements', {vendorName})}
+ plusButtonTitle={i18n('Add License Agreement')}
+ onAdd={() => onAddLicenseAgreementClick(version)}
+ filterValue={localFilter}
+ onFilter={value => this.setState({localFilter: value})}
+ isReadOnlyMode={isReadOnlyMode}>
+ {this.filterList().map(licenseAgreement => this.renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode, version))}
+ </ListEditorView>
+ <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-agreement-modal'>
<Modal.Header>
<Modal.Title>{`${isModalInEditMode ? i18n('Edit License Agreement') : i18n('Create New License Agreement')}`}</Modal.Title>
</Modal.Header>
<Modal.Body>
{
isDisplayModal && (
- <LicenseAgreementEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode} />
+ <LicenseAgreementEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode} />
)
}
</Modal.Body>
</Modal>
- <LicenseAgreementConfirmationModal licenseModelId={licenseModelId}/>
-
</div>
);
}
@@ -73,7 +81,7 @@ class LicenseAgreementListEditorView extends React.Component {
if (localFilter.trim()) {
const filter = new RegExp(escape(localFilter), 'i');
return licenseAgreementList.filter(({name = '', description = '', licenseTerm = ''}) => {
- return escape(name).match(filter) || escape(description).match(filter) || escape(this.extractValue(licenseTerm)).match(filter);
+ return escape(name).match(filter) || escape(description).match(filter) || escape(extractValue(licenseTerm)).match(filter);
});
}
else {
@@ -81,14 +89,14 @@ class LicenseAgreementListEditorView extends React.Component {
}
}
- renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode) {
+ renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode, version) {
let {id, name, description, licenseTerm, featureGroupsIds = []} = licenseAgreement;
let {onEditLicenseAgreementClick, onDeleteLicenseAgreement} = this.props;
return (
<ListEditorItemView
key={id}
- onSelect={() => onEditLicenseAgreementClick(licenseAgreement)}
- onDelete={() => onDeleteLicenseAgreement(licenseAgreement)}
+ onSelect={() => onEditLicenseAgreementClick(licenseAgreement, version)}
+ onDelete={() => onDeleteLicenseAgreement(licenseAgreement, version)}
className='list-editor-item-view'
isReadOnlyMode={isReadOnlyMode}>
<div className='list-editor-item-view-field'>
@@ -98,7 +106,7 @@ class LicenseAgreementListEditorView extends React.Component {
<div className='list-editor-item-view-field'>
<div className='list-editor-item-view-field-tight'>
<div className='title'>{i18n('Type')}</div>
- <div className='text type'>{this.extractValue(licenseTerm)}</div>
+ <div className='text type'>{extractValue(licenseTerm)}</div>
</div>
<div className='list-editor-item-view-field-tight'>
<div className='title'>{i18n('Feature')}</div>
@@ -113,14 +121,6 @@ class LicenseAgreementListEditorView extends React.Component {
</ListEditorItemView>
);
}
-
- extractValue(item) {
- if (item === undefined) {
- return '';
- } //TODO fix it later
-
- return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
- }
}
export default LicenseAgreementListEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js
index 5b5fa00df1..e6a8f34b58 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes as licenseAgreementActionTypes} from './LicenseAgreementConstants';
export default (state = [], action) => {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
index 50ac2c85a3..dd2a5c6003 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
@@ -1,44 +1,39 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes as licenseKeyGroupsConstants} from './LicenseKeyGroupsConstants.js';
import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
-function baseUrl(licenseModelId) {
+function baseUrl(licenseModelId, version) {
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/license-key-groups`;
+ const {id: versionId} = version;
+ return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-key-groups`;
}
function fetchLicenseKeyGroupsList(licenseModelId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`);
+ return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
}
-function deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId) {
- return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${licenseKeyGroupId}`);
+function deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId, version) {
+ return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}`);
}
-function postLicenseKeyGroup(licenseModelId, licenseKeyGroup) {
- return RestAPIUtil.create(baseUrl(licenseModelId), {
+function postLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) {
+ return RestAPIUtil.post(baseUrl(licenseModelId, version), {
name: licenseKeyGroup.name,
description: licenseKeyGroup.description,
operationalScope: licenseKeyGroup.operationalScope,
@@ -46,8 +41,8 @@ function postLicenseKeyGroup(licenseModelId, licenseKeyGroup) {
});
}
-function putLicenseKeyGroup(licenseModelId, licenseKeyGroup) {
- return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${licenseKeyGroup.id}`, {
+function putLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) {
+ return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseKeyGroup.id}`, {
name: licenseKeyGroup.name,
description: licenseKeyGroup.description,
operationalScope: licenseKeyGroup.operationalScope,
@@ -77,9 +72,9 @@ export default {
});
},
- saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup}) {
+ saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version}) {
if (previousLicenseKeyGroup) {
- return putLicenseKeyGroup(licenseModelId, licenseKeyGroup).then(() => {
+ return putLicenseKeyGroup(licenseModelId, licenseKeyGroup, version).then(() => {
dispatch({
type: licenseKeyGroupsConstants.EDIT_LICENSE_KEY_GROUP,
licenseKeyGroup
@@ -87,11 +82,12 @@ export default {
});
}
else {
- return postLicenseKeyGroup(licenseModelId, licenseKeyGroup).then(response => {
+ return postLicenseKeyGroup(licenseModelId, licenseKeyGroup, version).then(response => {
dispatch({
type: licenseKeyGroupsConstants.ADD_LICENSE_KEY_GROUP,
licenseKeyGroup: {
...licenseKeyGroup,
+ referencingFeatureGroups: [],
id: response.value
}
});
@@ -101,8 +97,8 @@ export default {
},
- deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId}){
- return deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId).then(()=> {
+ deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId, version}){
+ return deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId, version).then(()=> {
dispatch({
type: licenseKeyGroupsConstants.DELETE_LICENSE_KEY_GROUP,
licenseKeyGroupId
@@ -110,13 +106,6 @@ export default {
});
},
- licenseKeyGroupEditorDataChanged(dispatch, {deltaData}) {
- dispatch({
- type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.DATA_CHANGED,
- deltaData
- });
- },
-
hideDeleteConfirm(dispatch) {
dispatch({
type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM,
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx
deleted file mode 100644
index 2413db51d0..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import React from 'react';
-import {connect} from 'react-redux';
-import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
-import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-function renderMsg(licenseKeyGroupToDelete) {
- let name = licenseKeyGroupToDelete ? licenseKeyGroupToDelete.name : '';
- let msg = i18n('Are you sure you want to delete "{name}"?', {name});
- let subMsg = licenseKeyGroupToDelete
- && licenseKeyGroupToDelete.referencingFeatureGroups
- && licenseKeyGroupToDelete.referencingFeatureGroups.length > 0 ?
- i18n('This license key group is associated with one or more feature groups') :
- '';
- return(
- <div>
- <p>{msg}</p>
- <p>{subMsg}</p>
- </div>
- );
-};
-
-const mapStateToProps = ({licenseModel: {licenseKeyGroup}}, {licenseModelId}) => {
- let {licenseKeyGroupToDelete} = licenseKeyGroup;
- const show = licenseKeyGroupToDelete !== false;
- return {
- show,
- title: 'Warning!',
- type: 'warning',
- msg: renderMsg(licenseKeyGroupToDelete),
- confirmationDetails: {licenseKeyGroupToDelete, licenseModelId}
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
- onConfirmed: ({licenseKeyGroupToDelete, licenseModelId}) => {
-
- LicenseKeyGroupsActionHelper.deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId:licenseKeyGroupToDelete.id});
- LicenseKeyGroupsActionHelper.hideDeleteConfirm(dispatch);
- },
- onDeclined: () => {
- LicenseKeyGroupsActionHelper.hideDeleteConfirm(dispatch);
- }
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
index d32bc52744..50d1fe8625 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
@@ -1,25 +1,21 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
export const actionTypes = keyMirror({
@@ -42,6 +38,8 @@ export const defaultState = {
}
};
+export const LKG_FORM_NAME = 'LKGFORM';
+
export const optionsInputValues = {
OPERATIONAL_SCOPE: [
{enum: '', title: i18n('please select…')},
@@ -61,4 +59,21 @@ export const optionsInputValues = {
]
};
+export const extractValue = (item) => {
+ if (item === undefined) {return '';} //TODO fix it later
+
+ return item ? item === optionInputOther.OTHER ? item : InputOptions.getTitleByName(optionsInputValues, item) : '';
+};
+export const getOperationalScopes = (operationalScope) => {
+ if(operationalScope.choices.toString() === i18n(optionInputOther.OTHER) && operationalScope.other !== '') {
+ return operationalScope.other;
+ }
+ else {
+ let allOpScopes = '';
+ for (let opScope of operationalScope.choices) {
+ allOpScopes += allOpScopes === '' ? InputOptions.getTitleByName(optionsInputValues, opScope) : `, ${InputOptions.getTitleByName(optionsInputValues, opScope)}`;
+ }
+ return allOpScopes;
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
index 3940ec594a..aef1532dc1 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
@@ -1,52 +1,60 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
import LicenseKeyGroupsEditorView from './LicenseKeyGroupsEditorView.jsx';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
const mapStateToProps = ({licenseModel: {licenseKeyGroup}}) => {
- let {data} = licenseKeyGroup.licenseKeyGroupsEditor;
+ let {data, genericFieldInfo, formReady} = licenseKeyGroup.licenseKeyGroupsEditor;
- let previousData;
+ let previousData, LKGNames = {};
const licenseKeyGroupId = data ? data.id : null;
if(licenseKeyGroupId) {
previousData = licenseKeyGroup.licenseKeyGroupsList.find(licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId);
}
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
+ const list = licenseKeyGroup.licenseKeyGroupsList;
+ for (let i = 0; i < list.length; i++) {
+ LKGNames[list[i].name] = list[i].id;
+ }
+
return {
data,
- previousData
+ previousData,
+ genericFieldInfo,
+ isFormValid,
+ formReady,
+ LKGNames
};
};
-const mapActionsToProps = (dispatch, {licenseModelId}) => {
+const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
- onDataChanged: deltaData => LicenseKeyGroupsActionHelper.licenseKeyGroupEditorDataChanged(dispatch, {deltaData}),
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onCancel: () => LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch),
onSubmit: ({previousLicenseKeyGroup, licenseKeyGroup}) => {
LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch);
- LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup});
- }
+ LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version});
+ },
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
index a74498269a..090c971c65 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
@@ -1,42 +1,53 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes, defaultState} from './LicenseKeyGroupsConstants.js';
+import {actionTypes, defaultState, LKG_FORM_NAME} from './LicenseKeyGroupsConstants.js';
export default (state = {}, action) => {
switch (action.type) {
case actionTypes.licenseKeyGroupsEditor.OPEN:
return {
...state,
- data: action.licenseKeyGroup ? {...action.licenseKeyGroup} : defaultState.licenseKeyGroupsEditor
+ data: action.licenseKeyGroup ? {...action.licenseKeyGroup} : defaultState.licenseKeyGroupsEditor,
+ formReady: null,
+ formName: LKG_FORM_NAME,
+ genericFieldInfo: {
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}]
+ },
+ 'name' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
+ },
+ 'type' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ 'operationalScope' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ }
+ }
};
case actionTypes.licenseKeyGroupsEditor.CLOSE:
return {};
- case actionTypes.licenseKeyGroupsEditor.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
- }
- };
default:
return state;
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
index 102e713060..b95efd0f9c 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
@@ -1,10 +1,29 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
+import Validator from 'nfvo-utils/Validator.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
-import {optionsInputValues as licenseKeyGroupOptionsInputValues} from './LicenseKeyGroupsConstants.js';
-import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+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 {optionsInputValues as licenseKeyGroupOptionsInputValues, LKG_FORM_NAME} from './LicenseKeyGroupsConstants.js';
+import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
const LicenseKeyGroupPropType = React.PropTypes.shape({
id: React.PropTypes.string,
@@ -17,10 +36,80 @@ const LicenseKeyGroupPropType = React.PropTypes.shape({
type: React.PropTypes.string
});
+const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateOperationalScope}) => {
+ let {name, description, operationalScope, type} = data;
+ return (
+ <GridSection>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={name => onDataChanged({name}, LKG_FORM_NAME, {name: validateName})}
+ label={i18n('Name')}
+ data-test-id='create-lkg-name'
+ value={name}
+ isValid={genericFieldInfo.name.isValid}
+ errorText={genericFieldInfo.name.errorText}
+ isRequired={true}
+ type='text'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <InputOptions
+ onInputChange={()=>{}}
+ isMultiSelect={true}
+ isRequired={true}
+ onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
+ LKG_FORM_NAME, {operationalScope: validateOperationalScope})}
+ onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
+ other: operationalScope}}, LKG_FORM_NAME, {operationalScope: validateOperationalScope})}
+ label={i18n('Operational Scope')}
+ data-test-id='create-lkg-operational-scope'
+ type='select'
+ multiSelectedEnum={operationalScope && operationalScope.choices}
+ otherValue={operationalScope && operationalScope.other}
+ values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}
+ isValid={genericFieldInfo.operationalScope.isValid}
+ errorText={genericFieldInfo.operationalScope.errorText} />
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={description => onDataChanged({description}, LKG_FORM_NAME)}
+ label={i18n('Description')}
+ data-test-id='create-lkg-description'
+ value={description}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ isRequired={true}
+ type='textarea'
+ overlayPos='bottom' />
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ isRequired={true}
+ onChange={e => { const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onDataChanged({type: val}, LKG_FORM_NAME);}}
+ value={type}
+ label={i18n('Type')}
+ data-test-id='create-lkg-type'
+ isValid={genericFieldInfo.type.isValid}
+ errorText={genericFieldInfo.type.errorText}
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ type='select' >
+ {
+ licenseKeyGroupOptionsInputValues.TYPE.map(type =>
+ (<option key={type.enum} value={type.enum}>{type.title}</option>))
+ }
+ </Input>
+ </GridItem>
+ </GridSection>
+ );
+};
+
class LicenseKeyGroupsEditorView extends React.Component {
static propTypes = {
data: LicenseKeyGroupPropType,
previousData: LicenseKeyGroupPropType,
+ LKGNames: React.PropTypes.object,
isReadOnlyMode: React.PropTypes.bool,
onDataChanged: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired,
@@ -32,54 +121,29 @@ class LicenseKeyGroupsEditorView extends React.Component {
};
render() {
- let {data = {}, onDataChanged, isReadOnlyMode} = this.props;
- let {name, description, operationalScope, type} = data;
+ let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo} = this.props;
return (
- <ValidationForm
+ <div>
+ { genericFieldInfo &&
+ <Form
ref='validationForm'
hasButtons={true}
onSubmit={ () => this.submit() }
onReset={ () => this.props.onCancel() }
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm(LKG_FORM_NAME) }
labledButtons={true}
isReadOnlyMode={isReadOnlyMode}
className='license-key-groups-form'>
- <div className='license-key-groups-form-row'>
- <ValidationInput
- onChange={name => onDataChanged({name})}
- ref='name'
- label={i18n('Name')}
- value={name}
- validations={{maxLength: 120, required: true}}
- type='text'/>
- <ValidationInput
- isMultiSelect={true}
- isRequired={true}
- onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}})}
- onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], other: operationalScope}})}
- label={i18n('Operational Scope')}
- validations={{required: true}}
- multiSelectedEnum={operationalScope && operationalScope.choices}
- otherValue={operationalScope && operationalScope.other}
- values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}/>
- </div>
- <div className='license-key-groups-form-row'>
- <ValidationInput
- onChange={description => onDataChanged({description})}
- ref='description'
- label={i18n('Description')}
- value={description}
- validations={{maxLength: 1000, required: true}}
- type='textarea'/>
- <ValidationInput
- isRequired={true}
- onEnumChange={type => onDataChanged({type})}
- selectedEnum={type}
- label={i18n('Type')}
- type='select'
- validations={{required: true}}
- values={licenseKeyGroupOptionsInputValues.TYPE}/>
- </div>
- </ValidationForm>
+ <LicenseKeyGroupFormContent
+ data={data}
+ onDataChanged={onDataChanged}
+ genericFieldInfo={genericFieldInfo}
+ validateName={(value)=> this.validateName(value)}
+ validateOperationalScope={this.validateOperationalScope}/>
+ </Form>}
+ </div>
);
}
@@ -87,6 +151,37 @@ class LicenseKeyGroupsEditorView extends React.Component {
const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup} = this.props;
this.props.onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
}
+
+ validateName(value) {
+ const {data: {id}, LKGNames} = this.props;
+ const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LKGNames});
+
+ return !isExists ? {isValid: true, errorText: ''} :
+ {isValid: false, errorText: i18n('License key group by the name \'' + value + '\' already exists. License key group name must be unique')};
+ }
+
+ validateOperationalScope(value) {
+ if (value && value.choices && value.choices.length > 0) {
+ if (value.choices[0] !== optionInputOther.OTHER)
+ {
+ return {
+ isValid: true,
+ errorText: ''
+ };
+ } else {
+ if ( value.other ) {
+ return {
+ isValid: true,
+ errorText: ''
+ };
+ }
+ }
+ }
+ return {
+ isValid: false,
+ errorText: 'Field is required'
+ };
+ }
}
export default LicenseKeyGroupsEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
index e1b610f973..e2c6c30e21 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
@@ -1,27 +1,24 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+import i18n from 'nfvo-utils/i18n/i18n.js';
import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
-import LicenseKeyGroupsListEditorView from './LicenseKeyGroupsListEditorView.jsx';
+import LicenseKeyGroupsListEditorView, {generateConfirmationMsg} from './LicenseKeyGroupsListEditorView.jsx';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js';
const mapStateToProps = ({licenseModel: {licenseKeyGroup, licenseModelEditor}}) => {
let {licenseKeyGroupsList} = licenseKeyGroup;
@@ -38,11 +35,18 @@ const mapStateToProps = ({licenseModel: {licenseKeyGroup, licenseModelEditor}})
};
};
-const mapActionsToProps = (dispatch) => {
+const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
onAddLicenseKeyGroupClick: () => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch),
onEditLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup}),
- onDeleteLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openDeleteLicenseAgreementConfirm(dispatch, {licenseKeyGroup})
+ onDeleteLicenseKeyGroupClick: licenseKeyGroup => dispatch({
+ type: globalMoadlActions.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: generateConfirmationMsg(licenseKeyGroup),
+ title: i18n('Warning'),
+ onConfirmed: ()=>LicenseKeyGroupsActionHelper.deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId:licenseKeyGroup.id, version})
+ }
+ })
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
index 1ed1d2093a..a303e46706 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -8,8 +23,6 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js
import LicenseKeyGroupsEditor from './LicenseKeyGroupsEditor.js';
import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
import {optionsInputValues} from './LicenseKeyGroupsConstants';
-import LicenseKeyGroupsConfirmationModal from './LicenseKeyGroupsConfirmationModal.jsx';
-
class LicenseKeyGroupsListEditorView extends React.Component {
static propTypes = {
@@ -33,35 +46,33 @@ class LicenseKeyGroupsListEditorView extends React.Component {
};
render() {
- let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
+ let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = this.props;
let {onAddLicenseKeyGroupClick} = this.props;
const {localFilter} = this.state;
return (
<div className='license-key-groups-list-editor'>
<ListEditorView
- title={i18n('License Key Groups for {vendorName} License Model', {vendorName})}
+ title={i18n('License Key Groups', {vendorName})}
plusButtonTitle={i18n('Add License Key Group')}
onAdd={onAddLicenseKeyGroupClick}
filterValue={localFilter}
- onFilter={filter => this.setState({localFilter: filter})}
+ onFilter={value => this.setState({localFilter: value})}
isReadOnlyMode={isReadOnlyMode}>
{this.filterList().map(licenseKeyGroup => (this.renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode)))}
</ListEditorView>
- <Modal show={isDisplayModal} bsSize='large' animation={true} className='license-key-groups-modal'>
+ <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-key-groups-modal'>
<Modal.Header>
<Modal.Title>{`${isModalInEditMode ? i18n('Edit License Key Group') : i18n('Create New License Key Group')}`}</Modal.Title>
</Modal.Header>
<Modal.Body>
{
isDisplayModal && (
- <LicenseKeyGroupsEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
+ <LicenseKeyGroupsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/>
)
}
</Modal.Body>
</Modal>
- <LicenseKeyGroupsConfirmationModal licenseModelId={licenseModelId}/>
-
</div>
);
}
@@ -134,5 +145,17 @@ class LicenseKeyGroupsListEditorView extends React.Component {
export default LicenseKeyGroupsListEditorView;
-
-
+export function generateConfirmationMsg(licenseKeyGroupToDelete) {
+ let name = licenseKeyGroupToDelete ? licenseKeyGroupToDelete.name : '';
+ let msg = i18n('Are you sure you want to delete "{name}"?', {name});
+ let subMsg = licenseKeyGroupToDelete.referencingFeatureGroups
+ && licenseKeyGroupToDelete.referencingFeatureGroups.length > 0 ?
+ i18n('This license key group is associated with one or more feature groups') :
+ '';
+ return (
+ <div>
+ <p>{msg}</p>
+ <p>{subMsg}</p>
+ </div>
+ );
+}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js
index 54ce4e3955..1f0a64e295 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './LicenseKeyGroupsConstants.js';
export default (state = [], action) => {
switch (action.type) {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js
new file mode 100644
index 0000000000..1ca4f37988
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js
@@ -0,0 +1,163 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {connect} from 'react-redux';
+import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import LicenseModelOverviewView from './LicenseModelOverviewView.jsx';
+import {overviewEditorHeaders, selectedButton} from './LicenseModelOverviewConstants.js';
+import licenseModelOverviewActionHelper from './licenseModelOverviewActionHelper.js';
+
+export const mapStateToProps = ({licenseModel: {licenseModelEditor, entitlementPool, licenseAgreement, featureGroup, licenseKeyGroup, licenseModelOverview}}) => {
+
+ let modalHeader, licensingDataList;
+ let isDisplayModal = false;
+
+ const reduceLicenseKeyGroups = (accum, licenseKeyGroupId) => {
+ let curLicenseKeyGroup = licenseKeyGroup.licenseKeyGroupsList.find(item => {return item.id === licenseKeyGroupId;});
+ if (curLicenseKeyGroup) {
+ accum.push({
+ ...curLicenseKeyGroup,
+ itemType: overviewEditorHeaders.LICENSE_KEY_GROUP
+ });
+ }
+ return accum;
+ };
+
+ const reduceEntitlementPools = (accum, entitlementPoolId) => {
+ let curEntitlementPool = entitlementPool.entitlementPoolsList.find(item => {return item.id === entitlementPoolId;});
+ if (curEntitlementPool) {
+ accum.push ({
+ ...curEntitlementPool,
+ itemType: overviewEditorHeaders.ENTITLEMENT_POOL
+ });
+ }
+ return accum;
+ };
+
+ const reduceFeatureGroups = (accum, featureGroupId) => {
+ let curFeatureGroup = featureGroup.featureGroupsList.find(item => {return item.id === featureGroupId;});
+ if (curFeatureGroup) {
+ let {entitlementPoolsIds = [], licenseKeyGroupsIds = []} = curFeatureGroup;
+ accum.push({
+ ...curFeatureGroup,
+ itemType: overviewEditorHeaders.FEATURE_GROUP,
+ children: [
+ ...entitlementPoolsIds.length ? entitlementPoolsIds.reduce(reduceEntitlementPools, []) : [],
+ ...licenseKeyGroupsIds.length ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, []) : []
+ ]
+ });
+ }
+ return accum;
+ };
+
+
+ const checkEP = (accum, elem) => {
+ if (!elem.referencingFeatureGroups || !elem.referencingFeatureGroups.length) {
+ accum.push({
+ ...elem,
+ itemType: overviewEditorHeaders.ENTITLEMENT_POOL
+ });
+ }
+ return accum;
+ };
+
+ const checkLG = (accum, elem) => {
+ if (!elem.referencingFeatureGroups || !elem.referencingFeatureGroups.length) {
+ accum.push({
+ ...elem,
+ itemType: overviewEditorHeaders.LICENSE_KEY_GROUP
+ });
+ }
+ return accum;
+ };
+
+ const checkFG = (accum, elem) => {
+ if (!elem.referencingLicenseAgreements || !elem.referencingLicenseAgreements.length) {
+ let {entitlementPoolsIds = [], licenseKeyGroupsIds = []} = elem;
+ accum.push({
+ ...elem,
+ itemType: overviewEditorHeaders.FEATURE_GROUP,
+
+ children: [
+ ...entitlementPoolsIds.length ? entitlementPoolsIds.reduce(reduceEntitlementPools, []) : [],
+ ...licenseKeyGroupsIds.length ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, []) : []
+ ]
+
+ });
+ }
+ return accum;
+ };
+
+
+
+ const mapLicenseAgreementData = licenseAgreement => {
+ let {featureGroupsIds = []} = licenseAgreement;
+ return {
+ ...licenseAgreement,
+ itemType: overviewEditorHeaders.LICENSE_AGREEMENT,
+ children: featureGroupsIds.length ? featureGroupsIds.reduce(reduceFeatureGroups, []) : []
+ };
+ };
+
+ if (entitlementPool.entitlementPoolEditor && entitlementPool.entitlementPoolEditor.data) {
+ modalHeader = overviewEditorHeaders.ENTITLEMENT_POOL;
+ isDisplayModal = true;
+ }else
+ if (licenseAgreement.licenseAgreementEditor && licenseAgreement.licenseAgreementEditor.data) {
+ modalHeader = overviewEditorHeaders.LICENSE_AGREEMENT;
+ isDisplayModal = true;
+ }else
+ if (featureGroup.featureGroupEditor && featureGroup.featureGroupEditor.data) {
+ modalHeader = overviewEditorHeaders.FEATURE_GROUP;
+ isDisplayModal = true;
+ }else
+ if (licenseKeyGroup.licenseKeyGroupsEditor && licenseKeyGroup.licenseKeyGroupsEditor.data) {
+ modalHeader = overviewEditorHeaders.LICENSE_KEY_GROUP;
+ isDisplayModal = true;
+ }
+
+ if (licenseModelOverview.selectedTab === selectedButton.NOT_IN_USE) {
+ licensingDataList = [
+ ...featureGroup.featureGroupsList.reduce(checkFG, []),
+ ...entitlementPool.entitlementPoolsList.reduce(checkEP, []),
+ ...licenseKeyGroup.licenseKeyGroupsList.reduce(checkLG, [])
+ ];
+ }else {
+ licensingDataList = licenseAgreement.licenseAgreementList && licenseAgreement.licenseAgreementList.length ? licenseAgreement.licenseAgreementList.map(mapLicenseAgreementData) : [];
+ }
+
+ return {
+ isReadOnlyMode: VersionControllerUtils.isReadOnly(licenseModelEditor.data),
+ isDisplayModal,
+ modalHeader,
+ licenseModelId: licenseModelEditor.data.id,
+ version: licenseModelEditor.data.version,
+ licensingDataList,
+ selectedTab: licenseModelOverview.selectedTab
+
+ };
+};
+
+const mapActionsToProps = (dispatch, {licenseModelId}) => {
+ return {
+ onCallVCAction: action => {
+ LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action});
+ },
+ onTabSelect: (buttonTab) => licenseModelOverviewActionHelper.selectVLMListView(dispatch,{buttonTab})
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(LicenseModelOverviewView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js
new file mode 100644
index 0000000000..b5a27ed018
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js
@@ -0,0 +1,42 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const overviewItems = keyMirror({
+ LICENSE_AGREEMENTS: 'License Agreements',
+ FEATURE_GROUPS: 'Feature Groups',
+ ENTITLEMENT_POOLS: 'Entitlement Pools',
+ LICENSE_KEY_GROUPS: 'License Key Groups'
+});
+
+export const overviewEditorHeaders = keyMirror({
+ LICENSE_AGREEMENT: 'License Agreement',
+ FEATURE_GROUP: 'Feature Group',
+ ENTITLEMENT_POOL: 'Entitlement Pool',
+ LICENSE_KEY_GROUP: 'License Key Group'
+});
+
+export const actionTypes = keyMirror({
+ LICENSE_MODEL_OVERVIEW_TAB_SELECTED: null,
+ LM_DATA_CHANGED: null
+});
+
+export const selectedButton = keyMirror({
+ VLM_LIST_VIEW: null,
+ NOT_IN_USE: null
+});
+
+export const VLM_DESCRIPTION_FORM = 'VLMDEWSCRIPTIONFORM';
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx
new file mode 100644
index 0000000000..d6c79ddb52
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx
@@ -0,0 +1,105 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Modal from 'nfvo-components/modal/Modal.jsx';
+import classNames from 'classnames';
+
+import EntitlementPoolsEditor from '../entitlementPools/EntitlementPoolsEditor.js';
+import FeatureGroupEditor from '../featureGroups/FeatureGroupEditor.js';
+import LicenseAgreementEditor from '../licenseAgreement/LicenseAgreementEditor.js';
+import LicenseKeyGroupsEditor from '../licenseKeyGroups/LicenseKeyGroupsEditor.js';
+import {overviewEditorHeaders, selectedButton} from './LicenseModelOverviewConstants.js';
+
+import SummaryView from './SummaryView.jsx';
+import VLMListView from './VLMListView.jsx';
+import ListButtons from './summary/ListButtons.jsx';
+
+
+const setModalClassName = (modalHeader) => {
+ switch (modalHeader) {
+ case overviewEditorHeaders.ENTITLEMENT_POOL:
+ return 'entitlement-pools-modal';
+ case overviewEditorHeaders.LICENSE_AGREEMENT:
+ return 'license-agreement-modal';
+ case overviewEditorHeaders.FEATURE_GROUP:
+ return 'feature-group-modal';
+ case overviewEditorHeaders.LICENSE_KEY_GROUP:
+ return 'license-key-groups-modal';
+ default:
+ return '';
+ }
+};
+
+class LicenseModelOverviewView extends React.Component {
+
+ static propTypes = {
+ isDisplayModal: React.PropTypes.bool,
+ isReadOnlyMode: React.PropTypes.bool,
+ licenseModelId: React.PropTypes.string,
+ licensingDataList: React.PropTypes.array,
+ modalHeader: React.PropTypes.string,
+ selectedTab: React.PropTypes.symbol,
+ onTabSelect: React.PropTypes.func,
+ onCallVCAction: React.PropTypes.func,
+ onClose: React.PropTypes.func
+ };
+
+ render() {
+ let {isDisplayModal, modalHeader, licensingDataList, selectedTab, onTabSelect} = this.props;
+ let selectedInUse = selectedTab !== selectedButton.NOT_IN_USE;
+
+ return(
+ <div className='license-model-overview'>
+ <SummaryView/>
+ <div className={classNames('overview-list-section ', !selectedInUse ? 'overview-list-orphans' : '' )}>
+ <div className='vlm-list-tab-panel'>
+ <div className='section-title'>{selectedInUse ? i18n('VLM List View') : i18n('Entities not in Use')}</div>
+ <ListButtons onTabSelect={onTabSelect} selectedInUse={selectedInUse}/>
+ </div>
+ <VLMListView licensingDataList={licensingDataList} showInUse={selectedInUse}/>
+ </div>
+ {
+ isDisplayModal &&
+ <Modal show={isDisplayModal} bsSize='large' animation={true} className={classNames('onborading-modal', setModalClassName(modalHeader))}>
+ <Modal.Header>
+ <Modal.Title>{`${i18n('Create New ')}${i18n(modalHeader)}`}</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ {this.renderModalBody(modalHeader)}
+ </Modal.Body>
+ </Modal>
+ }
+ </div>
+ );
+ }
+
+ renderModalBody(modalHeader) {
+ let {licenseModelId, version} = this.props;
+ switch (modalHeader) {
+ case overviewEditorHeaders.ENTITLEMENT_POOL:
+ return <EntitlementPoolsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>;
+ case overviewEditorHeaders.LICENSE_AGREEMENT:
+ return <LicenseAgreementEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>;
+ case overviewEditorHeaders.FEATURE_GROUP:
+ return <FeatureGroupEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>;
+ case overviewEditorHeaders.LICENSE_KEY_GROUP:
+ return <LicenseKeyGroupsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>;
+ }
+ }
+}
+
+export default LicenseModelOverviewView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx
new file mode 100644
index 0000000000..6fcdb477e6
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx
@@ -0,0 +1,33 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {default as VendorDataView} from './summary/VendorDataView.js';
+import {default as SummaryCountList} from './summary/SummaryCountList.js';
+
+function SummaryView() {
+ return(
+ <div className='overview-top-section'>
+ <div className='overview-title'>{i18n('overview')}</div>
+ <div className='license-model-overview-top'>
+ <VendorDataView/>
+ <SummaryCountList/>
+ </div>
+ </div>
+ );
+}
+
+export default SummaryView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx
new file mode 100644
index 0000000000..119008a849
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx
@@ -0,0 +1,123 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component} from 'react';
+import {Collapse} from 'react-bootstrap';
+import LicenseAgreement from './listItems/LicenseAgreement.jsx';
+import EntitlementPool from './listItems/EntitlementPool.jsx';
+import FeatureGroup from './listItems/FeatureGroup.jsx';
+import LicenseKeyGroup from './listItems/LicenseKeyGroup.jsx';
+import {overviewEditorHeaders} from './LicenseModelOverviewConstants.js';
+
+class VLMListView extends Component {
+
+ static propTypes = {
+ licensingDataList: React.PropTypes.array,
+ showInUse: React.PropTypes.bool
+ };
+
+ state = {
+
+ };
+
+ render() {
+ let {licensingDataList = []} = this.props;
+ return (
+ <div className='vlm-list-view'>
+ <div>
+ <ul className='vlm-list' data-test-id='vlm-list'>
+ {licensingDataList.map(item => this.renderLicensingItem(item))}
+ </ul>
+ </div>
+ </div>
+ );
+ }
+
+ renderLicensingItem(item) {
+ switch (item.itemType) {
+ case overviewEditorHeaders.LICENSE_AGREEMENT :
+ return this.renderLicenseAgreementItem(item);
+ case overviewEditorHeaders.FEATURE_GROUP :
+ return this.renderFeatureGroupItem(item);
+ case overviewEditorHeaders.LICENSE_KEY_GROUP :
+ return this.renderLicenseKeyGroupItem(item);
+ case overviewEditorHeaders.ENTITLEMENT_POOL:
+ return this.renderEntitlementPoolItem(item);
+ default:
+ return;
+ }
+ }
+
+ renderLicenseAgreementItem(licenseAgreement) {
+ return (
+ <li key={licenseAgreement.id}>
+ <LicenseAgreement
+ laData={licenseAgreement}
+ isCollapsed={this.state[licenseAgreement.id]}
+ onClick={event => this.updateCollapsable(event, licenseAgreement.id) }/>
+ <Collapse in={this.state[licenseAgreement.id]}>
+ <ul>
+ {licenseAgreement.children && licenseAgreement.children.map(item => this.renderLicensingItem(item))}
+ </ul>
+ </Collapse>
+ </li>
+ );
+ }
+
+ renderFeatureGroupItem(featureGroup) {
+ const {showInUse} = this.props;
+ return (
+ <li key={featureGroup.id}>
+ <FeatureGroup
+ fgData={featureGroup}
+ isCollapsed={this.state[featureGroup.id]}
+ onClick={event=> this.updateCollapsable(event, featureGroup.id) }/>
+ {
+ showInUse && <Collapse in={this.state[featureGroup.id]}>
+ <ul>
+ {featureGroup.children && featureGroup.children.map(item => this.renderLicensingItem(item))}
+
+ </ul>
+ </Collapse>
+ }
+ </li>
+ );
+ }
+
+ renderEntitlementPoolItem(entitlementPool) {
+ return (
+ <li key={entitlementPool.id}>
+ <EntitlementPool epData={entitlementPool} />
+ </li>
+ );
+ }
+
+ renderLicenseKeyGroupItem(licenseKeyGroup) {
+ return (
+ <li key={licenseKeyGroup.id}>
+ <LicenseKeyGroup lkgData={licenseKeyGroup} />
+ </li>
+ );
+ }
+
+ updateCollapsable(event, id) {
+ event.stopPropagation();
+ let obj = {};
+ obj[id] = !this.state[id];
+ this.setState(obj);
+ }
+}
+
+export default VLMListView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js
new file mode 100644
index 0000000000..f0286ba3bb
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js
@@ -0,0 +1,39 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './LicenseModelOverviewConstants.js';
+
+export default {
+ selectVLMListView(dispatch, {buttonTab}) {
+ dispatch({
+ type: actionTypes.LICENSE_MODEL_OVERVIEW_TAB_SELECTED,
+ buttonTab
+ });
+ },
+
+ editDescriptionOpen(dispatch, {description}) {
+ dispatch({
+ type: actionTypes.LM_DATA_CHANGED,
+ description
+ });
+ },
+
+ editDescriptionClose(dispatch) {
+ dispatch({
+ type: actionTypes.LM_DATA_CHANGED,
+ description: false
+ });
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx
new file mode 100644
index 0000000000..94977b40d1
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx
@@ -0,0 +1,53 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component} from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {extractValue, extractUnits} from '../../entitlementPools/EntitlementPoolsConstants.js';
+import ArrowCol from './listItemsComponents/ArrowCol.jsx';
+import ItemInfo from './listItemsComponents/ItemInfo.jsx';
+import IconCol from './listItemsComponents/IconCol.jsx';
+import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
+
+class EntitlementPool extends Component {
+ render() {
+ let {epData: {name, description, manufacturerReferenceNumber}} = this.props;
+ return (
+ <div className='vlm-list-item vlm-list-item-ep' data-test-id='vlm-list-item-ep'>
+ <ArrowCol/>
+ <IconCol className='ep-icon'/>
+ <ItemInfo name={name} description={description}/>
+ <AdditionalDataCol>
+ <AdditionalDataElement
+ className='vlm-list-item-entitlement-metric'
+ name={i18n('Entitlement')}
+ value={this.getEntitlement()}/>
+ <AdditionalDataElement
+ name={i18n('Manufacturer Reference Number')}
+ value={manufacturerReferenceNumber}
+ className='vlm-list-item-sku'/>
+ </AdditionalDataCol>
+ </div>
+ );
+ }
+
+ getEntitlement() {
+ let {epData: {entitlementMetric, aggregationFunction, time, thresholdValue, thresholdUnits}} = this.props;
+ return `${extractValue(aggregationFunction)} ${extractValue(entitlementMetric)} per ${extractValue(time)} ${thresholdValue} ${extractUnits(thresholdUnits)}`;
+ }
+
+}
+
+export default EntitlementPool;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx
new file mode 100644
index 0000000000..8dbd46a29e
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx
@@ -0,0 +1,50 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component} from 'react';
+import {overviewEditorHeaders} from '../LicenseModelOverviewConstants.js';
+import ArrowCol from './listItemsComponents/ArrowCol.jsx';
+import ItemInfo from './listItemsComponents/ItemInfo.jsx';
+import IconCol from './listItemsComponents/IconCol.jsx';
+
+class FeatureGroup extends Component {
+ render() {
+ let {fgData: {name, description, children = []}, isCollapsed, onClick} = this.props;
+ return (
+ <div onClick={e => onClick(e)} className='vlm-list-item vlm-list-item-fg' data-test-id='vlm-list-item-fg'>
+ <ArrowCol isCollapsed={isCollapsed} length={children.length} />
+ <IconCol className='fg-icon'/>
+ <ItemInfo name={name} description={description}>
+ <div className='children-count'>
+ <span className='count-value'>
+ Entitlement Pools:
+ <span data-test-id='vlm-list-ep-count-value'>
+ {`${children.filter(child => child.itemType === overviewEditorHeaders.ENTITLEMENT_POOL).length}`}
+ </span>
+ </span>
+ <span className='count-value'>
+ License Key Groups:
+ <span data-test-id='vlm-list-lkg-count-value'>
+ {`${children.filter(child => child.itemType === overviewEditorHeaders.LICENSE_KEY_GROUP).length}`}
+ </span>
+ </span>
+ </div>
+ </ItemInfo>
+ </div>
+ );
+ }
+}
+
+export default FeatureGroup;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx
new file mode 100644
index 0000000000..dd4686d330
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx
@@ -0,0 +1,53 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component} from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import {optionsInputValues} from '../../licenseAgreement/LicenseAgreementConstants.js';
+import ArrowCol from './listItemsComponents/ArrowCol.jsx';
+import ItemInfo from './listItemsComponents/ItemInfo.jsx';
+import IconCol from './listItemsComponents/IconCol.jsx';
+import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
+
+class LicenseAgreement extends Component {
+ render() {
+ let {laData: {name, description, licenseTerm, children = []}, isCollapsed, onClick} = this.props;
+ return (
+ <div onClick={e => onClick(e)} className='vlm-list-item vlm-list-item-la' data-test-id='vlm-list-la-item'>
+ <ArrowCol isCollapsed={isCollapsed} length={children.length} />
+ <IconCol className='la-icon'/>
+ <ItemInfo name={name} description={description}>
+ <div className='children-count'>
+ <span className='count-value'>Feature Groups: <span data-test-id='vlm-list-fg-count-value'>{`${children.length}`}</span></span>
+ </div>
+ </ItemInfo>
+ <AdditionalDataCol>
+ <AdditionalDataElement
+ name={i18n('License Model Type')}
+ value={this.extractValue(licenseTerm)}/>
+ </AdditionalDataCol>
+ </div>
+ );
+ }
+
+ extractValue(item) {
+ if (item === undefined) {return '';} //TODO fix it later
+
+ return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : '';
+ }
+}
+
+export default LicenseAgreement;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx
new file mode 100644
index 0000000000..9722b83336
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx
@@ -0,0 +1,48 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component} from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {extractValue, getOperationalScopes} from '../../licenseKeyGroups/LicenseKeyGroupsConstants.js';
+import ArrowCol from './listItemsComponents/ArrowCol.jsx';
+import ItemInfo from './listItemsComponents/ItemInfo.jsx';
+import IconCol from './listItemsComponents/IconCol.jsx';
+import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
+
+class LicenseKeyGroup extends Component {
+ render() {
+ let {lkgData: {name, description, operationalScope, type}} = this.props;
+ return (
+ <div className='vlm-list-item vlm-list-item-lkg' data-test-id='vlm-list-item-lkg'>
+ <ArrowCol/>
+ <IconCol className='lkg-icon'/>
+ <ItemInfo name={name} description={description}/>
+ <AdditionalDataCol>
+ <AdditionalDataElement
+ className='vlm-list-item-operational-scope'
+ name={i18n('Operational Scope')}
+ value={operationalScope && getOperationalScopes(operationalScope)}/>
+ <AdditionalDataElement
+ className='vlm-list-item-group-type'
+ name={i18n('Type')}
+ value={extractValue(type)}/>
+ </AdditionalDataCol>
+ </div>
+ );
+ }
+
+}
+
+export default LicenseKeyGroup;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx
new file mode 100644
index 0000000000..5b5daafb4f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx
@@ -0,0 +1,51 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+function AdditionalDataCol({children}) {
+ return (
+ <div className='list-item-section list-item-additional-data-col'>
+ <div className='additional-data-col-border'></div>
+ <div className='additional-data'>
+ {children}
+ </div>
+ </div>
+ );
+}
+
+AdditionalDataCol.propTypes = {
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.node),
+ React.PropTypes.node
+ ])
+};
+
+function AdditionalDataElement({className, name, value}) {
+ return (
+ <div className={className}>
+ <span className='additional-data-name'>{name}: </span>
+ <span className='additional-data-value'>{value}</span>
+ </div>
+ );
+}
+
+AdditionalDataElement.propTypes = {
+ name: React.PropTypes.string,
+ value: React.PropTypes.string,
+ className: React.PropTypes.string
+};
+
+export {AdditionalDataCol, AdditionalDataElement};
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx
new file mode 100644
index 0000000000..a5eb9d27dd
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx
@@ -0,0 +1,35 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import classNames from 'classnames';
+
+function ArrowCol ({isCollapsed, length}) {
+ return (
+ <div className='list-item-section list-item-arrow-col'>
+ <div className={classNames('arrow-icon', {'chevron': length > 0},
+ {'down': (length > 0 && isCollapsed)},
+ {'right': (length > 0 && (!isCollapsed))})} >
+ </div>
+ </div>
+ );
+}
+
+ArrowCol.propTypes = {
+ isCollapsed: React.PropTypes.bool,
+ length: React.PropTypes.number
+};
+
+export default ArrowCol;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx
new file mode 100644
index 0000000000..7fd7fcb88a
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx
@@ -0,0 +1,26 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+function IconCol({className}) {
+ return (
+ <div className='list-item-section list-item-icon-col'>
+ <div className={className}></div>
+ </div>
+ );
+}
+
+export default IconCol;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx
new file mode 100644
index 0000000000..655a0dd4a8
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx
@@ -0,0 +1,39 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+function ItemInfo({name, description, children}) {
+ return (
+ <div className='list-item-section vlm-item-info'>
+ <div className='vlm-list-item-title'>
+ <div className='item-name' data-test-id='vlm-list-item-name'>{name}</div>
+ {children}
+ </div>
+ <div className='vlm-list-item-description'>{description}</div>
+ </div>
+ );
+}
+
+ItemInfo.propTypes = {
+ name: React.PropTypes.string,
+ description: React.PropTypes.string,
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.node),
+ React.PropTypes.node
+ ])
+};
+
+export default ItemInfo;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx
new file mode 100644
index 0000000000..0c0103fc10
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx
@@ -0,0 +1,56 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+
+class LicenseModelDescriptionEdit extends React.Component {
+ render() {
+ let {onDataChanged, description, genericFieldInfo} = this.props;
+ let saveButtonClassName = (genericFieldInfo.description.isValid) ? 'description-save' : 'description-save disabled';
+ return(
+ <div className='vendor-description-edit'>
+
+ <Input
+ onChange={description => onDataChanged({description})}
+ value={description}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ className='description-edit-textarea'
+ type='textarea'/>
+ <div className='buttons-row'>
+ <div className='buttons-wrapper'>
+ <div onClick={() => this.onClose()} className='description-button' data-test-id='vlm-summary-vendor-desc-cancel-btn'>cancel</div>
+ <div onClick={() => this.submit()} className={saveButtonClassName} data-test-id='vlm-summary-vendor-desc-save-btn'>save</div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+
+ onClose() {
+ this.props.onClose();
+ }
+
+ submit() {
+ let {onSubmit, data, description} = this.props;
+ onSubmit({
+ ...data,
+ description: description
+ });
+ }
+}
+
+export default LicenseModelDescriptionEdit;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx
new file mode 100644
index 0000000000..730ccb33f1
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx
@@ -0,0 +1,39 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import {selectedButton} from '../LicenseModelOverviewConstants.js';
+
+function ListButtons ({onTabSelect, selectedInUse}) {
+ return (
+ <div className='overview-buttons-section'>
+ <div onClick={()=>onTabSelect(selectedButton.VLM_LIST_VIEW)}
+ className={selectedInUse ? 'button-vlm-list-view vlm-list-icon selected' : 'button-vlm-list-view vlm-list-icon' }
+ data-test-id='vlm-overview-vlmlist-tab'></div>
+ <div onClick={()=>onTabSelect(selectedButton.NOT_IN_USE)}
+ className={selectedInUse ? 'button-vlm-list-view entities-list-icon' : 'button-vlm-list-view entities-list-icon selected' }
+ data-test-id='vlm-overview-orphans-tab' >
+ </div>
+
+ </div>
+ );
+}
+
+ListButtons.propTypes = {
+ onTabSelect: React.PropTypes.func,
+ selectedInUse: React.PropTypes.bool
+};
+
+export default ListButtons;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx
new file mode 100644
index 0000000000..66f2cc6838
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx
@@ -0,0 +1,31 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+function SummaryCountItem ({name, counter, onAdd, onNavigate, isReadOnlyMode}) {
+ return(
+ <div className='summary-count-item'>
+ <div className='summary-name-and-count' onClick={onNavigate}>
+ <span className='item-name' onClick={onNavigate}>{name}</span>
+ <span className='item-count' onClick={onNavigate} data-test-id={'vlm-summary-vendor-counter-' + name.toLowerCase().replace(/\s/g,'-')}>({counter})</span>
+ </div>
+ <div className={isReadOnlyMode ? 'add-button disabled' : 'add-button'} onClick={onAdd} data-test-id={'vlm-summary-vendor-add-btn-' + name.toLowerCase().replace(/\s/g,'-')}/>
+ </div>
+ );
+}
+
+export default SummaryCountItem;
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js
new file mode 100644
index 0000000000..c69a092d23
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js
@@ -0,0 +1,126 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import {connect} from 'react-redux';
+
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+
+import OnboardingActionHelper from '../../../OnboardingActionHelper.js';
+import EntitlementPoolsActionHelper from '../../entitlementPools/EntitlementPoolsActionHelper.js';
+import LicenseAgreementActionHelper from '../../licenseAgreement/LicenseAgreementActionHelper.js';
+import LicenseKeyGroupsActionHelper from '../../licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
+import FeatureGroupsActionHelper from '../../featureGroups/FeatureGroupsActionHelper.js';
+
+import {overviewItems} from '../LicenseModelOverviewConstants.js';
+import SummaryCountItem from './SummaryCountItem.jsx';
+
+export const mapStateToProps = ({licenseModel: {licenseModelEditor, licenseAgreement: {licenseAgreementList},
+ featureGroup: {featureGroupsList}, entitlementPool: {entitlementPoolsList}, licenseKeyGroup: {licenseKeyGroupsList}}}) => {
+
+ let {vendorName, description, id, version} = licenseModelEditor.data;
+
+ let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data);
+
+ let counts = [
+ {name: overviewItems.LICENSE_AGREEMENTS, count: licenseAgreementList.length},
+ {name: overviewItems.FEATURE_GROUPS, count: featureGroupsList.length},
+ {name: overviewItems.ENTITLEMENT_POOLS, count: entitlementPoolsList.length},
+ {name: overviewItems.LICENSE_KEY_GROUPS, count: licenseKeyGroupsList.length},
+ ];
+ return {
+ vendorName,
+ licenseModelId: id,
+ description,
+ counts,
+ isReadOnlyMode,
+ version
+ };
+};
+
+const mapActionsToProps = (dispatch) => {
+ return {
+ onEditorOpenClick: (name, licenseModelId, version) => {
+ switch (name) {
+ case overviewItems.ENTITLEMENT_POOLS:
+ EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch);
+ break;
+ case overviewItems.FEATURE_GROUPS:
+ FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId, version});
+ break;
+ case overviewItems.LICENSE_AGREEMENTS:
+ LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, version});
+ break;
+ case overviewItems.LICENSE_KEY_GROUPS:
+ LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch);
+ break;
+ default:
+ break;
+ }
+ },
+ onNavigateClick: ({name, licenseModelId, version}) => {
+ switch (name) {
+ case overviewItems.ENTITLEMENT_POOLS:
+ OnboardingActionHelper.navigateToEntitlementPools(dispatch, {licenseModelId, version});
+ break;
+ case overviewItems.FEATURE_GROUPS:
+ OnboardingActionHelper.navigateToFeatureGroups(dispatch, {licenseModelId, version});
+ break;
+ case overviewItems.LICENSE_AGREEMENTS:
+ OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId, version});
+ break;
+ case overviewItems.LICENSE_KEY_GROUPS:
+ OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, {licenseModelId, version});
+ break;
+ default:
+ break;
+ }
+ }
+ };
+};
+
+export class SummaryCountList extends React.Component {
+
+ render() {
+ let {counts} = this.props;
+ return(
+ <div className='summary-count-list'>
+ {counts.map(item => this.renderItem(item))}
+ </div>
+ );
+ }
+
+ renderItem(item){
+ const {name, count} = item;
+ const {isReadOnlyMode} = this.props;
+ return(
+ <SummaryCountItem isReadOnlyMode={isReadOnlyMode} name={name} counter={count} onNavigate={() => this.onNavigate(name)} onAdd={() => this.onAdd(name)} key={name} />
+ );
+ }
+
+ onAdd(name) {
+ let {onEditorOpenClick, licenseModelId, isReadOnlyMode, version} = this.props;
+ if (!isReadOnlyMode) {
+ onEditorOpenClick(name, licenseModelId, version);
+ }
+ }
+
+ onNavigate(name) {
+ let {onNavigateClick, licenseModelId, version} = this.props;
+ onNavigateClick({licenseModelId, name, version});
+ }
+}
+
+export default connect(mapStateToProps, mapActionsToProps)(SummaryCountList);
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js
new file mode 100644
index 0000000000..1d65ab9869
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js
@@ -0,0 +1,86 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import {connect} from 'react-redux';
+
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import licenseModelOverviewActionHelper from '../licenseModelOverviewActionHelper.js';
+import LicenseModelActionHelper from '../../LicenseModelActionHelper.js';
+import LicenseModelDescriptionEdit from './LicenseModelDescriptionEdit.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {VLM_DESCRIPTION_FORM} from '../LicenseModelOverviewConstants.js';
+
+export const mapStateToProps = ({licenseModel: {licenseModelEditor: {data}, licenseModelOverview: {descriptionEditor: {data: descriptionData, genericFieldInfo} }}}) => {
+ let description = (descriptionData && descriptionData.description) ? descriptionData.description : null;
+ let isReadOnlyMode = VersionControllerUtils.isReadOnly(data);
+ return {
+ data,
+ description,
+ genericFieldInfo,
+ isReadOnlyMode
+ };
+};
+
+const mapActionsToProps = (dispatch) => {
+ return {
+ onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: VLM_DESCRIPTION_FORM}),
+ onCancel: () => licenseModelOverviewActionHelper.editDescriptionClose(dispatch),
+ onSubmit: (licenseModel) => {
+ licenseModelOverviewActionHelper.editDescriptionClose(dispatch);
+ LicenseModelActionHelper.saveLicenseModel(dispatch, {licenseModel});
+ },
+ onVendorDescriptionEdit: description => licenseModelOverviewActionHelper.editDescriptionOpen(dispatch,{description})
+ };
+};
+
+
+
+export class VendorDataView extends React.Component {
+ render() {
+ let {data: {vendorName}, description, isReadOnlyMode} = this.props;
+ return (
+ <div className='vendor-data-view'>
+ <div className='vendor-title'>vendor</div>
+ <div className='vendor-name' data-test-id='vlm-summary-vendor-name'>{vendorName}</div>
+ {
+ description && !isReadOnlyMode ? this.renderDescriptionEdit() : this.renderDescription()
+ }
+ </div>
+ );
+ }
+
+ renderDescription() {
+ let {data: {description}, onVendorDescriptionEdit, isReadOnlyMode} = this.props;
+ return (
+ <div onClick={() => {if (!isReadOnlyMode) {onVendorDescriptionEdit(description);}}} className={!isReadOnlyMode ? 'vendor-description' : 'vendor-description-readonly'}>
+ <div className='description-data' data-test-id='vlm-summary-vendor-description'>
+ {description}
+ </div>
+ </div>
+ );
+ }
+
+ renderDescriptionEdit() {
+ let {onCancel, onDataChanged, onSubmit, description, genericFieldInfo, data} = this.props;
+ return(
+ <LicenseModelDescriptionEdit onClose={onCancel} onDataChanged={onDataChanged} onSubmit={onSubmit} data={data} genericFieldInfo={genericFieldInfo} description={description}/>
+ );
+ }
+
+}
+
+export default connect(mapStateToProps, mapActionsToProps)(VendorDataView);
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
new file mode 100644
index 0000000000..c63fbff21b
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
@@ -0,0 +1,134 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import {catalogItemTypeClasses, migrationStatusMapper} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import CatalogTile from './CatalogTile.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {statusEnum, statusBarTextMap} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import tooltip from './onboardingCatalog/Tooltip.jsx';
+
+
+
+const CatalogTileIcon = ({catalogItemTypeClass}) => (
+ <div className={'catalog-tile-icon ' + catalogItemTypeClass}>
+ <div className='icon'><SVGIcon
+ name={catalogItemTypeClass === catalogItemTypeClasses.LICENSE_MODEL ? 'vlm' : 'vsp' }/>
+ </div>
+ </div>
+);
+
+const ItemTypeTitle = ({catalogItemTypeClass}) => {
+ const itemTypeTitle = catalogItemTypeClass === catalogItemTypeClasses.LICENSE_MODEL ? i18n('VLM') : i18n('VSP');
+ return(
+ <div className={`catalog-tile-type ${catalogItemTypeClass}`}>{itemTypeTitle}</div>
+ );
+};
+
+const CatalogTileVendorName = ({vendorName, catalogItemTypeClass}) => {
+ const name = catalogItemTypeClass === catalogItemTypeClasses.SOFTWARE_PRODUCT ? vendorName : '';
+ return(
+ <div>
+ <OverlayTrigger placement='top' overlay={tooltip(name)}>
+ <div className='catalog-tile-vendor-name'>{name}</div>
+ </OverlayTrigger>
+ </div>
+ );
+};
+
+const CatalogTileItemName = ({name}) => (
+ <div>
+ <OverlayTrigger placement='top' overlay={tooltip(name && name.toUpperCase())}>
+ <div className='catalog-tile-item-name'>{name}</div>
+ </OverlayTrigger>
+ </div>
+);
+
+const VersionInfo = ({version}) => (
+ <div className='catalog-tile-version-info'>
+ <div className='catalog-tile-item-version' data-test-id='catalog-item-version'>
+ V {version}
+ </div>
+ </div>
+);
+
+const EntityDetails = ({catalogItemData, catalogItemTypeClass}) => {
+ const {vendorName, name, version} = catalogItemData;
+ return (
+ <div className='catalog-tile-entity-details'>
+ <CatalogTileVendorName catalogItemTypeClass={catalogItemTypeClass} vendorName={vendorName}/>
+ <CatalogTileItemName name={name}/>
+ <VersionInfo version={version.label} />
+ </div>
+ );
+};
+
+
+const ItemStatusInfo = ({catalogItemTypeClass, lockingUser, itemStatus}) => {
+ const status = statusBarTextMap[itemStatus];
+ const lockedBy = lockingUser ? ` by ${lockingUser}` : '';
+ const toolTipMsg = `${status}${lockedBy}`;
+
+ return (
+ <div className={'catalog-tile-content ' + catalogItemTypeClass}>
+ <div className='catalog-tile-locking-user-name'>{i18n(status)}</div>
+ <OverlayTrigger placement='top' overlay={tooltip(toolTipMsg)}>
+ <div className='catalog-tile-check-in-status'><SVGIcon
+ name={itemStatus === statusEnum.CHECK_OUT_STATUS ? 'unlocked' : 'locked'}
+ data-test-id={itemStatus === statusEnum.CHECK_IN_STATUS ? 'catalog-item-checked-in' : 'catalog-item-checked-out'}/>
+ </div>
+ </OverlayTrigger>
+ </div>
+
+ );
+};
+
+const CatalogItemDetails = ({catalogItemData, catalogItemTypeClass, onSelect, onMigrate}) => {
+
+ let {status: itemStatus} = VersionControllerUtils.getCheckOutStatusKindByUserID(catalogItemData.status, catalogItemData.lockingUser);
+
+ return (
+ <CatalogTile catalogItemTypeClass={catalogItemTypeClass} onSelect={() => {
+ if (catalogItemData.isOldVersion && catalogItemData.isOldVersion === migrationStatusMapper.OLD_VERSION) {
+ onMigrate({
+ softwareProduct: catalogItemData
+ });
+ } else {
+ onSelect();
+ }
+ }} data-test-id={catalogItemTypeClass}>
+ <div className='catalog-tile-top item-details'>
+ <ItemTypeTitle catalogItemTypeClass={catalogItemTypeClass}/>
+ <CatalogTileIcon catalogItemTypeClass={catalogItemTypeClass}/>
+ <EntityDetails catalogItemTypeClass={catalogItemTypeClass} catalogItemData={catalogItemData} />
+ <ItemStatusInfo itemStatus={itemStatus} catalogItemTypeClass={catalogItemTypeClass} lockingUser={catalogItemData.lockingUser} />
+ </div>
+ </CatalogTile>
+ );
+
+};
+
+CatalogItemDetails.PropTypes = {
+ catalogItemData: React.PropTypes.obj,
+ catalogItemTypeClass: React.PropTypes.string,
+ onSelect: React.PropTypes.func,
+ onMigrate: React.PropTypes.func
+};
+
+export default CatalogItemDetails;
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js
new file mode 100644
index 0000000000..c4e2724eaf
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import {storiesOf, action} from '@kadira/storybook';
+import {select, withKnobs} from '@kadira/storybook-addon-knobs';
+import CatalogItemDetails from './CatalogItemDetails.jsx';
+import {FinalizedLicenseModelFactory} from 'test-utils/factories/licenseModel/LicenseModelFactories.js';
+import {statusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+
+
+
+const stories = storiesOf('CatalogTiles', module);
+stories.addDecorator(withKnobs);
+
+const types = [
+ 'license-model-type',
+ 'software-product-type'
+];
+
+function selectType() {
+ return select('Item type' , types, types[0]);
+}
+
+let vlm = FinalizedLicenseModelFactory.build({name: 'Test-VLM'});
+let unclockedVlm = {...vlm, status: statusEnum.CHECK_OUT_STATUS};
+
+
+stories
+ .add('preview', () => (
+ <div className='catalog-view'>
+ <div className='catalog-list'>
+ <div className='catalog-items'>
+ <CatalogItemDetails catalogItemData={vlm} catalogItemTypeClass={selectType()} onSelect={action('onSelect')} onMigrate={action('onMigrate')}/>
+ <CatalogItemDetails catalogItemData={unclockedVlm} catalogItemTypeClass={selectType()} onSelect={action('onSelect')} onMigrate={action('onMigrate')}/>
+ </div>
+ </div>
+ </div>
+ ));
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx
new file mode 100644
index 0000000000..17248e3b02
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogList.jsx
@@ -0,0 +1,51 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+
+const SoftwareProductListHeader = ({selectedVendor, onBack}) => (
+ <div className='vendor-page-header'>
+ <SVGIcon name='back' onClick={onBack}/>
+ <div className='tab-separator' />
+ <div className='vendor-name'>{selectedVendor.vendorName}</div>
+ </div>
+);
+
+const CatalogList = ({children, onAddVLM, onAddVSP, vendorPageOptions}) => (
+ <div className='catalog-list'>
+ {vendorPageOptions && <SoftwareProductListHeader onBack={vendorPageOptions.onBack} selectedVendor={vendorPageOptions.selectedVendor}/>}
+ <div className='catalog-items'>
+ <div className='create-catalog-item-wrapper'>
+ {onAddVLM && <CreateItemTile onClick={onAddVLM} dataTestId={'catalog-add-new-lm'} className='vlm-type' title={i18n('CREATE NEW VLM')}/>}
+ {onAddVSP &&
+ <CreateItemTile onClick={onAddVSP} dataTestId={'catalog-add-new-vsp'} className='vsp-type' title={i18n('CREATE NEW VSP')}/>}
+ </div>
+ {children}
+ </div>
+ </div>
+);
+
+const CreateItemTile = ({onClick, dataTestId, title, className = ''}) => {
+ return (
+ <div className={'create-catalog-item tile ' + className} onClick={() => onClick()} data-test-id={dataTestId}>
+ <div className='create-item-plus-icon'><SVGIcon name='plus' /></div>
+ <div className='create-item-text'>{title}</div>
+ </div>
+ );
+};
+
+export default CatalogList;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx
new file mode 100644
index 0000000000..1ef9c82822
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogModal.jsx
@@ -0,0 +1,62 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import {modalMapper, catalogItemTypes, catalogItemTypeClasses } from './onboardingCatalog/OnboardingCatalogConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Modal from 'nfvo-components/modal/Modal.jsx';
+import LicenseModelCreation from '../licenseModel/creation/LicenseModelCreation.js';
+import SoftwareProductCreation from '../softwareProduct/creation/SoftwareProductCreation.js';
+
+class CatalogModal extends React.Component{
+
+ getModalDetails(){
+ const {modalToShow} = this.props;
+ switch (modalToShow) {
+ case catalogItemTypes.LICENSE_MODEL:
+ return {
+ title: i18n('New License Model'),
+ element: <LicenseModelCreation/>
+ };
+ case catalogItemTypes.SOFTWARE_PRODUCT:
+ return {
+ title: i18n('New Software Product'),
+ element: <SoftwareProductCreation/>
+ };
+ }
+ }
+
+ render(){
+ const {modalToShow} = this.props;
+ const modalDetails = this.getModalDetails(modalToShow);
+
+ return (
+ <Modal
+ show={Boolean(modalDetails)}
+ className={`${catalogItemTypeClasses[modalMapper[modalToShow]]}-modal`}>
+ <Modal.Header>
+ <Modal.Title>{modalDetails && modalDetails.title}</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ {
+ modalDetails && modalDetails.element
+ }
+ </Modal.Body>
+ </Modal>
+ );
+ }
+}
+
+export default CatalogModal;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx
new file mode 100644
index 0000000000..c7720a9d0e
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogTile.jsx
@@ -0,0 +1,31 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+
+const CatalogTile = ({catalogItemTypeClass, onSelect, children}) => {
+ return(
+ <div className={`catalog-tile tile ${catalogItemTypeClass}`} onClick={(e) => {e.stopPropagation(); e.preventDefault(); onSelect();}} data-test-id={catalogItemTypeClass}>
+ {children}
+ </div>
+ );
+};
+
+CatalogTile.PropTypes = {
+ catalogItemTypeClass: React.PropTypes.string,
+ onSelect: React.PropTypes.func
+};
+
+export default CatalogTile;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx
new file mode 100644
index 0000000000..ef54848523
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx
@@ -0,0 +1,56 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import {catalogItemTypes, modalMapper, catalogItemTypeClasses} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import {filterCatalogItemsByType} from './onboardingCatalog/OnboardingCatalogUtils.js';
+import CatalogList from './CatalogList.jsx';
+import CatalogItemDetails from './CatalogItemDetails.jsx';
+
+class DetailsCatalogView extends React.Component{
+
+ static propTypes = {
+ VLMList: React.PropTypes.array,
+ VSPList: React.PropTypes.array,
+ onSelectVLM: React.PropTypes.func.isRequired,
+ onSelectVSP: React.PropTypes.func.isRequired,
+ onAddVLM: React.PropTypes.func.isRequired,
+ onAddVSP: React.PropTypes.func.isRequired,
+ filter: React.PropTypes.string.isRequired
+ };
+
+ renderCatalogItems(items, type, filter, onSelect, onMigrate, tileType){
+ return filterCatalogItemsByType(items, type, filter).map(item =>
+ <CatalogItemDetails
+ key={item.id}
+ catalogItemData={type === catalogItemTypes.LICENSE_MODEL ? {...item, name: item.vendorName} : item}
+ catalogItemTypeClass={catalogItemTypeClasses[modalMapper[type]]}
+ onMigrate={onMigrate}
+ onSelect={() => onSelect(item)}
+ tileType={tileType} />
+ );
+ }
+
+ render() {
+ let {VLMList, VSPList, onAddVSP, onAddVLM, onSelectVLM, onSelectVSP, filter = '', onMigrate, tileType} = this.props;
+ return (
+ <CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
+ {this.renderCatalogItems(VLMList, catalogItemTypes.LICENSE_MODEL, filter, onSelectVLM, onMigrate, tileType)}
+ {this.renderCatalogItems(VSPList, catalogItemTypes.SOFTWARE_PRODUCT, filter, onSelectVSP, onMigrate, tileType)}
+ </CatalogList>
+ );
+ }
+}
+export default DetailsCatalogView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js b/openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js
new file mode 100644
index 0000000000..b13ccbbba2
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js
@@ -0,0 +1,90 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import {connect} from 'react-redux';
+import OnboardView from './OnboardView.jsx';
+import OnboardingActionHelper from '../OnboardingActionHelper.js';
+import OnboardingCatalogActionHelper from './onboardingCatalog/OnboardingCatalogActionHelper.js';
+import OnboardActionHelper from './OnboardActionHelper.js';
+import LicenseModelCreationActionHelper from '../licenseModel/creation/LicenseModelCreationActionHelper.js';
+import SoftwareProductCreationActionHelper from '../softwareProduct/creation/SoftwareProductCreationActionHelper.js';
+import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
+
+export const mapStateToProps = ({
+ onboard: {onboardingCatalog, activeTab, searchValue}, licenseModelList, finalizedLicenseModelList, softwareProductList, finalizedSoftwareProductList
+}) => {
+
+ const reduceLicenseModelList = (accum, vlm)=> {
+ let currentSoftwareProductList = sortByStringProperty(
+ finalizedSoftwareProductList
+ .filter(vsp => vsp.vendorId === vlm.id),
+ 'name'
+ );
+ accum.push({...vlm, softwareProductList: currentSoftwareProductList});
+ return accum;
+ };
+
+ finalizedLicenseModelList = sortByStringProperty(
+ licenseModelList
+ .filter(vlm => finalizedLicenseModelList.map(finalVlm => finalVlm.id).includes(vlm.id))
+ .reduce(reduceLicenseModelList, []),
+ 'vendorName'
+ );
+
+ finalizedSoftwareProductList = sortByStringProperty(
+ softwareProductList
+ .filter(vsp => finalizedSoftwareProductList.map(finalVsp => finalVsp.id).includes(vsp.id)),
+ 'name'
+ );
+
+
+ let {activeTab: catalogActiveTab, vendorCatalog: {vspOverlay, selectedVendor}} = onboardingCatalog;
+
+ return {
+ finalizedLicenseModelList,
+ finalizedSoftwareProductList,
+ licenseModelList,
+ softwareProductList,
+ activeTab,
+ catalogActiveTab,
+ searchValue,
+ vspOverlay,
+ selectedVendor
+ };
+};
+
+const mapActionsToProps = (dispatch) => {
+ return {
+ onSelectLicenseModel({id: licenseModelId, version}) {
+ OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, {licenseModelId, version});
+ },
+ onSelectSoftwareProduct(softwareProduct) {
+ let {id: softwareProductId, vendorId: licenseModelId, licensingVersion, version} = softwareProduct;
+ OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version, licenseModelId, licensingVersion});
+ },
+ onAddSoftwareProductClick: (vendorId) => SoftwareProductCreationActionHelper.open(dispatch, vendorId),
+ onAddLicenseModelClick: () => LicenseModelCreationActionHelper.open(dispatch),
+ onVspOverlayChange: (vendor) => OnboardingCatalogActionHelper.changeVspOverlay(dispatch, vendor),
+ closeVspOverlay: () => OnboardingCatalogActionHelper.closeVspOverlay(dispatch),
+ onCatalogTabClick: (tab) => OnboardingCatalogActionHelper.changeActiveTab(dispatch, tab),
+ onTabClick: (tab) => OnboardActionHelper.changeActiveTab(dispatch, tab),
+ onSearch: (searchValue) => OnboardActionHelper.changeSearchValue(dispatch, searchValue),
+ onVendorSelect: (vendor) => OnboardingCatalogActionHelper.onVendorSelect(dispatch, {vendor}),
+ onMigrate: ({softwareProduct}) => OnboardingCatalogActionHelper.onMigrate(dispatch, softwareProduct)
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(OnboardView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js
new file mode 100644
index 0000000000..6ebb40878f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js
@@ -0,0 +1,45 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './OnboardConstants.js';
+
+const OnboardActionHelper = {
+ resetOnboardStore(dispatch) {
+ dispatch({
+ type: actionTypes.RESET_ONBOARD_STORE
+ });
+ },
+ changeActiveTab(dispatch, activeTab) {
+ this.clearSearchValue(dispatch);
+ dispatch({
+ type: actionTypes.CHANGE_ACTIVE_ONBOARD_TAB,
+ activeTab
+ });
+ },
+ changeSearchValue(dispatch, searchValue) {
+ dispatch({
+ type: actionTypes.CHANGE_SEARCH_VALUE,
+ searchValue
+ });
+ },
+ clearSearchValue(dispatch) {
+ dispatch({
+ type: actionTypes.CHANGE_SEARCH_VALUE,
+ searchValue: ''
+ });
+ }
+};
+
+export default OnboardActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js
new file mode 100644
index 0000000000..41128bfb11
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardConstants.js
@@ -0,0 +1,28 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const tabsMapping = {
+ 'WORKSPACE': 1,
+ 'CATALOG': 2
+};
+
+export const actionTypes = keyMirror({
+ CHANGE_ACTIVE_ONBOARD_TAB: null,
+ CHANGE_SEARCH_VALUE: null,
+ RESET_ONBOARD_STORE: null,
+ VSP_MIGRATION: null
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js
new file mode 100644
index 0000000000..72145015db
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardReducer.js
@@ -0,0 +1,31 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes, tabsMapping} from './OnboardConstants.js';
+import {combineReducers} from 'redux';
+import onboardingCatalogReducer from './onboardingCatalog/OnboardingCatalogReducer.js';
+
+const onboardReducer = combineReducers({
+ onboardingCatalog: onboardingCatalogReducer,
+ activeTab: (state = tabsMapping.WORKSPACE, action) => action.type === actionTypes.CHANGE_ACTIVE_ONBOARD_TAB ? action.activeTab : state,
+ searchValue: (state = '', action) => action.type === actionTypes.CHANGE_SEARCH_VALUE ? action.searchValue : state
+});
+
+export default (state, action) => {
+ if (action.type === actionTypes.RESET_ONBOARD_STORE) {
+ state = undefined;
+ }
+ return onboardReducer(state, action);
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx
new file mode 100644
index 0000000000..b7a7fa5f68
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx
@@ -0,0 +1,95 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import OnboardingCatalogView from './onboardingCatalog/OnboardingCatalogView.jsx';
+import WorkspaceView from './workspace/WorkspaceView.jsx';
+import {tabsMapping} from './OnboardConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import classnames from 'classnames';
+import ExpandableInput from 'nfvo-components/input/ExpandableInput.jsx';
+import objectValues from 'lodash/values.js';
+import {catalogItemTypes} from './onboardingCatalog/OnboardingCatalogConstants.js';
+
+const OnboardHeaderTabs = ({onTabClick, activeTab}) => (
+ <div className='onboard-header-tabs'>
+ <div
+ className={classnames('onboard-header-tab', {'active': activeTab === tabsMapping.WORKSPACE })}
+ onClick={() => onTabClick(tabsMapping.WORKSPACE)}
+ data-test-id='onboard-workspace-tab'>
+ {i18n('WORKSPACE')}
+ </div>
+ <div
+ className={classnames('onboard-header-tab', {'active': activeTab === tabsMapping.CATALOG })}
+ onClick={() => onTabClick(tabsMapping.CATALOG)}
+ data-test-id='onboard-onboard-tab'>
+ {i18n('ONBOARD CATALOG')}
+ </div>
+ </div>
+);
+
+const OnboardHeader = ({onSearch, activeTab, onTabClick, searchValue}) => (
+ <div className='onboard-header'>
+ <OnboardHeaderTabs activeTab={activeTab} onTabClick={onTabClick} />
+ <ExpandableInput
+ onChange={onSearch}
+ iconType='search'
+ value={searchValue}/>
+ </div>
+);
+
+class OnboardView extends React.Component {
+ static propTypes = {
+ licenseModelList: React.PropTypes.array,
+ softwareProductList: React.PropTypes.array,
+ finalizedLicenseModelList: React.PropTypes.array,
+ finalizedSoftwareProductList: React.PropTypes.array,
+ modalToShow: React.PropTypes.oneOf(objectValues(catalogItemTypes)),
+ onSelectLicenseModel: React.PropTypes.func.isRequired,
+ onSelectSoftwareProduct: React.PropTypes.func.isRequired,
+ onAddLicenseModelClick: React.PropTypes.func.isRequired,
+ onAddSoftwareProductClick: React.PropTypes.func.isRequired,
+ closeVspOverlay: React.PropTypes.func.isRequired,
+ onVspOverlayChange: React.PropTypes.func.isRequired,
+ onTabClick: React.PropTypes.func.isRequired,
+ onCatalogTabClick: React.PropTypes.func.isRequired,
+ onSearch: React.PropTypes.func.isRequired,
+ activeTab: React.PropTypes.number.isRequired,
+ catalogActiveTab: React.PropTypes.number.isRequired,
+ searchValue: React.PropTypes.string.isRequired,
+ onMigrate: React.PropTypes.func.isRequired,
+ };
+ renderViewByTab(activeTab){
+ switch (activeTab){
+ case tabsMapping.WORKSPACE:
+ return <WorkspaceView {...this.props} />;
+ case tabsMapping.CATALOG:
+ default:
+ return <OnboardingCatalogView {...this.props} />;
+ }
+ }
+
+ render() {
+ let {closeVspOverlay, activeTab, onTabClick, onSearch, searchValue} = this.props;
+ return (
+ <div className='catalog-view' onClick={closeVspOverlay}>
+ <OnboardHeader activeTab={activeTab} onTabClick={onTabClick} searchValue={searchValue} onSearch={value => onSearch(value)}/>
+ {this.renderViewByTab(activeTab)}
+ </div>
+ );
+ }
+}
+
+export default OnboardView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js
new file mode 100644
index 0000000000..73a447558d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js
@@ -0,0 +1,85 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes} from './OnboardingCatalogConstants.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import {statusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import OnboardActionHelper from '../OnboardActionHelper.js';
+import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
+
+
+function getMessageForMigration(name) {
+ return (
+ <div>
+ <div>{i18n('{name} needs to be updated. Click ‘Checkout & Update’, to proceed.',{name})}</div>
+ <div>{i18n('Please don’t forget to submit afterwards')}</div>
+ </div>
+ );
+}
+
+const OnboardingCatalogActionHelper = {
+ changeVspOverlay(dispatch, vendor) {
+ dispatch({
+ type: actionTypes.CHANGE_VSP_OVERLAY,
+ vendorId: vendor ? vendor.id : null
+ });
+ },
+ closeVspOverlay(dispatch) {
+ dispatch({
+ type: actionTypes.CLOSE_VSP_OVERLAY
+ });
+ },
+ changeActiveTab(dispatch, activeTab) {
+ OnboardActionHelper.clearSearchValue(dispatch);
+ dispatch({
+ type: actionTypes.CHANGE_ACTIVE_CATALOG_TAB,
+ activeTab
+ });
+ },
+ onVendorSelect(dispatch, {vendor}) {
+ OnboardActionHelper.clearSearchValue(dispatch);
+ dispatch({
+ type: actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE,
+ selectedVendor: vendor
+ });
+ },
+ onMigrate(dispatch, softwareProduct) {
+ const {status, name, lockingUser} = softwareProduct;
+ if (status === statusEnum.CHECK_OUT_STATUS && !VersionControllerUtils.isCheckedOutByCurrentUser(softwareProduct)) {
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data: {
+ title: 'WARNING',
+ msg: i18n('{name} is locked by user {lockingUser} for self-healing',{name, lockingUser})
+ }
+ });
+ } else {
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ title: 'WARNING',
+ msg: getMessageForMigration(softwareProduct.name.toUpperCase()),
+ confirmationButtonText: i18n('Checkout & Update'),
+ onConfirmed: ()=>SoftwareProductActionHelper.migrateSoftwareProduct(dispatch, {softwareProduct})
+ }
+ });
+ }
+ }
+};
+
+export default OnboardingCatalogActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js
new file mode 100644
index 0000000000..071160c4fd
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js
@@ -0,0 +1,50 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const catalogItemTypes = Object.freeze({
+ LICENSE_MODEL: 'license-model',
+ SOFTWARE_PRODUCT: 'software-product'
+});
+
+export const catalogItemTypeClasses = {
+ LICENSE_MODEL: 'license-model-type',
+ SOFTWARE_PRODUCT: 'software-product-type',
+ VENDOR: 'vendor-type'
+
+};
+
+export const modalMapper = {
+ 'license-model': 'LICENSE_MODEL',
+ 'software-product': 'SOFTWARE_PRODUCT'
+};
+
+export const tabsMapping = {
+ 'BY_VENDOR': 1,
+ 'ALL': 2
+};
+
+export const migrationStatusMapper = {
+ OLD_VERSION: 'True',
+};
+
+export const actionTypes = keyMirror({
+ ONBOARDING_CATALOG_OPEN_VENDOR_PAGE: null,
+ CHANGE_ACTIVE_CATALOG_TAB: null,
+ CHANGE_SEARCH_VALUE: null,
+ CHANGE_VSP_OVERLAY: null,
+ CLOSE_VSP_OVERLAY: null
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js
new file mode 100644
index 0000000000..d7d9d0bd6c
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogReducer.js
@@ -0,0 +1,30 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes, tabsMapping} from './OnboardingCatalogConstants.js';
+import {combineReducers} from 'redux';
+import vendorCatalogReducer from './VendorCatalogReducer.js';
+
+const onboardingCatalogReducer = combineReducers({
+ vendorCatalog: vendorCatalogReducer,
+ activeTab: (state = tabsMapping.ALL, action) => action.type === actionTypes.CHANGE_ACTIVE_CATALOG_TAB ? action.activeTab : state
+});
+
+export default (state, action) => {
+ if (action.type === actionTypes.RESET_ONBOARDING_CATALOG_STORE) {
+ state = undefined;
+ }
+ return onboardingCatalogReducer(state, action);
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js
new file mode 100644
index 0000000000..ac623db920
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogUtils.js
@@ -0,0 +1,21 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {catalogItemTypes} from './OnboardingCatalogConstants.js';
+
+export const filterCatalogItemsByType = (items, type, filter) => {
+ const fieldName = type === catalogItemTypes.LICENSE_MODEL ? 'vendorName' : 'name';
+ return items.filter(item => item[fieldName].toLowerCase().indexOf(filter.toLowerCase()) > -1);
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx
new file mode 100644
index 0000000000..b1f002d2fb
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx
@@ -0,0 +1,98 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import classnames from 'classnames';
+import DetailsCatalogView from 'sdc-app/onboarding/onboard/DetailsCatalogView.jsx';
+import VendorCatalogView from './VendorCatalogView.jsx';
+import { tabsMapping} from './OnboardingCatalogConstants.js';
+
+const CatalogHeaderTabs = ({onTabPress, activeTab}) => (
+ <div className='catalog-header-tabs'>
+ <div
+ className={classnames('catalog-header-tab', {'active': activeTab === tabsMapping.ALL })}
+ onClick={() => onTabPress(tabsMapping.ALL)}
+ data-test-id='catalog-all-tab'>
+ {i18n('ALL')}
+ </div>
+ <div className='tab-separator'/>
+ <div
+ className={classnames('catalog-header-tab', {'active': activeTab === tabsMapping.BY_VENDOR })}
+ onClick={() => onTabPress(tabsMapping.BY_VENDOR)}
+ data-test-id='catalog-by-vendor-tab'>
+ {i18n('BY VENDOR')}
+ </div>
+ </div>
+);
+
+const CatalogHeader = ({activeTab, onTabPress}) => (
+ <div className='catalog-header'>
+ <CatalogHeaderTabs activeTab={activeTab} onTabPress={onTabPress} />
+ </div>
+);
+
+class OnboardingCatalogView extends React.Component {
+ renderViewByTab(activeTab){
+ const {finalizedLicenseModelList: licenseModelList, vspOverlay, finalizedSoftwareProductList: softwareProductList, onSelectLicenseModel, onSelectSoftwareProduct,
+ onAddLicenseModelClick, onAddSoftwareProductClick, onVspOverlayChange, onVendorSelect, selectedVendor, searchValue, onMigrate} = this.props;
+ switch (activeTab){
+ case tabsMapping.ALL:
+ return (
+ <DetailsCatalogView
+ VLMList={licenseModelList}
+ VSPList={softwareProductList}
+ onAddVLM={onAddLicenseModelClick}
+ onAddVSP={onAddSoftwareProductClick}
+ onSelectVLM={onSelectLicenseModel}
+ onSelectVSP={onSelectSoftwareProduct}
+ filter={searchValue}
+ onMigrate={onMigrate}/>
+ );
+ case tabsMapping.BY_VENDOR:
+ default:
+ return (
+ <VendorCatalogView
+ licenseModelList={licenseModelList}
+ onAddVSP={onAddSoftwareProductClick}
+ onAddVLM={onAddLicenseModelClick}
+ onSelectVSP={onSelectSoftwareProduct}
+ onSelectVLM={onSelectLicenseModel}
+ vspOverlay={vspOverlay}
+ onVendorSelect={onVendorSelect}
+ selectedVendor={selectedVendor}
+ onVspOverlayChange={onVspOverlayChange}
+ onMigrate={onMigrate}
+ filter={searchValue}/>
+ );
+ }
+ }
+
+ render() {
+ const {selectedVendor, catalogActiveTab: activeTab, onCatalogTabClick, onSearch, searchValue} = this.props;
+ return (
+ <div className='catalog-wrapper'>
+ {!selectedVendor && <CatalogHeader
+ onSearch={event => onSearch(event.target.value)}
+ activeTab={activeTab}
+ onTabPress={tab => onCatalogTabClick(tab)}
+ searchValue={searchValue}/>}
+ {this.renderViewByTab(activeTab)}
+ </div>
+ );
+ }
+}
+
+export default OnboardingCatalogView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx
new file mode 100644
index 0000000000..8d8d1162a0
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/Tooltip.jsx
@@ -0,0 +1,24 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import React from 'react';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+
+export default function tooltip (msg) {
+ return (
+ <Tooltip className='tile-tooltip' id='tile-tooltip'>{msg}</Tooltip>
+ );
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx
new file mode 100644
index 0000000000..1ba4834fa3
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VSPOverlay.jsx
@@ -0,0 +1,50 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {migrationStatusMapper} from './OnboardingCatalogConstants.js';
+
+const VSPOverlay = ({VSPList, onSelectVSP, onSeeMore, onMigrate}) => (
+ <div className='vsp-overlay-wrapper' onClick={(e) => {
+ e.stopPropagation();
+ e.preventDefault();
+ }}>
+ <div className='vsp-overlay-arrow'></div>
+ <div className='vsp-overlay'>
+ <div className='vsp-overlay-title'>{i18n('Recently Edited')}</div>
+ <div className='vsp-overlay-list'>
+ {VSPList.slice(0, 5).map(vsp => <div key={vsp.id} className='vsp-overlay-detail' onClick={() => {
+ if (vsp.isOldVersion && vsp.isOldVersion === migrationStatusMapper.OLD_VERSION) {
+ onMigrate({
+ softwareProduct: vsp
+ });
+ } else {
+ onSelectVSP(vsp);
+ }
+ }
+ }>{i18n(vsp.name)}</div>)}
+ </div>
+ {VSPList.length > 5 && <div className='vsp-overlay-see-more' onClick={onSeeMore}>{i18n('See More')}</div>}
+ </div>
+ </div>
+);
+
+VSPOverlay.PropTypes = {
+ VSPList: React.PropTypes.array,
+ onSelectVSP: React.PropTypes.func
+};
+
+export default VSPOverlay;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js
new file mode 100644
index 0000000000..dd8b41bd22
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogReducer.js
@@ -0,0 +1,38 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './OnboardingCatalogConstants.js';
+
+export default (state = {}, action) => {
+ switch(action.type) {
+ case actionTypes.ONBOARDING_CATALOG_OPEN_VENDOR_PAGE:
+ return {
+ ...state,
+ selectedVendor: action.selectedVendor
+ };
+ case actionTypes.CHANGE_VSP_OVERLAY:
+ return {
+ ...state,
+ vspOverlay: action.vendorId
+ };
+ case actionTypes.CLOSE_VSP_OVERLAY:
+ return {
+ ...state,
+ vspOverlay: null
+ };
+ default:
+ return state;
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx
new file mode 100644
index 0000000000..c4e0599d85
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorCatalogView.jsx
@@ -0,0 +1,74 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import VendorItem from './VendorItem.jsx';
+import CatalogList from '../CatalogList.jsx';
+import CatalogItemDetails from '../CatalogItemDetails.jsx';
+import {catalogItemTypes, catalogItemTypeClasses} from './OnboardingCatalogConstants.js';
+import {filterCatalogItemsByType} from './OnboardingCatalogUtils.js';
+
+const VendorList = ({onAddVLM, onAddVSP, onSelectVSP, licenseModelList = [], vspOverlay: currentOverlay, onVspOverlayChange, onVendorSelect, filter, onMigrate}) => {
+ return(
+ <CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
+ {
+ filterCatalogItemsByType(licenseModelList, catalogItemTypes.LICENSE_MODEL, filter).map(vlm =>
+ <VendorItem
+ key={vlm.id}
+ onAddVSP={onAddVSP}
+ onSelectVSP={onSelectVSP}
+ shouldShowOverlay={currentOverlay === vlm.id}
+ onVSPIconClick={(hasVSP) => onVspOverlayChange(vlm.id === currentOverlay || !hasVSP ? null : vlm)}
+ onVendorSelect={onVendorSelect}
+ onMigrate={onMigrate}
+ vendor={vlm}/>)
+ }
+ </CatalogList>
+ );
+};
+
+const SoftwareProductListByVendor = ({onAddVSP, selectedVendor, onVendorSelect, onSelectVSP, onSelectVLM, filter, onMigrate}) => {
+ return(
+ <div>
+ <CatalogList onAddVSP={()=>{onAddVSP(selectedVendor.id);}} vendorPageOptions={{selectedVendor, onBack: () => onVendorSelect(false)}}>
+ <CatalogItemDetails
+ key={selectedVendor.id}
+ onSelect={() => onSelectVLM(selectedVendor)}
+ catalogItemTypeClass={catalogItemTypeClasses.LICENSE_MODEL}
+ onMigrate={onMigrate}
+ catalogItemData={{...selectedVendor, name: selectedVendor.vendorName}}/>
+ {
+ filterCatalogItemsByType(selectedVendor.softwareProductList, catalogItemTypes.SOFTWARE_PRODUCT, filter).map(vsp =>
+ <CatalogItemDetails
+ key={vsp.id}
+ catalogItemTypeClass={catalogItemTypeClasses.SOFTWARE_PRODUCT}
+ onMigrate={onMigrate}
+ onSelect={() => onSelectVSP(vsp)}
+ catalogItemData={vsp}/>
+ )
+ }
+ </CatalogList>
+ </div>
+ );
+};
+
+class VendorCatalogView extends React.Component {
+ render() {
+ let {selectedVendor} = this.props;
+ return( selectedVendor ? <SoftwareProductListByVendor {...this.props}/> : <VendorList {...this.props}/>);
+ }
+}
+
+export default VendorCatalogView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx
new file mode 100644
index 0000000000..cecccdd9ad
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx
@@ -0,0 +1,96 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import {catalogItemTypeClasses} from './OnboardingCatalogConstants.js';
+import CatalogTile from '../CatalogTile.jsx';
+import classnames from 'classnames';
+import VSPOverlay from './VSPOverlay.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+import tooltip from './Tooltip.jsx';
+
+
+class VendorItem extends React.Component {
+
+ static PropTypes = {
+ softwareProductList: React.PropTypes.array,
+ vendor: React.PropTypes.object,
+ onSelectVSP: React.PropTypes.func,
+ shouldShowOverlay: React.PropTypes.boolm,
+ onVendorSelect: React.PropTypes.func,
+ onAddVSP: React.PropTypes.func,
+ onVSPIconClick: React.PropTypes.func,
+
+ };
+
+ render() {
+ let {vendor, onSelectVSP, shouldShowOverlay, onVendorSelect, onMigrate} = this.props;
+ let {softwareProductList = [], vendorName} = vendor;
+ return (
+ <CatalogTile
+ catalogItemTypeClass={catalogItemTypeClasses.VENDOR}
+ onSelect={() => onVendorSelect(vendor)}>
+ <div className='catalog-tile-top'>
+ <div className='catalog-tile-icon vendor-type'>
+ <div className='icon'><SVGIcon name='vendor'/></div>
+ </div>
+ <OverlayTrigger placement='top' overlay={tooltip(vendorName)}>
+ <div className='catalog-tile-item-name'>{vendorName}</div>
+ </OverlayTrigger>
+ <div
+ className={classnames('catalog-tile-vsp-count', {active: shouldShowOverlay}, {clickable: softwareProductList.length})}
+ onClick={(event) => this.handleVspCountClick(event)}
+ data-test-id='catalog-vsp-count'>
+ {i18n(`${softwareProductList.length} VSPs`)}
+ </div>
+ <div className='catalog-tile-content' onClick={(event) => this.onCreateVspClick(event)} data-test-id='catalog-create-new-vsp-from-vendor'>
+ <div className='create-new-vsp-button'>
+ <SVGIcon name='plus'/>&nbsp;&nbsp;&nbsp;{i18n('Create new VSP')}
+ </div>
+ </div>
+ </div>
+
+ {shouldShowOverlay && softwareProductList.length > 0
+ && <VSPOverlay onMigrate={onMigrate} VSPList={softwareProductList} onSelectVSP={onSelectVSP} onSeeMore={() => onVendorSelect(vendor)}/>}
+ </CatalogTile>
+ );
+ }
+
+ onClick(vlm) {
+ this.setState({
+ licenseModelToShow: vlm
+ });
+ }
+
+ onCreateVspClick(event) {
+ let {onAddVSP, vendor: {id}} = this.props;
+ event.stopPropagation();
+ event.preventDefault();
+ onAddVSP(id);
+ }
+
+ handleVspCountClick(e){
+ let {onVSPIconClick, vendor: {softwareProductList}} = this.props;
+ e.stopPropagation();
+ e.preventDefault();
+ const hasVSP = Boolean(softwareProductList.length);
+ onVSPIconClick(hasVSP);
+ }
+
+}
+
+export default VendorItem;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx
new file mode 100644
index 0000000000..d86b674f13
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceView.jsx
@@ -0,0 +1,57 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import DetailsCatalogView from '../DetailsCatalogView.jsx';
+import {statusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {tabsMapping} from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+
+const WorkspaceView = (props) => {
+ let {
+ licenseModelList, softwareProductList, onAddLicenseModelClick,
+ onAddSoftwareProductClick, onSelectLicenseModel, onSelectSoftwareProduct, searchValue, onMigrate
+ } = props;
+
+ let {getCheckOutStatusKindByUserID} = VersionControllerUtils;
+ let unfinalizedLicenseModelList = licenseModelList.filter(vlm => {
+ let {status} = getCheckOutStatusKindByUserID(vlm.status, vlm.lockingUser);
+ return status !== statusEnum.SUBMIT_STATUS && status !== statusEnum.LOCK_STATUS;
+ });
+ let unfinalizedSoftwareProductList = softwareProductList.filter(vsp =>{
+ let {status} = getCheckOutStatusKindByUserID(vsp.status, vsp.lockingUser);
+ return status !== statusEnum.SUBMIT_STATUS && status !== statusEnum.LOCK_STATUS;
+ });
+
+ return (
+ <div className='catalog-wrapper workspace-view'>
+ <div className='catalog-header workspace-header'>
+ {i18n('WORKSPACE')}
+ </div>
+ <DetailsCatalogView
+ VLMList={unfinalizedLicenseModelList}
+ VSPList={unfinalizedSoftwareProductList}
+ onAddVLM={onAddLicenseModelClick}
+ onAddVSP={onAddSoftwareProductClick}
+ onSelectVLM={onSelectLicenseModel}
+ onSelectVSP={onSelectSoftwareProduct}
+ onMigrate={onMigrate}
+ filter={searchValue}
+ tileType={tabsMapping.WORKSPACE} />
+ </div>);
+};
+
+export default WorkspaceView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js
new file mode 100644
index 0000000000..396f65f5d7
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/FinalizedSoftwareProductReducer.js
@@ -0,0 +1,25 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './SoftwareProductConstants.js';
+
+export default (state = [], action) => {
+ 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 2dbef6baf2..12f68a2afe 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
@@ -1,36 +1,40 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import {statusEnum as versionStatusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx';
import {enums} from 'sdc-app/onboarding/OnboardingConstants.js';
import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
-import {navigationItems} from './SoftwareProductConstants.js';
+import {navigationItems, mapScreenToNavigationItem} from './SoftwareProductConstants.js';
import SoftwareProductActionHelper from './SoftwareProductActionHelper.js';
import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js';
+import SoftwareProductDependenciesActionHelper from './dependencies/SoftwareProductDependenciesActionHelper.js';
+import {doesHeatDataExist} from './attachments/SoftwareProductAttachmentsUtils.js';
+
+import HeatSetupActionHelper from './attachments/setup/HeatSetupActionHelper.js';
+import { actionsEnum as versionControllerActions } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+
+function getActiveNavigationId(screen, componentId) {
+ let activeItemId = componentId ? mapScreenToNavigationItem[screen] + '|' + componentId : mapScreenToNavigationItem[screen];
+ return activeItemId;
+}
const buildComponentNavigationBarGroups = ({componentId, meta}) => {
const groups = ([
@@ -106,6 +110,18 @@ const buildNavigationBarProps = ({softwareProduct, meta, screen, componentId, co
id: navigationItems.ATTACHMENTS,
name: i18n('Attachments'),
disabled: false,
+ hidden: !doesHeatDataExist(meta.heatSetup),
+ meta
+ }, {
+ id: navigationItems.ACTIVITY_LOG,
+ name: i18n('Activity Log'),
+ disabled: false,
+ meta
+ }, {
+ id: navigationItems.DEPENDENCIES,
+ name: i18n('Component Dependencies'),
+ hidden: componentsList.length <= 1,
+ disabled: false,
meta
}, {
id: navigationItems.COMPONENTS,
@@ -125,29 +141,7 @@ const buildNavigationBarProps = ({softwareProduct, meta, screen, componentId, co
}
]
}];
- let activeItemId = ({
- [enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE]: navigationItems.VENDOR_SOFTWARE_PRODUCT,
- [enums.SCREEN.SOFTWARE_PRODUCT_DETAILS]: navigationItems.GENERAL,
- [enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS]: navigationItems.ATTACHMENTS,
- [enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES]: navigationItems.PROCESS_DETAILS,
- [enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS]: navigationItems.NETWORKS,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: navigationItems.COMPONENTS
- })[screen];
-
- if(componentId) {
- activeItemId =
- Object.keys(mapOfExpandedIds).length === 1 && mapOfExpandedIds[navigationItems.COMPONENTS] === true ?
- navigationItems.COMPONENTS : ({
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL]: navigationItems.GENERAL,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE]: navigationItems.COMPUTE,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING]: navigationItems.LOAD_BALANCING,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK]: navigationItems.NETWORKS,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE]: navigationItems.STORAGE,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES]: navigationItems.PROCESS_DETAILS,
- [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING]: navigationItems.MONITORING
- })[screen] + '|' + componentId;
- }
-
+ let activeItemId = getActiveNavigationId(screen, componentId);
return {
activeItemId, groups
};
@@ -158,9 +152,7 @@ const buildVersionControllerProps = (softwareProduct) => {
const {data: currentSoftwareProduct = {}, isValidityData = true} = softwareProductEditor;
const {version, viewableVersions, status: currentStatus, lockingUser} = currentSoftwareProduct;
- const {status, isCheckedOut} = (currentStatus === versionStatusEnum.CHECK_OUT_STATUS) ?
- VersionControllerUtils.getCheckOutStatusKindByUserID(currentStatus, lockingUser) :
- {status: currentStatus, isCheckedOut: false};
+ const {status, isCheckedOut} = VersionControllerUtils.getCheckOutStatusKindByUserID(currentStatus, lockingUser);
return {
status, isCheckedOut, version, viewableVersions,
@@ -168,42 +160,56 @@ const buildVersionControllerProps = (softwareProduct) => {
};
};
-const mapStateToProps = ({softwareProduct}, {currentScreen: {screen, props: {componentId}}}) => {
- const {softwareProductEditor, softwareProductComponents, softwareProductQuestionnaire} = softwareProduct;
- const {data: currentSoftwareProduct = {}, mapOfExpandedIds = []} = softwareProductEditor;
+function buildMeta({softwareProduct, componentId, softwareProductDependencies}) {
+ const {softwareProductEditor, softwareProductComponents, softwareProductQuestionnaire, softwareProductAttachments} = softwareProduct;
+ const {data: currentSoftwareProduct = {}} = softwareProductEditor;
const {version} = currentSoftwareProduct;
- const {componentsList = []} = softwareProductComponents;
const isReadOnlyMode = VersionControllerUtils.isReadOnly(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, isReadOnlyMode, currentComponentMeta};
+ const meta = {softwareProduct: currentSoftwareProduct, qdata, version, heatSetup, heatSetupCache, isReadOnlyMode, currentComponentMeta, softwareProductDependencies};
+ return meta;
+}
+
+const mapStateToProps = ({softwareProduct}, {currentScreen: {screen, props: {componentId}}}) => {
+ const {softwareProductEditor, softwareProductComponents, softwareProductDependencies} = softwareProduct;
+ const {mapOfExpandedIds = []} = softwareProductEditor;
+ const {componentsList = []} = softwareProductComponents;
+ const meta = buildMeta({softwareProduct, componentId, softwareProductDependencies});
return {
versionControllerProps: buildVersionControllerProps(softwareProduct),
- navigationBarProps: buildNavigationBarProps({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds})
+ navigationBarProps: buildNavigationBarProps({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds}),
+ meta
};
};
-const autoSaveBeforeNavigate = ({dispatch, screen, softwareProductId, componentId, meta: {isReadOnlyMode, softwareProduct, qdata, currentComponentMeta: {componentData, componentQdata}}}) => {
+const autoSaveBeforeNavigate = ({dispatch, screen, softwareProductId, componentId,
+ meta: {isReadOnlyMode, softwareProduct, version, qdata, softwareProductDependencies,
+ currentComponentMeta: {componentData, componentQdata}}}) => {
let promise;
if (isReadOnlyMode) {
promise = Promise.resolve();
} else {
switch(screen) {
+ case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
+ promise = SoftwareProductDependenciesActionHelper.saveDependencies(dispatch,{softwareProductId, version, dependenciesList: softwareProductDependencies});
case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
promise = SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, qdata});
break;
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
- promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId: componentId, componentData, qdata: componentQdata});
+ 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_LOAD_BALANCING:
- promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, vspComponentId: componentId, qdata: componentQdata});
+ promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata: componentQdata});
break;
default:
promise = Promise.resolve();
@@ -228,22 +234,22 @@ const onComponentNavigate = (dispatch, {id, softwareProductId, version, currentC
OnboardingActionHelper.navigateToSoftwareProductComponentGeneral(dispatch, {softwareProductId, componentId: nextComponentId, version});
break;
case navigationItems.COMPUTE:
- OnboardingActionHelper.navigateToComponentCompute(dispatch, {softwareProductId, componentId: nextComponentId});
+ OnboardingActionHelper.navigateToComponentCompute(dispatch, {softwareProductId, componentId: nextComponentId, version});
break;
case navigationItems.LOAD_BALANCING:
- OnboardingActionHelper.navigateToComponentLoadBalancing(dispatch, {softwareProductId, componentId: nextComponentId});
+ OnboardingActionHelper.navigateToComponentLoadBalancing(dispatch, {softwareProductId, componentId: nextComponentId, version});
break;
case navigationItems.NETWORKS:
OnboardingActionHelper.navigateToComponentNetwork(dispatch, {softwareProductId, componentId: nextComponentId, version});
break;
case navigationItems.STORAGE:
- OnboardingActionHelper.navigateToComponentStorage(dispatch, {softwareProductId, componentId: nextComponentId});
+ OnboardingActionHelper.navigateToComponentStorage(dispatch, {softwareProductId, componentId: nextComponentId, version});
break;
case navigationItems.PROCESS_DETAILS:
- OnboardingActionHelper.navigateToSoftwareProductComponentProcesses(dispatch, {softwareProductId, componentId: nextComponentId});
+ OnboardingActionHelper.navigateToSoftwareProductComponentProcesses(dispatch, {softwareProductId, componentId: nextComponentId, version});
break;
case navigationItems.MONITORING:
- OnboardingActionHelper.navigateToSoftwareProductComponentMonitoring(dispatch, {softwareProductId, componentId: nextComponentId});
+ OnboardingActionHelper.navigateToSoftwareProductComponentMonitoring(dispatch, {softwareProductId, componentId: nextComponentId, version});
break;
}
};
@@ -251,44 +257,49 @@ const onComponentNavigate = (dispatch, {id, softwareProductId, version, currentC
const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {softwareProductId, componentId: currentComponentId}}}) => {
const props = {
- onClose: ({version}) => {
- if (screen === enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE) {
- OnboardingActionHelper.navigateToOnboardingCatalog(dispatch);
- } else {
- OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version});
- }
- },
- onVersionSwitching: (version) => {
- OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version});
+ onVersionSwitching: (version, meta) => {
+ SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version});
+ props.onNavigate({id: getActiveNavigationId(screen, currentComponentId), meta, version});
},
onToggle: (groups, itemIdToExpand) => groups.map(({items}) => SoftwareProductActionHelper.toggleNavigationItems(dispatch, {items, itemIdToExpand})),
- onNavigate: ({id, meta}) => {
- let preNavigate = autoSaveBeforeNavigate({dispatch, screen, meta, softwareProductId, componentId: currentComponentId});
- preNavigate.then(() => {
+ onNavigate: ({id, meta, version}) => {
+ let {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, softwareProductId, componentId: currentComponentId}) : Promise.resolve();
+ version = version || (meta ? meta.version : undefined);
+ Promise.all([preNavigate, heatSetupPopupPromise]).then(() => {
switch(id) {
case navigationItems.VENDOR_SOFTWARE_PRODUCT:
- OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version: meta.version});
+ OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, version});
break;
case navigationItems.GENERAL:
- OnboardingActionHelper.navigateToSoftwareProductDetails(dispatch, {softwareProductId});
+ OnboardingActionHelper.navigateToSoftwareProductDetails(dispatch, {softwareProductId, version});
break;
case navigationItems.PROCESS_DETAILS:
- OnboardingActionHelper.navigateToSoftwareProductProcesses(dispatch, {softwareProductId, version: meta.version});
+ OnboardingActionHelper.navigateToSoftwareProductProcesses(dispatch, {softwareProductId, version});
break;
case navigationItems.NETWORKS:
- OnboardingActionHelper.navigateToSoftwareProductNetworks(dispatch, {softwareProductId, version: meta.version});
+ OnboardingActionHelper.navigateToSoftwareProductNetworks(dispatch, {softwareProductId, version});
+ break;
+ case navigationItems.DEPENDENCIES:
+ OnboardingActionHelper.navigateToSoftwareProductDependencies(dispatch, {softwareProductId, version});
break;
case navigationItems.ATTACHMENTS:
- OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId});
+ OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId, version});
break;
case navigationItems.COMPONENTS:
- OnboardingActionHelper.navigateToSoftwareProductComponents(dispatch, {softwareProductId});
+ OnboardingActionHelper.navigateToSoftwareProductComponents(dispatch, {softwareProductId, version});
+ break;
+ case navigationItems.ACTIVITY_LOG:
+ OnboardingActionHelper.navigateToSoftwareProductActivityLog(dispatch, {softwareProductId, version});
break;
default:
- onComponentNavigate(dispatch, {id, softwareProductId, version: meta.version, screen, currentComponentId});
+ onComponentNavigate(dispatch, {id, softwareProductId, version, screen, currentComponentId});
break;
}
- });
+ }).catch(() => {});
}
};
@@ -297,6 +308,8 @@ const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {softwarePr
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_COMPONENT_PROCESSES:
case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
@@ -310,11 +323,20 @@ const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {softwarePr
}
- props.onVersionControllerAction = (action) =>
- SoftwareProductActionHelper.performVCAction(dispatch, {softwareProductId, action}).then(() => {
- SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId});
- });
-
+ props.onVersionControllerAction = (action, version, meta) => {
+ let {heatSetup, heatSetupCache} = meta;
+ let heatSetupPopupPromise = screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS && action === versionControllerActions.CHECK_IN ?
+ HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) :
+ Promise.resolve();
+ heatSetupPopupPromise.then(() => {
+ return SoftwareProductActionHelper.performVCAction(dispatch, {softwareProductId, action, version}).then(({newVersion}) => {
+ //props.onNavigate({id: getActiveNavigationId(screen, currentComponentId), version});
+ if(screen === enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG) {
+ OnboardingActionHelper.navigateToSoftwareProductActivityLog(dispatch, {softwareProductId, version: newVersion});
+ }
+ });
+ }).catch(() => {});
+ };
return props;
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
index d9ed8af679..6f53886350 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -26,10 +21,17 @@ import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licens
import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
import {actionTypes} from './SoftwareProductConstants.js';
-import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.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 ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import {PRODUCT_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import {statusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
function baseUrl() {
const restPrefix = Configuration.get('restPrefix');
@@ -40,46 +42,58 @@ function softwareProductCategoriesUrl() {
return `${restATTPrefix}/v1/categories/resources/`;
}
-function uploadFile(vspId, formData) {
-
- return RestAPIUtil.create(`${baseUrl()}${vspId}/upload`, formData);
+function uploadFile(vspId, formData, version) {
+ return RestAPIUtil.post(`${baseUrl()}${vspId}/versions/${version.id}/orchestration-template-candidate`, formData);
}
-function putSoftwareProduct(softwareData) {
- return RestAPIUtil.save(`${baseUrl()}${softwareData.id}`, {
- name: softwareData.name,
- description: softwareData.description,
- category: softwareData.category,
- subCategory: softwareData.subCategory,
- vendorId: softwareData.vendorId,
- vendorName: softwareData.vendorName,
- licensingVersion: softwareData.licensingVersion,
- icon: softwareData.icon,
- licensingData: softwareData.licensingData
+function putSoftwareProduct(softwareProduct) {
+ return RestAPIUtil.put(`${baseUrl()}${softwareProduct.id}/versions/${softwareProduct.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.id ? softwareProduct.licensingVersion : {} ,
+ icon: softwareProduct.icon,
+ licensingData: softwareProduct.licensingData
});
}
-function putSoftwareProductQuestionnaire(vspId, qdata) {
- return RestAPIUtil.save(`${baseUrl()}${vspId}/questionnaire`, qdata);
+function putSoftwareProductQuestionnaire(vspId, qdata, version) {
+ return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/questionnaire`, qdata);
}
-function putSoftwareProductAction(id, action) {
- return RestAPIUtil.save(`${baseUrl()}${id}/actions`, {action: action});
+function putSoftwareProductAction(id, action, version) {
+ return RestAPIUtil.put(`${baseUrl()}${id}/versions/${version.id}/actions`, {action: action});
}
function fetchSoftwareProductList() {
return RestAPIUtil.fetch(baseUrl());
}
+function fetchFinalizedSoftwareProductList() {
+ return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=Final`);
+}
+
function fetchSoftwareProduct(vspId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl()}${vspId}${versionQuery}`);
+ return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}`);
}
function fetchSoftwareProductQuestionnaire(vspId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl()}${vspId}/questionnaire${versionQuery}`);
+ 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 validateHeatCandidate(softwareProductId, version) {
+ 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 objToString(obj) {
@@ -88,7 +102,8 @@ function objToString(obj) {
obj.forEach((item) => {
str += objToString(item) + '\n';
});
- } else {
+ }
+ else {
for (let p in obj) {
if (obj.hasOwnProperty(p)) {
str += obj[p] + '\n';
@@ -115,24 +130,27 @@ function fetchSoftwareProductCategories(dispatch) {
});
return RestAPIUtil.fetch(softwareProductCategoriesUrl())
.then(handleResponse)
- .fail(() => handleResponse(null));
+ .catch(() => handleResponse(null));
}
function loadLicensingData(dispatch, {licenseModelId, licensingVersion}) {
- LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: licensingVersion});
- FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version: licensingVersion});
+ return Promise.all([
+ LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: licensingVersion}),
+ FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version: licensingVersion})
+ ]);
}
function getExpandedItemsId(items, itemIdToToggle) {
- for(let i = 0; i < items.length; i++) {
- if(items[i].id === itemIdToToggle) {
+ for (let i = 0; i < items.length; i++) {
+ if (items[i].id === itemIdToToggle) {
if (items[i].expanded) {
return {};
- } else {
+ }
+ else {
return {[itemIdToToggle]: true};
}
}
- else if(items[i].items && items[i].items.length > 0) {
+ 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;
@@ -143,8 +161,63 @@ function getExpandedItemsId(items, itemIdToToggle) {
return false;
}
+function getTimestampString() {
+ let date = new Date();
+ let z = n => n < 10 ? '0' + n : n;
+ return `${date.getFullYear()}-${z(date.getMonth())}-${z(date.getDate())}_${z(date.getHours())}-${z(date.getMinutes())}`;
+}
+
+function showFileSaveDialog({blob, xhr, defaultFilename, addTimestamp}) {
+ let filename;
+ let contentDisposition = xhr.getResponseHeader('content-disposition') ? xhr.getResponseHeader('content-disposition') : '';
+ let match = contentDisposition.match(/filename=(.*?)(;|$)/);
+ if (match) {
+ filename = match[1];
+ }
+ else {
+ filename = defaultFilename;
+ }
+
+ if (addTimestamp) {
+ filename = filename.replace(/(^.*?)\.([^.]+$)/, `$1_${getTimestampString()}.$2`);
+ }
+
+ let link = document.createElement('a');
+ let url = URL.createObjectURL(blob);
+ link.href = url;
+ link.download = filename;
+ link.style.display = 'none';
+ document.body.appendChild(link);
+ link.click();
+ setTimeout(function(){
+ document.body.removeChild(link);
+ URL.revokeObjectURL(url);
+ }, 0);
+}
+
+function migrateSoftwareProduct(vspId, version) {
+ return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/heal`);
+}
+
+function adjustMinorVersion(version, value) {
+ let ar = version.split('.');
+ return ar[0] + '.' + (parseInt(ar[1]) + value);
+}
+
+function adjustMajorVersion(version, value) {
+ let ar = version.split('.');
+ return (parseInt(ar[0]) + value) + '.0';
+}
+
const SoftwareProductActionHelper = {
+ fetchFinalizedSoftwareProductList(dispatch) {
+ return fetchFinalizedSoftwareProductList().then(response => dispatch({
+ type: actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED,
+ response
+ }));
+ },
+
loadSoftwareProductAssociatedData(dispatch) {
fetchSoftwareProductCategories(dispatch);
LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
@@ -152,7 +225,7 @@ const SoftwareProductActionHelper = {
loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion}) {
SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
- loadLicensingData(dispatch, {licenseModelId, licensingVersion});
+ return loadLicensingData(dispatch, {licenseModelId, licensingVersion});
},
fetchSoftwareProductList(dispatch) {
@@ -162,37 +235,61 @@ const SoftwareProductActionHelper = {
}));
},
- uploadFile(dispatch, {softwareProductId, formData, failedNotificationTitle}) {
+ loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version}){
+ return RestAPIUtil.fetch(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/manifest`).then(response => dispatch({
+ type: HeatSetupActions.MANIFEST_LOADED,
+ response
+ }));
+ },
+
+ 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});
+ }
+ });
+ },
+
+ uploadFile(dispatch, {softwareProductId, formData, failedNotificationTitle, version}) {
+ dispatch({
+ type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
+ payload: {}
+ });
+
Promise.resolve()
- .then(() => uploadFile(softwareProductId, formData))
+ .then(() => uploadFile(softwareProductId, formData, version))
.then(response => {
- if (response.status !== 'Success') {
+ if (response.status === 'Success') {
+ OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId, version});
+ }
+ else {
throw new Error(parseUploadErrorMsg(response.errors));
}
})
- .then(() => {
- SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId});
- OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId});
- SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId});
- })
.catch(error => {
dispatch({
- type: NotificationConstants.NOTIFY_ERROR,
- data: {title: failedNotificationTitle, msg: error.message}
+ type: modalActionTypes.GLOBAL_MODAL_ERROR,
+ data: {
+ title: failedNotificationTitle,
+ msg: error.message
+ }
});
});
},
- uploadConfirmation(dispatch, {softwareProductId, formData, failedNotificationTitle}) {
- dispatch({
- type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION,
- uploadData: {
- softwareProductId,
- formData,
- failedNotificationTitle
- }
- });
+ downloadHeatFile(dispatch, {softwareProductId, heatCandidate, isReadOnlyMode, version}){
+ let p = isReadOnlyMode ? Promise.resolve() : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version});
+ p.then(() => {
+ fetchOrchestrationTemplateCandidate(softwareProductId, version)
+ .then((blob, statusText, xhr) => showFileSaveDialog({blob, xhr, defaultFilename: 'HEAT_file.zip', addTimestamp: true}));
+ }, null/* do not download if data was not saved correctly*/);
},
+
hideUploadConfirm (dispatch) {
dispatch({
type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION
@@ -208,7 +305,8 @@ const SoftwareProductActionHelper = {
),
SoftwareProductActionHelper.updateSoftwareProductQuestionnaire(dispatch, {
softwareProductId: softwareProduct.id,
- qdata
+ qdata,
+ version: softwareProduct.version
})
]);
},
@@ -217,8 +315,8 @@ const SoftwareProductActionHelper = {
return putSoftwareProduct(softwareProduct);
},
- updateSoftwareProductQuestionnaire(dispatch, {softwareProductId, qdata}) {
- return putSoftwareProductQuestionnaire(softwareProductId, qdata);
+ updateSoftwareProductQuestionnaire(dispatch, {softwareProductId, qdata, version}) {
+ return putSoftwareProductQuestionnaire(softwareProductId, qdata, version);
},
softwareProductEditorDataChanged(dispatch, {deltaData}) {
@@ -235,10 +333,34 @@ const SoftwareProductActionHelper = {
});
},
- softwareProductEditorVendorChanged(dispatch, {deltaData}) {
- LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId: deltaData.vendorId, version: deltaData.licensingVersion});
- FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId: deltaData.vendorId, version: deltaData.licensingVersion});
- SoftwareProductActionHelper.softwareProductEditorDataChanged(dispatch, {deltaData});
+ softwareProductEditorVendorChanged(dispatch, {deltaData, formName}) {
+ if (deltaData.licensingVersion.id){
+ let p = Promise.all([
+ LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {
+ licenseModelId: deltaData.vendorId,
+ version: {id: deltaData.licensingVersion.id}
+ }),
+ FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
+ licenseModelId: deltaData.vendorId,
+ version: {id: deltaData.licensingVersion.id}
+ })
+ ]);
+ ValidationHelper.dataChanged(dispatch, {deltaData, formName});
+ return p;
+ } 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}) {
@@ -265,55 +387,67 @@ const SoftwareProductActionHelper = {
return response;
}),
fetchSoftwareProductQuestionnaire(softwareProductId, version).then(response => {
- dispatch({
- type: actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE,
- payload: {
- qdata: response.data ? JSON.parse(response.data) : {},
- qschema: JSON.parse(response.schema)
- }
- });
+ ValidationHelper.qDataLoaded(dispatch, {response: {qdata: response.data ? JSON.parse(response.data) : {},
+ qschema: JSON.parse(response.schema)}, qName: PRODUCT_QUESTIONNAIRE});
})
]);
},
- performVCAction(dispatch, {softwareProductId, action}) {
+ performVCAction(dispatch, {softwareProductId, action, version}) {
if (action === VersionControllerActionsEnum.SUBMIT) {
- return putSoftwareProductAction(softwareProductId, action).then(() => {
- return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.CREATE_PACKAGE).then(() => {
+ return putSoftwareProductAction(softwareProductId, action, version).then(() => {
+ return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.CREATE_PACKAGE, version).then(() => {
dispatch({
- type: NotificationConstants.NOTIFY_SUCCESS,
+ type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
data: {
title: i18n('Submit Succeeded'),
msg: i18n('This software product successfully submitted'),
+ cancelButtonText: i18n('OK'),
timeout: 2000
}
});
- fetchSoftwareProduct(softwareProductId).then(response => {
- dispatch({
- type: actionTypes.SOFTWARE_PRODUCT_LOADED,
- response
- });
- });
+ const newVersionId = adjustMajorVersion(version.label, 1);
+ SoftwareProductActionHelper.fetchSoftwareProduct(dispatch,{softwareProductId, version: {id: newVersionId}});
+ return Promise.resolve({newVersion: {id: newVersionId}});
});
}, error => dispatch({
- type: NotificationConstants.NOTIFY_ERROR,
- data: {title: i18n('Submit Failed'), validationResponse: error.responseJSON}
+ type: modalActionTypes.GLOBAL_MODAL_ERROR,
+ data: {
+ modalComponentName: modalContentMapper.SUMBIT_ERROR_RESPONSE,
+ title: i18n('Submit Failed'),
+ modalComponentProps: {
+ validationResponse: error.responseJSON
+ },
+ cancelButtonText: i18n('Ok')
+ }
}));
}
else {
- return putSoftwareProductAction(softwareProductId, action).then(() => {
- fetchSoftwareProduct(softwareProductId).then(response => {
- dispatch({
- type: actionTypes.SOFTWARE_PRODUCT_LOADED,
- response
- });
- });
+ return putSoftwareProductAction(softwareProductId, action, version).then(() => {
+ let newVersionId = version.id;
+ /*
+ TODO Temorary switch to change version label
+ */
+ switch(action) {
+ case VersionControllerActionsEnum.CHECK_OUT:
+ newVersionId = adjustMinorVersion(version.label, 1);
+ break;
+ case VersionControllerActionsEnum.UNDO_CHECK_OUT:
+ newVersionId = adjustMinorVersion(version.label, -1);
+ break;
+ }
+ SoftwareProductActionHelper.fetchSoftwareProduct(dispatch,{softwareProductId, version:{id: newVersionId}});
+ return Promise.resolve({newVersion: {id: newVersionId}});
});
}
},
switchVersion(dispatch, {softwareProductId, licenseModelId, version}) {
- OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, licenseModelId, version});
+ OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {
+ softwareProductId,
+ licenseModelId,
+ version
+ });
},
toggleNavigationItems(dispatch, {items, itemIdToExpand}) {
@@ -327,7 +461,17 @@ const SoftwareProductActionHelper = {
/** for the next verision */
addComponent(dispatch) {
return dispatch;
+ },
+
+ migrateSoftwareProduct(dispatch, {softwareProduct}) {
+ let {licenseModelId, licensingVersion, id: softwareProductId, version, status} = softwareProduct;
+ const newVer = status === statusEnum.CHECK_IN_STATUS || status === statusEnum.SUBMIT_STATUS ?
+ adjustMinorVersion(version.id, 1) : version.id;
+ migrateSoftwareProduct(softwareProductId, version)
+ .then(() =>OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch,
+ {softwareProductId, version: {id: newVer, label: newVer}, licenseModelId, licensingVersion}));
}
+
};
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 812afe5409..9b147415f9 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
export default {
getCurrentCategoryOfSubCategory(selectedSubCategory, softwareProductCategories) {
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js
index 5f10c27084..f29b0f6e0d 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js
@@ -1,28 +1,25 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
+import {enums} from 'sdc-app/onboarding/OnboardingConstants.js';
export const actionTypes = keyMirror({
SOFTWARE_PRODUCT_LOADED: null,
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,
@@ -33,21 +30,46 @@ export const actionTypes = keyMirror({
OPEN: null,
CLOSE: null,
DATA_CHANGED: null,
- IS_VALIDITY_DATA_CHANGED: null,
- UPLOAD_CONFIRMATION: null
+ IS_VALIDITY_DATA_CHANGED: null
}
});
export const navigationItems = keyMirror({
- VENDOR_SOFTWARE_PRODUCT: 'Vendor Software Product',
- GENERAL: 'General',
- PROCESS_DETAILS: 'Process Details',
- NETWORKS: 'Networks',
- ATTACHMENTS: 'Attachments',
- COMPONENTS: 'Components',
+ VENDOR_SOFTWARE_PRODUCT: 'vendor-software-product',
+ GENERAL: 'general',
+ PROCESS_DETAILS: 'process-details',
+ NETWORKS: 'networks',
+ DEPENDENCIES: 'dependencies',
+ ATTACHMENTS: 'attachments',
+ ACTIVITY_LOG: 'activity-log',
+ COMPONENTS: 'components',
+
+ COMPUTE: 'compute',
+ LOAD_BALANCING: 'load-balancing',
+ STORAGE: 'storage',
+ MONITORING: 'monitoring'
+});
- COMPUTE: 'Compute',
- LOAD_BALANCING: 'Load Balancing',
- STORAGE: 'Storage',
- MONITORING: 'Monitoring'
+export const forms = keyMirror({
+ VENDOR_SOFTWARE_PRODUCT_DETAILS: 'vendor-software-product-details',
});
+
+export const PRODUCT_QUESTIONNAIRE = 'product';
+
+export const mapScreenToNavigationItem = {
+ [enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE]: navigationItems.VENDOR_SOFTWARE_PRODUCT,
+ [enums.SCREEN.SOFTWARE_PRODUCT_DETAILS]: navigationItems.GENERAL,
+ [enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS]: navigationItems.ATTACHMENTS,
+ [enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES]: navigationItems.PROCESS_DETAILS,
+ [enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS]: navigationItems.NETWORKS,
+ [enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG]: navigationItems.ACTIVITY_LOG,
+ [enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES]: navigationItems.DEPENDENCIES,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS]: navigationItems.COMPONENTS,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL]: navigationItems.GENERAL,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE]: navigationItems.COMPUTE,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING]: navigationItems.LOAD_BALANCING,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK]: navigationItems.NETWORKS,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE]: navigationItems.STORAGE,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES]: navigationItems.PROCESS_DETAILS,
+ [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING]: navigationItems.MONITORING,
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js
index 6d1db1626f..2fde8c2216 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductConstants.js';
export default (state = [], action) => {
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js
index 784ac9db84..97988d87f9 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js
@@ -1,26 +1,23 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {combineReducers} from 'redux';
-import {actionTypes} from './SoftwareProductConstants.js';
-import SoftwareProductAttachmentsReducer from './attachments/SoftwareProductAttachmentsReducer.js';
+import {actionTypes, PRODUCT_QUESTIONNAIRE} from './SoftwareProductConstants.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 SoftwareProductCreationReducer from './creation/SoftwareProductCreationReducer.js';
import SoftwareProductDetailsReducer from './details/SoftwareProductDetailsReducer.js';
import SoftwareProductProcessesListReducer from './processes/SoftwareProductProcessesListReducer.js';
@@ -35,30 +32,40 @@ import {actionTypes as componentProcessesActionTypes} from './components/proces
import SoftwareProductComponentsNICListReducer from './components/network/SoftwareProductComponentsNICListReducer.js';
import SoftwareProductComponentsNICEditorReducer from './components/network/SoftwareProductComponentsNICEditorReducer.js';
import SoftwareProductComponentsMonitoringReducer from './components/monitoring/SoftwareProductComponentsMonitoringReducer.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} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
export default combineReducers({
- softwareProductAttachments: SoftwareProductAttachmentsReducer,
- softwareProductCreation: SoftwareProductCreationReducer,
- softwareProductEditor: SoftwareProductDetailsReducer,
+ softwareProductAttachments: combineReducers({
+ 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: SoftwareProductProcessesEditorReducer,
+ processesEditor: createPlainDataReducer(SoftwareProductProcessesEditorReducer),
processToDelete: (state = false, action) => action.type === processesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM ? action.processToDelete : state
}),
softwareProductNetworks: combineReducers({
networksList: SoftwareProductNetworksListReducer
}),
+ softwareProductDependencies: SoftwareProductDependenciesReducer,
softwareProductComponents: combineReducers({
componentsList: SoftwareProductComponentsListReducer,
- componentEditor: SoftwareProductComponentEditorReducer,
+ componentEditor: createPlainDataReducer(createComposedJSONSchemaReducer(COMPONENTS_QUESTIONNAIRE, SoftwareProductComponentEditorReducer)),
componentProcesses: combineReducers({
processesList: SoftwareProductComponentProcessesListReducer,
- processesEditor: SoftwareProductComponentProcessesEditorReducer,
+ processesEditor: createPlainDataReducer(SoftwareProductComponentProcessesEditorReducer),
processToDelete: (state = false, action) => action.type === componentProcessesActionTypes.SOFTWARE_PRODUCT_PROCESS_DELETE_COMPONENTS_CONFIRM ? action.processToDelete : state,
}),
network: combineReducers({
nicList: SoftwareProductComponentsNICListReducer,
- nicEditor: SoftwareProductComponentsNICEditorReducer
+ nicEditor: createPlainDataReducer(createComposedJSONSchemaReducer(NIC_QUESTIONNAIRE, SoftwareProductComponentsNICEditorReducer))
}),
monitoring: SoftwareProductComponentsMonitoringReducer
}),
@@ -68,13 +75,5 @@ export default combineReducers({
}
return state;
},
- softwareProductQuestionnaire: (state = {}, action) => {
- if (action.type === actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE) {
- return {
- ...state,
- ...action.payload
- };
- }
- 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 a4b95a4b7e..8f2506abdd 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js
@@ -1,42 +1,89 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+import i18n from 'nfvo-utils/i18n/i18n.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 SoftwareProductAttachmentsActionHelper from './SoftwareProductAttachmentsActionHelper.js';
+import {errorLevels} from 'sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js';
+import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
+import HeatSetup from './setup/HeatSetup.js';
+import {doesHeatDataExist} from './SoftwareProductAttachmentsUtils.js';
+
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+
+export const mapStateToProps = (state) => {
+ let {
+ softwareProduct: {
+ softwareProductEditor:{data: currentSoftwareProduct = {}},
+ softwareProductAttachments: {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);
-export const mapStateToProps = ({softwareProduct: {softwareProductAttachments}}) => {
- let {attachmentsTree, hoveredNode, selectedNode, errorList} = softwareProductAttachments;
+ let isReadOnlyMode = currentSoftwareProduct && currentSoftwareProduct.version ?
+ VersionControllerUtils.isReadOnly(currentSoftwareProduct) : false;
+ let {version} = currentSoftwareProduct;
return {
- attachmentsTree,
- hoveredNode,
- selectedNode,
- errorList
+ isValidationAvailable: unassigned.length === 0 && modules.length > 0,
+ heatSetup,
+ heatSetupCache,
+ heatDataExist,
+ goToOverview,
+ HeatSetupComponent: HeatSetup,
+ isReadOnlyMode,
+ version
};
};
-const mapActionsToProps = (dispatch) => {
+export const mapActionsToProps = (dispatch, {softwareProductId}) => {
return {
- toggleExpanded: (path) => SoftwareProductAttachmentsActionHelper.toggleExpanded(dispatch, {path}),
- onSelectNode: (nodeName) => SoftwareProductAttachmentsActionHelper.onSelectNode(dispatch, {nodeName}),
- onUnselectNode: () => SoftwareProductAttachmentsActionHelper.onUnselectNode(dispatch)
+ onDownload: ({heatCandidate, isReadOnlyMode, version}) => SoftwareProductActionHelper.downloadHeatFile(dispatch, {softwareProductId, heatCandidate, isReadOnlyMode, version}),
+ onUpload: (formData, version) => dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n('Upload will erase existing data. Do you want to continue?'),
+ confirmationButtonText: i18n('Continue'),
+ onConfirmed: ()=>SoftwareProductActionHelper.uploadFile(dispatch, {
+ softwareProductId,
+ formData,
+ failedNotificationTitle: i18n('Upload validation failed'),
+ version
+ })
+ }
+ }),
+ onSave: (heatCandidate, version) => SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version}),
+ onGoToOverview: () => {
+ OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId});
+ },
+ onProcessAndValidate: ({heatData, heatDataCache, isReadOnlyMode, version}) => {
+ return HeatSetupActionHelper.processAndValidateHeat(dispatch,
+ {softwareProductId, heatData, heatDataCache, isReadOnlyMode, version});
+ }
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js
deleted file mode 100644
index a7f7a5173b..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import {actionTypes} from './SoftwareProductAttachmentsConstants.js';
-
-export default {
-
- toggleExpanded(dispatch, {path}) {
- dispatch({
- type: actionTypes.TOGGLE_EXPANDED,
- path
- });
- },
-
- onSelectNode(dispatch, {nodeName}) {
- dispatch({
- type: actionTypes.SELECTED_NODE,
- nodeName
- });
- },
-
- onUnselectNode(dispatch) {
- dispatch({
- type: actionTypes.UNSELECTED_NODE
- });
- }
-};
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 33af476d9c..b0410d1566 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js
@@ -1,55 +1,19 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import keyMirror from 'nfvo-utils/KeyMirror.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-export const actionTypes = keyMirror({
- 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')
-});
-
-export const nodeTypes = keyMirror({
- 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
-});
-
+export const tabsMapping = {
+ SETUP: 1,
+ VALIDATION: 2
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js
deleted file mode 100644
index 5c5567b032..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsReducer.js
+++ /dev/null
@@ -1,199 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-import {actionTypes as softwareProductsActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
-import {actionTypes} from './SoftwareProductAttachmentsConstants.js';
-
-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 mapArtifactsData = ({fileName, errors}) => ({
- name: fileName,
- type: 'artifact',
- 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) : [])
- ]
-});
-
-function createErrorList(node, parent, deep = 0, errorList = []) {
- if (node.errors) {
- errorList.push(...node.errors.map((error) => ({
- errorLevel: 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 => {
- let {HEAT, volume, network, artifacts, other} = validationData.importStructure || {};
- return {
- children: [
- {
- name: 'HEAT',
- expanded: true,
- type: 'heat',
- children: (HEAT ? HEAT.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;
-};
-
-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;
- });
-
- 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;
- let attachmentsTree = currentSoftwareProduct.validationData ? mapValidationDataToTree(currentSoftwareProduct.validationData) : {};
- let errorList = createErrorList(attachmentsTree);
- return {
- ...state,
- attachmentsTree,
- errorList
- };
- 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: undefined
- };
- 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
new file mode 100644
index 0000000000..2e76b11630
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsUtils.js
@@ -0,0 +1,25 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+export function doesHeatDataExist(heatData) {
+ 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 c52999ca46..66fb2f8356 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx
@@ -1,182 +1,119 @@
-import React from 'react';
-import FontAwesome from 'react-fontawesome';
-import classNames from 'classnames';
-import Collapse from 'react-bootstrap/lib/Collapse.js';
-
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component, PropTypes} from 'react';
+import Tabs from 'react-bootstrap/lib/Tabs.js';
+import Tab from 'react-bootstrap/lib/Tab.js';
+import {tabsMapping} from './SoftwareProductAttachmentsConstants.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import {nodeTypes, mouseActions} from './SoftwareProductAttachmentsConstants';
-
-const typeToIcon = Object.freeze({
- heat: 'building-o',
- volume: 'database',
- network: 'cloud',
- artifact: 'gear',
- env: 'server',
- other: 'cube'
-});
+import Icon from 'nfvo-components/icon/Icon.jsx';
+import HeatValidation from './validation/HeatValidation.js';
-const leftPanelWidth = 250;
-
-class SoftwareProductAttachmentsView extends React.Component {
+class HeatScreenView extends Component {
static propTypes = {
- attachmentsTree: React.PropTypes.object.isRequired
+ isValidationAvailable: PropTypes.bool,
+ goToOverview: PropTypes.bool
};
+
state = {
- treeWidth: '400'
+ activeTab: tabsMapping.SETUP
};
render() {
- let {attachmentsTree, errorList} = this.props;
- let {treeWidth} = this.state;
+ let {isValidationAvailable, isReadOnlyMode, heatDataExist, onDownload, softwareProductId, onProcessAndValidate, heatSetup, HeatSetupComponent, onGoToOverview, version, ...other} = this.props;
return (
- <div className='software-product-attachments'>
- <div className='software-product-attachments-tree' style={{'width' : treeWidth + 'px'}}>
- <div className='tree-wrapper'>
- {
- attachmentsTree && attachmentsTree.children && attachmentsTree.children.map((child, ind) => this.renderNode(child, [ind]))
- }
- </div>
+ <div className='vsp-attachments-view'>
+ <div className='attachments-view-controllers'>
+ {(this.state.activeTab === tabsMapping.SETUP) &&
+ <Icon
+ iconClassName={heatDataExist ? '' : 'disabled'}
+ className={heatDataExist ? '' : 'disabled'}
+ image='download'
+ label={i18n('Download HEAT')}
+ onClick={heatDataExist ? () => onDownload({heatCandidate: heatSetup, isReadOnlyMode, version}) : undefined}
+ data-test-id='download-heat'/>}
+ {(this.state.activeTab === tabsMapping.VALIDATION && softwareProductId) &&
+ <Icon
+ iconClassName={this.props.goToOverview ? '' : 'disabled'}
+ className={`go-to-overview-icon ${this.props.goToOverview ? '' : 'disabled'}`}
+ labelClassName='go-to-overview-label'
+ onClick={this.props.goToOverview ? onGoToOverview : undefined}
+ image='go-to-overview'
+ label={i18n('Go to Overview')}
+ data-test-id='go-to-overview'/>}
+ <Icon
+ image='upload'
+ label={i18n('Upload New HEAT')}
+ className={isReadOnlyMode ? 'disabled' : ''}
+ iconClassName={isReadOnlyMode ? 'disabled' : ''}
+ onClick={evt => {this.refs.hiddenImportFileInput.click(evt);}}
+ data-test-id='upload-heat'/>
+ <input
+ ref='hiddenImportFileInput'
+ type='file'
+ name='fileInput'
+ accept='.zip'
+ onChange={evt => this.handleImport(evt)}/>
</div>
- <div onMouseDown={(e) => this.onChangeTreeWidth(e)} className='software-product-attachments-separator'/>
-
- <div className='software-product-attachments-error-list'>
- {errorList.length ? this.renderErrorList(errorList) : <div className='no-errors'>{attachmentsTree.children ?
- i18n('VALIDATION SUCCESS') : i18n('THERE IS NO HEAT DATA TO PRESENT') }</div>}
- </div>
- </div>
- );
- }
-
- renderNode(node, path) {
- let isFolder = node.children && node.children.length > 0;
- let {onSelectNode} = this.props;
- return (
- <div key={node.name} className='tree-block-inside'>
- {
- <div onDoubleClick={() => this.props.toggleExpanded(path)} className={this.getTreeRowClassName(node.name)}>
- {
- isFolder &&
- <div onClick={() => this.props.toggleExpanded(path)} className={classNames('tree-node-expander', {'tree-node-expander-collapsed': !node.expanded})}>
- <FontAwesome name='caret-down'/>
- </div>
- }
- {
-
- <span className='tree-node-icon'>
- <FontAwesome name={typeToIcon[node.type]}/>
- </span>
- }
- {
-
- <span onClick={() => onSelectNode(node.name)} className={this.getTreeTextClassName(node)}>
- {node.name}
- </span>
- }
- </div>
- }
- {
- isFolder &&
- <Collapse in={node.expanded}>
- <div className='tree-node-children'>
- {
- node.children.map((child, ind) => this.renderNode(child, [...path, ind]))
- }
- </div>
- </Collapse>
- }
+ <Tabs id='attachments-tabs' activeKey={this.state.activeTab} onSelect={key => this.handleTabPress(key)}>
+ <Tab eventKey={tabsMapping.SETUP} title='HEAT Setup'>
+ <HeatSetupComponent
+ heatDataExist={heatDataExist}
+ changeAttachmentsTab={tab => this.setState({activeTab: tab})}
+ onProcessAndValidate={onProcessAndValidate}
+ softwareProductId={softwareProductId}
+ isReadOnlyMode={isReadOnlyMode}
+ version={version}/>
+ </Tab>
+ <Tab eventKey={tabsMapping.VALIDATION} title='Heat Validation' disabled={!isValidationAvailable}>
+ <HeatValidation {...other}/>
+ </Tab>
+ </Tabs>
</div>
);
}
- createErrorList(errorList, node, parent) {
- if (node.errors) {
- node.errors.forEach(error => errorList.push({
- error,
- name: node.name,
- parentName: parent.name,
- type: node.type
- }));
+ handleTabPress(key) {
+ let {heatSetup, heatSetupCache, onProcessAndValidate, isReadOnlyMode, version} = this.props;
+ switch (key) {
+ case tabsMapping.VALIDATION:
+ onProcessAndValidate({heatData: heatSetup, heatDataCache: heatSetupCache, isReadOnlyMode, version}).then(
+ () => this.setState({activeTab: tabsMapping.VALIDATION})
+ );
+ return;
+ case tabsMapping.SETUP:
+ this.setState({activeTab: tabsMapping.SETUP});
+ return;
}
- if (node.children && node.children.length) {
- node.children.map((child) => this.createErrorList(errorList, child, node));
- }
- }
-
- renderErrorList(errors) {
- let prevError = {};
- let {selectedNode} = this.props;
- return errors.map(error => {
- let isSameNodeError = error.name === prevError.name && error.parentName === prevError.parentName;
- prevError = error;
-
- return (
- <div
- key={error.name + error.errorMessage + error.parentName}
-
- onClick={() => this.selectNode(error.name)}
- className={classNames('error-item', {'clicked': selectedNode === error.name, 'shifted': !isSameNodeError})}>
- <span className={classNames('error-item-file-type', {'strong': !isSameNodeError})}>
- {
- error.hasParent ?
- i18n('{type} {name} in {parentName}: ', {
- type: nodeTypes[error.type],
- name: error.name,
- parentName: error.parentName
- }) :
- i18n('{type} {name}: ', {
- type: nodeTypes[error.type],
- name: error.name
- })
- }
- </span>
- <span className={`error-item-file-type ${error.errorLevel}`}> {error.errorMessage} </span>
- </div>
- );
- });
}
- selectNode(currentSelectedNode) {
- let {onUnselectNode, onSelectNode, selectedNode} = this.props;
- if (currentSelectedNode !== selectedNode) {
- onSelectNode(currentSelectedNode);
- }else{
- onUnselectNode();
- }
-
- }
-
- getTreeRowClassName(name) {
- let {hoveredNode, selectedNode} = this.props;
- return classNames({
- 'tree-node-row': true,
- 'tree-node-selected': name === hoveredNode,
- 'tree-node-clicked': name === selectedNode
- });
+ handleImport(evt) {
+ evt.preventDefault();
+ let {version} = this.props;
+ let formData = new FormData();
+ formData.append('upload', this.refs.hiddenImportFileInput.files[0]);
+ this.refs.hiddenImportFileInput.value = '';
+ this.props.onUpload(formData, version);
+ this.setState({activeTab: tabsMapping.SETUP});
}
- getTreeTextClassName(node) {
- let {selectedNode} = this.props;
- return classNames({
- 'tree-element-text': true,
- 'error-status': node.errors,
- 'error-status-selected': node.name === selectedNode
- });
+ save() {
+ return this.props.onSave(this.props.heatSetup, this.props.version);
}
- 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);
- }
- }
}
-export default SoftwareProductAttachmentsView;
+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
new file mode 100644
index 0000000000..4c3adc6a7d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetup.js
@@ -0,0 +1,62 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {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;
+}
+
+export const mapStateToProps = ({softwareProduct: {softwareProductAttachments: {heatSetup, heatSetupCache}}}) => {
+ let {modules = [], unassigned = [], artifacts = [], nested = []} = heatSetup;
+ let isBaseExist = baseExists(modules);
+
+ 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)
+ };
+};
+
+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
new file mode 100644
index 0000000000..53143647a3
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js
@@ -0,0 +1,77 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './HeatSetupConstants.js';
+import isEqual from 'lodash/isEqual.js';
+import cloneDeep from 'lodash/cloneDeep.js';
+import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+
+export default {
+
+ addModule(dispatch, isBase){
+ dispatch({type: actionTypes.ADD_MODULE, data: {isBase}});
+ },
+
+ deleteModule(dispatch, moduleName){
+ dispatch({type: actionTypes.REMOVE_MODULE, data: {moduleName}});
+ },
+
+ 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}});
+ },
+
+ 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}}));
+ },
+
+ addAllUnassignedFilesToArtifacts(dispatch){
+ dispatch({type: actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS});
+ },
+
+ heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) {
+ return new Promise((resolve, reject) => {
+ if (isEqual({...heatSetup, softwareProductId}, heatSetupCache)) {
+ resolve();
+ } else {
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n(`You have uploaded a new HEAT. If you navigate away or Check-in without proceeding to validation,
+ Old HEAT zip file will be in use. new HEAT will be ignored. Do you want to continue?`),
+ confirmationButtonText: i18n('Continue'),
+ onConfirmed: () => resolve(),
+ onDeclined: () => reject()
+ }
+ });
+ }
+ });
+ }
+};
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
new file mode 100644
index 0000000000..2d6bd574a7
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js
@@ -0,0 +1,42 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+
+ 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,
+
+ 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}
+};
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
new file mode 100644
index 0000000000..f49339ce35
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupReducer.js
@@ -0,0 +1,124 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {actionTypes} from './HeatSetupConstants.js';
+import differenceWith from 'lodash/differenceWith.js';
+
+
+const emptyModule = (isBase, currentLength) => ({
+ 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 findModuleIndexByName(modules, 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]);
+ }
+ }
+ }
+
+ 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;
+ }
+};
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
new file mode 100644
index 0000000000..0d8bc58361
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupView.jsx
@@ -0,0 +1,328 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component} from 'react';
+import Button from 'react-bootstrap/lib/Button.js';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
+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 Icon from 'nfvo-components/icon/Icon.jsx';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+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>
+ );
+ }
+}
+
+
+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} = 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)} /></SortableListItem>
+ );
+ }, this);
+
+ return (
+ <div className='modules-list-wrapper'>
+ <div className='modules-list-header'>
+ <div className='modules-list-controllers'>
+ {!isBaseExist && <Button bsStyle='link' onClick={onBaseAdd} disabled={unassigned.length === 0}>{i18n('Add Base')}</Button>}
+ <Button bsStyle='link' onClick={onModuleAdd} disabled={unassigned.length === 0}>{i18n('Add Module')}</Button>
+ </div>
+ </div>
+ <ul>{listItems}</ul>
+ </div>
+ );
+ }
+}
+
+const tooltip = (name) => <Tooltip id='tooltip-bottom'>{name}</Tooltip>;
+const UnassignedFileList = (props) => {
+ return (
+ <div className='unassigned-files'>
+ <div className='unassigned-files-title'>{i18n('UNASSIGNED FILES')}</div>
+ <div className='unassigned-files-list'>{props.children}</div>
+ </div>
+ );
+};
+
+const EmptyListContent = props => {
+ let {onClick, 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>
+ {heatDataExist && <div className={'link'} onClick={onClick} data-test-id='go-to-validation'>{i18n('Proceed To Validation')}<SVGIcon name='angle-right'/></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 AddOrDeleteVolumeFiels = ({add = true, onAdd, onDelete}) => {
+ const displayText = add ? 'Add Volume Files' : 'Delete Volume Files';
+ const action = add ? onAdd : onDelete;
+ return (
+ <div className='add-or-delete-volumes' onClick={action}>
+ <SVGIcon name={add ? 'plus' : 'close'} />
+ <span>{i18n(displayText)}</span>
+ </div>
+ );
+};
+
+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}/>
+ );
+ }
+}
+
+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} = 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'>
+ <Icon image={isBase ? 'base' : 'module'} 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='trash-o' 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}/>}
+ <AddOrDeleteVolumeFiels onAdd={() => this.setState({displayVolumes: true})} onDelete={() => this.deleteVolumeFiles()} add={!displayVolumes}/>
+ </div>
+ </div>
+ );
+ }
+}
+
+class ArtifactOrNestedFileList extends Component {
+
+ render() {
+ let {type, title, selected, options, onSelectChanged, onAddAllUnassigned} = this.props;
+ return (
+ <div className={`artifact-files ${type === 'nested' ? 'nested' : ''}`}>
+ <div className='artifact-files-header'>
+ <span>
+ {type === 'artifact' && (<Icon image='artifacts' iconClassName='heat-setup-module-icon' />)}
+ {`${title}`}
+ </span>
+ {type === 'artifact' && <span className='add-all-unassigned' onClick={onAddAllUnassigned}>{i18n('Add All Unassigned Files')}</span>}
+ </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);
+
+class SoftwareProductHeatSetupView extends Component {
+
+ processAndValidateHeat(heatData, heatDataCache){
+ let {onProcessAndValidate, changeAttachmentsTab, version} = this.props;
+ onProcessAndValidate({heatData, heatDataCache, version}).then(
+ () => changeAttachmentsTab(tabsMapping.VALIDATION)
+ );
+ }
+
+ render() {
+ let {modules, heatSetupCache, 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}
+ artifacts={formattedArtifacts}
+ unassigned={formattedUnassigned}/>
+ <ArtifactOrNestedFileList
+ type={'artifact'}
+ title={i18n('ARTIFACTS')}
+ options={formattedUnassigned}
+ selected={formattedArtifacts}
+ onSelectChanged={onArtifactListChange}
+ onAddAllUnassigned={onAddAllUnassigned}/>
+ <ArtifactOrNestedFileList
+ type={'nested'}
+ title={i18n('NESTED HEAT FILES')}
+ options={[]}
+ selected={nested}/>
+ </div>
+ <UnassignedFileList>
+ {
+ formattedUnassigned.length > 0 ?
+ (<ul>{formattedUnassigned.map(file => <UnassignedFile key={file.label} name={file.label}/>)}</ul>)
+ :
+ (<EmptyListContent
+ heatDataExist={heatDataExist}
+ onClick={() => this.processAndValidateHeat({modules, unassigned, artifacts, nested}, heatSetupCache)}/>)
+ }
+ </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
new file mode 100644
index 0000000000..21f6e6c77f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidation.js
@@ -0,0 +1,51 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {connect} from 'react-redux';
+import HeatValidationView from './HeatValidationView.jsx';
+import HeatValidationActionHelper from './HeatValidationActionHelper.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
+ };
+};
+
+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);
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js
index 15b0ffa4a9..73366c20cc 100644
--- a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationActionHelper.js
@@ -1,24 +1,19 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from './AttachmentsConstants.js';
+import {actionTypes} from './HeatValidationConstants.js';
export default {
@@ -36,7 +31,7 @@ export default {
});
},
- onUnselectNode(dispatch) {
+ onDeselectNode(dispatch) {
dispatch({
type: actionTypes.UNSELECTED_NODE
});
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js
index 33af476d9c..f783fe6482 100644
--- a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -40,6 +35,13 @@ export const errorTypes = keyMirror({
ARTIFACT_NOT_IN_USE: i18n('artifact not in use')
});
+export const errorLevels = keyMirror({
+ WARNING: 'WARNING',
+ ERROR: 'ERROR'
+});
+export const nodeFilters = keyMirror({
+ ALL: 'All'
+});
export const nodeTypes = keyMirror({
heat: i18n('Heat'),
volume: i18n('Volume'),
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js
index 01f68aede8..f0c10ed457 100644
--- a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationReducer.js
@@ -1,25 +1,20 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes as softwareProductsActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
-import {actionTypes} from './AttachmentsConstants.js';
+import {actionTypes, nodeFilters} from './HeatValidationConstants.js';
const mapVolumeData = ({fileName, env, errors}) => ({
name: fileName,
@@ -80,7 +75,7 @@ const mapHeatData = ({fileName, env, nested, volume, network, artifacts, errors,
function createErrorList(node, parent, deep = 0, errorList = []) {
if (node.errors) {
errorList.push(...node.errors.map((error) => ({
- errorLevel: error.level,
+ level: error.level,
errorMessage: error.message,
name: node.name,
hasParent: deep > 2,
@@ -95,14 +90,15 @@ function createErrorList(node, parent, deep = 0, errorList = []) {
}
const mapValidationDataToTree = validationData => {
- let {HEAT, volume, network, artifacts, other} = validationData.importStructure || {};
+ let {heat, volume, network, artifacts, other} = validationData.importStructure || {};
return {
children: [
{
name: 'HEAT',
expanded: true,
type: 'heat',
- children: (HEAT ? HEAT.map(mapHeatData) : [])
+ header: true,
+ children: (heat ? heat.map(mapHeatData) : [])
},
...(artifacts ? [{
name: 'artifacts',
@@ -174,7 +170,8 @@ export default (state = {attachmentsTree: {}}, action) => {
return {
...state,
attachmentsTree,
- errorList
+ errorList,
+ selectedNode: nodeFilters.ALL
};
case actionTypes.TOGGLE_EXPANDED:
return {
@@ -191,7 +188,7 @@ export default (state = {attachmentsTree: {}}, action) => {
case actionTypes.UNSELECTED_NODE:
return {
...state,
- selectedNode: undefined
+ 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
new file mode 100644
index 0000000000..25ad90f351
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/validation/HeatValidationView.jsx
@@ -0,0 +1,274 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React, {Component, PropTypes} from 'react';
+import classNames from 'classnames';
+import Collapse from 'react-bootstrap/lib/Collapse.js';
+import Icon from 'nfvo-components/icon/Icon.jsx';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {mouseActions, errorLevels, nodeFilters} from './HeatValidationConstants.js';
+
+const leftPanelWidth = 250;
+const typeToIcon = Object.freeze({
+ heat: 'heat',
+ volume: 'volume',
+ network: 'network',
+ artifact: 'validation-artifacts',
+ env: 'env',
+ other: 'validation-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
+ };
+
+ 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 ? 'chevron-up' : 'chevron-down'} data-test-id='validation-tree-block-toggle'/>
+ </div>
+ }
+ {
+
+ <span className='tree-node-icon'>
+ <Icon image={typeToIcon[node.type]} iconClassName={selectedNode === node.name ? 'selected' : ''}/>
+ </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' >
+ <Icon image='zip' iconClassName={classNames(props.selectedNode === nodeFilters.ALL ? 'selected' : '', 'header-icon')} />
+ <span className={classNames({'tree-header-title-text' : true,
+ 'tree-header-title-selected' : props.selectedNode === nodeFilters.ALL})}>{i18n(`HEAT${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 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);
+ }
+ }
+}
+
+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='exclamation-triangle-line' iconClassName='large' /> : <Icon image='error-lg' /> }
+ <span className='error-item-file-type'>
+ {
+ (this.props.selectedNode === nodeFilters.ALL) ?
+ <span>
+ <span className='error-file-name'>
+ {i18n('{errorName}:', {
+ errorName: error.name
+ })}
+ </span>
+ <span>
+ {i18n('{message}', {message: error.errorMessage})}
+ </span>
+ </span> :
+ i18n('{errorMsg}', {
+ errorMsg: 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 errIcon = 'error';
+ let {size} = this.props;
+ if (size && size === 'large') {
+ errIcon += '-lg';
+ }
+ return (<div className='counters'>
+ {(errors.errorCount > 0) && <div className='counter'>
+ <Icon image={errIcon} iconClassName='counter-icon'/>
+ <div className={'error-text ' + (size ? size : '')} data-test-id='validation-error-count'>{errors.errorCount}</div>
+ </div>}
+ {(errors.warningCount > 0) && <div className='counter'>
+ <SVGIcon name='exclamation-triangle-line' iconClassName={size} />
+ <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 3b8bc4f171..2ae9ad0bae 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js
@@ -1,44 +1,43 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from './SoftwareProductComponentsConstants.js';
+import {actionTypes, forms} from './SoftwareProductComponentsConstants.js';
export default (state = {}, action) => {
switch (action.type) {
- 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:
+ case actionTypes.COMPONENT_LOAD:
return {
...state,
- data: {
- ...state.data,
- ...action.deltaData
+ formReady: null,
+ formName: forms.ALL_SPC_FORMS,
+ genericFieldInfo: {
+ 'displayName' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ },
+ 'vfcCode' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ },
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ }
}
};
default:
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 e53b2ecafe..9b3c9eaa73 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
@@ -1,56 +1,51 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
-import {actionTypes} from './SoftwareProductComponentsConstants.js';
+import {actionTypes, COMPONENTS_QUESTIONNAIRE, forms} from './SoftwareProductComponentsConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-function baseUrl(softwareProductId) {
+function baseUrl(softwareProductId, version) {
+ const versionId = version.id;
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/components`;
+ return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components`;
}
function fetchSoftwareProductComponents(softwareProductId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId)}${versionQuery}`);
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
}
-function putSoftwareProductComponentQuestionnaire(softwareProductId, vspComponentId, vspComponent) {
- return RestAPIUtil.save(`${baseUrl(softwareProductId)}/${vspComponentId}/questionnaire`, vspComponent);
+function putSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId, vspComponent) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire`, vspComponent);
}
-function fetchSoftwareProductComponentQuestionnaire(softwareProductId, vspComponentId, version){
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId)}/${vspComponentId}/questionnaire${versionQuery}`);
+function fetchSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId){
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${vspComponentId}/questionnaire`);
}
-function fetchSoftwareProductComponent(softwareProductId, vspComponentId, version){
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId)}/${vspComponentId}${versionQuery}`);
+function fetchSoftwareProductComponent(softwareProductId, version, vspComponentId){
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}/${vspComponentId}`);
}
-function putSoftwareProductComponent(softwareProductId, vspComponentId, vspComponent) {
- return RestAPIUtil.save(`${baseUrl(softwareProductId)}/${vspComponentId}`, {
+function putSoftwareProductComponent(softwareProductId, version, vspComponentId, vspComponent) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${vspComponentId}`, {
name: vspComponent.name,
displayName: vspComponent.displayName,
+ vfcCode: vspComponent.vfcCode,
description: vspComponent.description
});
}
@@ -65,27 +60,19 @@ const SoftwareProductComponentsActionHelper = {
});
},
- componentDataChanged(dispatch, {deltaData}) {
- dispatch({
- type: actionTypes.COMPONENT_DATA_CHANGED,
- deltaData
- });
- },
-
-
- updateSoftwareProductComponent(dispatch, {softwareProductId, vspComponentId, componentData, qdata}) {
+ updateSoftwareProductComponent(dispatch, {softwareProductId, version, vspComponentId, componentData, qdata}) {
return Promise.all([
- SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, vspComponentId, qdata}),
- SoftwareProductComponentsActionHelper.updateSoftwareProductComponentData(dispatch, {softwareProductId, vspComponentId, componentData})
+ SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId, qdata}),
+ SoftwareProductComponentsActionHelper.updateSoftwareProductComponentData(dispatch, {softwareProductId, version, vspComponentId, componentData})
]);
},
- updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, vspComponentId, qdata}) {
- return putSoftwareProductComponentQuestionnaire(softwareProductId, vspComponentId, qdata);
+ updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId, qdata}) {
+ return putSoftwareProductComponentQuestionnaire(softwareProductId, version, vspComponentId, qdata);
},
- updateSoftwareProductComponentData(dispatch, {softwareProductId, vspComponentId, componentData}) {
- return putSoftwareProductComponent(softwareProductId, vspComponentId, componentData).then(() => dispatch({
+ updateSoftwareProductComponentData(dispatch, {softwareProductId, version, vspComponentId, componentData}) {
+ return putSoftwareProductComponent(softwareProductId, version, vspComponentId, componentData).then(() => dispatch({
type: actionTypes.COMPONENTS_LIST_EDIT,
component: {
id: vspComponentId,
@@ -94,36 +81,36 @@ const SoftwareProductComponentsActionHelper = {
}));
},
-
- fetchSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, vspComponentId, version}) {
- return fetchSoftwareProductComponentQuestionnaire(softwareProductId, vspComponentId, version).then(response => {
- dispatch({
- type: actionTypes.COMPONENT_QUESTIONNAIRE_UPDATE,
- payload: {
- qdata: response.data ? JSON.parse(response.data) : {},
- qschema: JSON.parse(response.schema)
- }
- });
+ 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, vspComponentId, version}) {
- return fetchSoftwareProductComponent(softwareProductId, vspComponentId, version).then(response => {
- dispatch({
- type: actionTypes.COMPONENT_UPDATE,
- component: response.data
- });
+ fetchSoftwareProductComponent(dispatch, {softwareProductId, version, vspComponentId}) {
+ dispatch({
+ type: actionTypes.COMPONENT_LOAD
});
+ return Promise.all([
+ fetchSoftwareProductComponent(softwareProductId, version, vspComponentId).then(response => {
+ ValidationHelper.dataChanged(dispatch,{deltaData: response.data, formName: forms.ALL_SPC_FORMS});
+ 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)}});
+ })
+ ]);
},
- componentQuestionnaireUpdated(dispatch, {data}) {
+
+ clearComponentsStore(dispatch) {
dispatch({
- type: actionTypes.COMPONENT_QUESTIONNAIRE_UPDATE,
- payload: {
- qdata: data
- }
+ type: actionTypes.COMPONENTS_LIST_UPDATE,
+ componentsList: []
});
- },
+ }
};
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 dee517e5d1..9307b099ed 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js
@@ -1,31 +1,24 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
COMPONENTS_LIST_UPDATE: null,
COMPONENTS_LIST_EDIT: null,
- COMPONENT_UPDATE: null,
- COMPONENT_DATA_CHANGED: null,
- COMPONENT_QUESTIONNAIRE_UPDATE: null
+ COMPONENT_LOAD: null
});
export const storageConstants = keyMirror({
@@ -35,12 +28,18 @@ export const storageConstants = keyMirror({
}
});
+export const forms = keyMirror({
+ ALL_SPC_FORMS: null,
+ NIC_EDIT_FORM: null
+});
+
+export const COMPONENTS_QUESTIONNAIRE = 'component';
+
export const navigationItems = keyMirror({
STORAGE: 'Storage',
PROCESS_DETAILS: 'Process Details',
MONITORING: 'Monitoring',
NETWORK: 'Network',
COMPUTE: 'Compute',
- NETWORK: 'Network',
LOAD_BALANCING: 'High Availability & Load Balancing'
});
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js
index f1c1ed1fcc..f789a92c6f 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import SoftwareProductComponentsListView from './SoftwareProductComponentsListView.jsx';
import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
@@ -37,9 +32,9 @@ const mapStateToProps = ({softwareProduct}) => {
};
-const mapActionToProps = (dispatch, {version}) => {
+const mapActionToProps = (dispatch) => {
return {
- onComponentSelect: ({id: softwareProductId, componentId}) => {
+ onComponentSelect: ({id: softwareProductId, componentId, version}) => {
OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, {softwareProductId, componentId, version });
}
};
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 b91362a0cf..c7aaca5573 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductComponentsConstants.js';
export default (state = [], action) => {
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 0c0ba0f646..c28831fbde 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx
@@ -1,8 +1,24 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
const ComponentPropType = React.PropTypes.shape({
id: React.PropTypes.string,
@@ -43,8 +59,9 @@ class SoftwareProductComponentsListView extends React.Component {
title={i18n('Virtual Function Components')}
filterValue={localFilter}
placeholder={i18n('Filter Components')}
- onFilter={filter => this.setState({localFilter: filter})}
- isReadOnlyMode={isReadOnlyMode}>
+ onFilter={value => this.setState({localFilter: value})}
+ isReadOnlyMode={isReadOnlyMode}
+ twoColumns>
{this.filterList().map(component => this.renderComponentsListItem(component))}
</ListEditorView>
);
@@ -52,20 +69,18 @@ class SoftwareProductComponentsListView extends React.Component {
renderComponentsListItem(component) {
let {id: componentId, name, displayName, description = ''} = component;
- let {currentSoftwareProduct: {id}, onComponentSelect} = this.props;
+ let {currentSoftwareProduct: {id, version}, onComponentSelect} = this.props;
return (
<ListEditorItemView
key={name + Math.floor(Math.random() * (100 - 1) + 1).toString()}
className='list-editor-item-view'
- onSelect={() => onComponentSelect({id, componentId})}>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Component')}</div>
+ onSelect={() => onComponentSelect({id, componentId, version})}>
+ <ListEditorItemViewField>
<div className='name'>{displayName}</div>
- </div>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Description')}</div>
+ </ListEditorItemViewField>
+ <ListEditorItemViewField>
<div className='description'>{description}</div>
- </div>
+ </ListEditorItemViewField>
</ListEditorItemView>
);
}
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 7ac1c707ab..e97477b54d 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
@@ -1,51 +1,46 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import SoftwareProductComponentComputeView from './SoftwareProductComponentComputeView.jsx';
import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct;
- let {componentEditor: {qdata, qschema}} = softwareProductComponents;
+ let {componentEditor: {qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentVSP);
- let minNumberOfVMsSelectedByUser = 0;
- if(qdata && qdata.compute && qdata.compute.numOfVMs){
- minNumberOfVMsSelectedByUser = qdata.compute.numOfVMs.minimum || 0;
- }
-
return {
qdata,
- qschema,
- isReadOnlyMode,
- minNumberOfVMsSelectedByUser
+ dataMap,
+ qgenericFieldInfo,
+ isReadOnlyMode
};
};
-const mapActionToProps = (dispatch, {softwareProductId, componentId}) => {
+const mapActionToProps = (dispatch, {softwareProductId, version, componentId}) => {
return {
- onQDataChanged: ({data}) => SoftwareProductComponentsActionHelper.componentQuestionnaireUpdated(dispatch, {data}),
- onSubmit: ({qdata}) =>{ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, vspComponentId: componentId, qdata});}
+ 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})
};
};
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 3bad147117..8c197f0d49 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
@@ -1,128 +1,71 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from'nfvo-components/input/validation/ValidationInput.jsx';
-
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import VmSizing from './computeComponents/VmSizing.jsx';
+import NumberOfVms from './computeComponents/NumberOfVms.jsx';
+import GuestOs from './computeComponents/GuestOs.jsx';
+import Validator from 'nfvo-utils/Validator.js';
class SoftwareProductComponentComputeView extends React.Component {
static propTypes = {
- qdata: React.PropTypes.object,
- qschema: React.PropTypes.object,
+ dataMap: React.PropTypes.object,
+ qgenericFieldInfo: React.PropTypes.object,
isReadOnlyMode: React.PropTypes.bool,
- minNumberOfVMsSelectedByUser: React.PropTypes.number,
onQDataChanged: React.PropTypes.func.isRequired,
+ qValidateData: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired
};
render() {
- let {qdata, qschema, isReadOnlyMode, minNumberOfVMsSelectedByUser, onQDataChanged, onSubmit} = this.props;
+ let {qdata, dataMap, qgenericFieldInfo, isReadOnlyMode, onQDataChanged, qValidateData, onSubmit} = this.props;
return (
<div className='vsp-component-questionnaire-view'>
- <ValidationForm
- ref='computeValidationForm'
+ { qgenericFieldInfo && <Form
+ ref={ (form) => { this.form = form; }}
+ formReady={null}
+ isValid={true}
hasButtons={false}
onSubmit={() => onSubmit({qdata})}
className='component-questionnaire-validation-form'
- isReadOnlyMode={isReadOnlyMode}
- onDataChanged={onQDataChanged}
- data={qdata}
- schema={qschema}>
-
- <div className='section-title'>{i18n('VM Sizing')}</div>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Number of CPUs')}
- pointer={'/compute/vmSizing/numOfCPUs'}/>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('File System Size (GB)')}
- pointer={'/compute/vmSizing/fileSystemSizeGB'}/>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Persistent Storage/Volume Size (GB)')}
- pointer={'/compute/vmSizing/persistentStorageVolumeSize'}/>
- </div>
- <ValidationInput
- type='text'
- label={i18n('I/O Operations (per second)')}
- pointer={'/compute/vmSizing/IOOperationsPerSec'}/>
- </div>
- </div>
- <div className='section-title'>{i18n('Number of VMs')}</div>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Minimum')}
- pointer={'/compute/numOfVMs/minimum'}/>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Maximum')}
- pointer={'/compute/numOfVMs/maximum'}
- validations={{minValue: minNumberOfVMsSelectedByUser}}/>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='select'
- label={i18n('CPU Oversubscription Ratio')}
- pointer={'/compute/numOfVMs/CpuOverSubscriptionRatio'}/>
- </div>
- <ValidationInput
- type='select'
- label={i18n('Memory - RAM')}
- pointer={'/compute/numOfVMs/MemoryRAM'}/>
- </div>
- </div>
-
- <div className='section-title'>{i18n('Guest OS')}</div>
- <div className='rows-section'>
- <div className='section-field row-flex-components input-row'>
- <div className='two-col'>
- <ValidationInput
- label={i18n('Guest OS')}
- type='text'
- pointer={'/compute/guestOS/name'}/>
- </div>
- <div className='empty-two-col'/>
- </div>
- <div className='vertical-flex input-row'>
- <label key='label' className='control-label'>{i18n('OS Bit Size')}</label>
- <div className='radio-options-content-row input-row'>
- <ValidationInput
- type='radiogroup'
- pointer={'/compute/guestOS/bitSize'}
- className='radio-field'/>
- </div>
- </div>
- <div className='section-field row-flex-components input-row'>
- <div className='two-col'>
- <ValidationInput
- type='textarea'
- label={i18n('Guest OS Tools:')}
- pointer={'/compute/guestOS/tools'}/>
- </div>
- <div className='empty-two-col'/>
- </div>
- </div>
- </ValidationForm>
+ isReadOnlyMode={isReadOnlyMode} >
+ <VmSizing onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} />
+ <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} />
+ </Form> }
</div>
);
}
save(){
- return this.refs.computeValidationForm.handleFormSubmit(new Event('dummy'));
+ return this.form.handleFormSubmit(new Event('dummy'));
+ }
+
+ validateMin(value, state) {
+ let maxVal = state.dataMap['compute/numOfVMs/maximum'];
+ return Validator.validateItem(value,maxVal,'maximum');
+ }
+
+ validateMax(value, state) {
+ let minVal = state.dataMap['compute/numOfVMs/minimum'];
+ return Validator.validateItem(value,minVal,'minimum');
}
}
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
new file mode 100644
index 0000000000..7a730d6f94
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx
@@ -0,0 +1,76 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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')} >
+ <GridItem colSpan={2}>
+ <Input
+ data-test-id='guestOS-name'
+ label={i18n('Guest OS')}
+ type='text'
+ 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}/>
+ <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-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
new file mode 100644
index 0000000000..efeedc653e
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx
@@ -0,0 +1,94 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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>
+ <GridItem>
+ <Input
+ data-test-id='numOfVMs-CpuOverSubscriptionRatio'
+ label={i18n('CPU Oversubscription Ratio')}
+ type='select'
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ isValid={qgenericFieldInfo['compute/numOfVMs/CpuOverSubscriptionRatio'].isValid}
+ errorText={qgenericFieldInfo['compute/numOfVMs/CpuOverSubscriptionRatio'].errorText}
+ value={dataMap['compute/numOfVMs/CpuOverSubscriptionRatio']}
+ onChange={(e) => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onQDataChanged({'compute/numOfVMs/CpuOverSubscriptionRatio' : val});}
+ }>
+ <option key='placeholder' value=''>{i18n('Select...')}</option>
+ {qgenericFieldInfo['compute/numOfVMs/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['compute/numOfVMs/MemoryRAM'].isValid}
+ errorText={qgenericFieldInfo['compute/numOfVMs/MemoryRAM'].errorText}
+ value={dataMap['compute/numOfVMs/MemoryRAM']}
+ onChange={(e) => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onQDataChanged({'compute/numOfVMs/MemoryRAM' : val});}
+ }>
+ <option key='placeholder' value=''>{i18n('Select...')}</option>
+ {qgenericFieldInfo['compute/numOfVMs/MemoryRAM'].enum.map(mRAM => <option value={mRAM.enum} key={mRAM.enum}>{mRAM.title}</option>)}
+ </Input>
+ </GridItem>
+ </GridSection>
+ );
+};
+
+NumberOfVms.propTypes = {
+ minNumberOfVMsSelectedByUser: React.PropTypes.number
+};
+
+export default NumberOfVms;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/VmSizing.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/VmSizing.jsx
new file mode 100644
index 0000000000..39f84807a2
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/VmSizing.jsx
@@ -0,0 +1,68 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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')}>
+ <GridItem>
+ <Input
+ data-test-id='numOfCPUs'
+ type='number'
+ label={i18n('Number of CPUs')}
+ onChange={(tools) => onQDataChanged({'compute/vmSizing/numOfCPUs' : tools})}
+ isValid={qgenericFieldInfo['compute/vmSizing/numOfCPUs'].isValid}
+ errorText={qgenericFieldInfo['compute/vmSizing/numOfCPUs'].errorText}
+ value={dataMap['compute/vmSizing/numOfCPUs']} />
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='fileSystemSizeGB'
+ type='number'
+ label={i18n('File System Size (GB)')}
+ onChange={(tools) => onQDataChanged({'compute/vmSizing/fileSystemSizeGB' : tools})}
+ isValid={qgenericFieldInfo['compute/vmSizing/fileSystemSizeGB'].isValid}
+ errorText={qgenericFieldInfo['compute/vmSizing/fileSystemSizeGB'].errorText}
+ value={dataMap['compute/vmSizing/fileSystemSizeGB']} />
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='persistentStorageVolumeSize'
+ type='number'
+ label={i18n('Persistent Storage/Volume Size (GB)')}
+ onChange={(tools) => onQDataChanged({'compute/vmSizing/persistentStorageVolumeSize' : tools})}
+ isValid={qgenericFieldInfo['compute/vmSizing/persistentStorageVolumeSize'].isValid}
+ errorText={qgenericFieldInfo['compute/vmSizing/persistentStorageVolumeSize'].errorText}
+ value={dataMap['compute/vmSizing/persistentStorageVolumeSize']} />
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='IOOperationsPerSec'
+ type='number'
+ label={i18n('I/O Operations (per second)')}
+ onChange={(tools) => onQDataChanged({'compute/vmSizing/IOOperationsPerSec' : tools})}
+ isValid={qgenericFieldInfo['compute/vmSizing/IOOperationsPerSec'].isValid}
+ errorText={qgenericFieldInfo['compute/vmSizing/IOOperationsPerSec'].errorText}
+ value={dataMap['compute/vmSizing/IOOperationsPerSec']} />
+ </GridItem>
+ </GridSection>
+ );
+};
+
+export default VmSizing;
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 e4c330bec8..34374aa7fb 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
@@ -1,50 +1,55 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import SoftwareProductComponentsGeneralView from './SoftwareProductComponentsGeneralView.jsx';
import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.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';
+
export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct;
- let {componentEditor: {data: componentData = {} , qdata, qschema}} = softwareProductComponents;
-
+ let {componentEditor: {data: componentData = {} , qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap, genericFieldInfo}} = softwareProductComponents;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentVSP);
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
return {
componentData,
qdata,
- qschema,
- isReadOnlyMode
+ isReadOnlyMode,
+ genericFieldInfo,
+ qGenericFieldInfo,
+ dataMap,
+ isFormValid
};
};
-const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
+const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
return {
- onDataChanged: deltaData => SoftwareProductComponentsActionHelper.componentDataChanged(dispatch, {deltaData}),
- onQDataChanged: ({data}) => SoftwareProductComponentsActionHelper.componentQuestionnaireUpdated(dispatch, {data}),
+ 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, vspComponentId: componentId, componentData, qdata});
- }
+ {softwareProductId, version, vspComponentId: componentId, componentData, qdata});
+ },
+ onValidityChanged: isValidityData => SoftwareProductActionHelper.setIsValidityData(dispatch, {isValidityData})
};
};
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 5d11e42cd3..e4595f97d6 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
@@ -1,177 +1,285 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from'nfvo-components/input/validation/ValidationInput.jsx';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+const GeneralSection = ({onDataChanged, displayName, vfcCode, description, isReadOnlyMode, genericFieldInfo}) => (
+ <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>
+ <div>{name}</div>
+ </div>
+ </div>
+
+ */}
+ <GridItem>
+ <Input
+ data-test-id='name'
+ label={i18n('Name')}
+ value={displayName}
+ disabled={true}
+ type='text'/>
+ <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'/>
+ </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 ImageSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
+ <GridSection title={i18n('Image')}>
+ <GridItem>
+ <Input
+ data-test-id='format'
+ label={i18n('Image format')}
+ type='select'
+ className='input-options-select'
+ groupClassName='bootstrap-input-options'
+ isValid={qgenericFieldInfo['general/image/format'].isValid}
+ errorText={qgenericFieldInfo['general/image/format'].errorText}
+ value={dataMap['general/image/format']}
+ onChange={(e) => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onQDataChanged({'general/image/format' : val});}
+ }>
+ <option key='placeholder' value=''>{i18n('Select...')}</option>
+ {qgenericFieldInfo['general/image/format'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)}
+ </Input>
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='providedBy'
+ label={i18n('Image provided by')}
+ type='select'
+ className='input-options-select'
+ groupClassName='bootstrap-input-options'
+ 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(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)}
+ </Input>
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='bootDiskSizePerVM'
+ onChange={(bootDiskSizePerVM) => onQDataChanged({'general/image/bootDiskSizePerVM' : bootDiskSizePerVM})}
+ label={i18n('Size of boot disk per VM (GB)')}
+ type='number'
+ isValid={qgenericFieldInfo['general/image/bootDiskSizePerVM'].isValid}
+ errorText={qgenericFieldInfo['general/image/bootDiskSizePerVM'].errorText}
+ value={dataMap['general/image/bootDiskSizePerVM']}/>
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='ephemeralDiskSizePerVM'
+ onChange={(ephemeralDiskSizePerVM) => onQDataChanged({'general/image/ephemeralDiskSizePerVM' : ephemeralDiskSizePerVM})}
+ label={i18n('Size of ephemeral disk per VM (GB)')}
+ type='number'
+ isValid={qgenericFieldInfo['general/image/ephemeralDiskSizePerVM'].isValid}
+ errorText={qgenericFieldInfo['general/image/ephemeralDiskSizePerVM'].errorText}
+ value={dataMap['general/image/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
+ <div className='row'>
+ <div className='col-md-3'>
+ <Input
+ label={i18n('VM Recovery Document')}
+ type='text'
+ pointer='/general/recovery/VMRecoveryDocument'/>
+ </div>
+ </div>
+ */
+ }
+ </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>
+);
class SoftwareProductComponentsGeneralView extends React.Component {
render() {
- let {qdata, qschema, onQDataChanged, onDataChanged, componentData: {displayName, description}, isReadOnlyMode} = this.props;
+ let {onQDataChanged, onDataChanged, genericFieldInfo, dataMap, qGenericFieldInfo, componentData: {displayName, vfcCode, description}, isReadOnlyMode} = this.props;
return(
<div className='vsp-components-general'>
<div className='general-data'>
- <ValidationForm
- isReadOnlyMode={isReadOnlyMode}
- hasButtons={false}>
- <div className=''>
- <h3 className='section-title'>{i18n('General')}</h3>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- {/** 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>
- <div>{name}</div>
- </div>
- </div>
-
- */}
- <div className='single-col'>
- <ValidationInput label={i18n('Name')} value={displayName} disabled={true} type='text'/>
- </div>
- <div className='two-col'>
- <ValidationInput
- label={i18n('Description')}
- onChange={description => onDataChanged({description})}
- disabled={isReadOnlyMode}
- value={description}
- type='textarea'/>
- </div>
- <div className='empty-col' />
- </div>
- </div>
- </div>
- </ValidationForm>
- {
- qschema &&
- <ValidationForm
- onDataChanged={onQDataChanged}
- data={qdata}
- schema={qschema}
+ {genericFieldInfo && qGenericFieldInfo && <Form
+ isValid={this.props.isFormValid}
+ formReady={null}
isReadOnlyMode={isReadOnlyMode}
+ onValidityChanged={(isValidityData) => this.props.onValidityChanged(isValidityData)}
hasButtons={false}>
- <h3 className='section-title additional-validation-form'>{i18n('Hypervisor')}</h3>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <ValidationInput
- label={i18n('Supported Hypervisors')}
- type='select'
- pointer='/general/hypervisor/hypervisor'/>
- </div>
- <div className='two-col'>
- <ValidationInput
- label={i18n('Hypervisor Drivers')}
- type='text'
- pointer='/general/hypervisor/drivers'/>
- </div>
- <div className='empty-col' />
- </div>
- <div className='row-flex-components input-row'>
- <div className='three-col'>
- <ValidationInput
- label={i18n('Describe Container Features')}
- type='textarea'
- pointer='/general/hypervisor/containerFeaturesDescription'/>
- </div>
- <div className='empty-col' />
- </div>
- </div>
- <h3 className='section-title'>{i18n('Image')}</h3>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <ValidationInput
- label={i18n('Image format')}
- type='select'
- pointer='/general/image/format'/>
- </div>
- <div className='single-col'>
- <ValidationInput
- label={i18n('Image provided by')}
- type='select'
- pointer='/general/image/providedBy'/>
- </div>
- <div className='single-col'>
- <ValidationInput
- label={i18n('Size of boot disk per VM (GB)')}
- type='text'
- pointer='/general/image/bootDiskSizePerVM'/>
- </div>
- <ValidationInput
- label={i18n('Size of ephemeral disk per VM (GB)')}
- type='text'
- pointer='/general/image/ephemeralDiskSizePerVM'/>
- </div>
- </div>
- <h3 className='section-title'>{i18n('Recovery')}</h3>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <ValidationInput
- label={i18n('VM Recovery Point Objective (Minutes)')}
- type='text'
- pointer='/general/recovery/pointObjective'/>
- </div>
- <ValidationInput
- label={i18n('VM Recovery Time Objective (Minutes)')}
- type='text'
- pointer='/general/recovery/timeObjective'/>
- <div className='empty-two-col' />
- </div>
-
-
- <div className='row-flex-components input-row'>
- <div className='two-col'>
- <ValidationInput
- className='textarea'
- label={i18n('How are in VM process failures handled?')}
- type='textarea'
- pointer='/general/recovery/vmProcessFailuresHandling'/>
- </div>
- <div className='empty-two-col' />
- {
- /** disabled until backend will be ready to implement it
- <div className='row'>
- <div className='col-md-3'>
- <ValidationInput
- label={i18n('VM Recovery Document')}
- type='text'
- pointer='/general/recovery/VMRecoveryDocument'/>
- </div>
- </div>
- */
- }
- </div>
- </div>
- <h3 className='section-title'>{i18n('DNS Configuration')}</h3>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='two-col'>
- <ValidationInput
- label={i18n('Do you have a need for DNS as a Service? Please describe.')}
- type='textarea'
- pointer='/general/dnsConfiguration'/>
- </div>
- <div className='empty-two-col' />
- </div>
- </div>
- <h3 className='section-title'>{i18n('Clone')}</h3>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='two-col'>
- <ValidationInput
- label={i18n('Describe VM Clone Use')}
- type='textarea'
- pointer='/general/vmCloneUsage'/>
- </div>
- <div className='empty-two-col' />
- </div>
- </div>
- </ValidationForm>
- }
+ <GeneralSection
+ onDataChanged={onDataChanged}
+ displayName={displayName}
+ vfcCode={vfcCode}
+ description={description}
+ 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>
);
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 4d4034de5b..0634858219 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
@@ -1,45 +1,43 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import SoftwareProductComponentLoadBalancingView from './SoftwareProductComponentLoadBalancingRefView.jsx';
import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct;
- let {componentEditor: {qdata, qschema}} = softwareProductComponents;
+ let {componentEditor: {qdata, qgenericFieldInfo : genericFieldInfo, dataMap}} = softwareProductComponents;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentVSP);
return {
qdata,
- qschema,
+ genericFieldInfo,
+ dataMap,
isReadOnlyMode
};
};
-const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
+const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
return {
- onQDataChanged: ({data}) => SoftwareProductComponentsActionHelper.componentQuestionnaireUpdated(dispatch, {data}),
- onSubmit: ({qdata}) =>{ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, vspComponentId: componentId, qdata});}
+ onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}),
+ onSubmit: ({qdata}) =>{ return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, version, vspComponentId: componentId, qdata});}
};
};
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 1aa2babc12..dc86771400 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
@@ -1,11 +1,29 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-import FontAwesome from 'react-fontawesome';
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from'nfvo-components/input/validation/ValidationInput.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import Input from'nfvo-components/input/validation/Input.jsx';
-const prefix = '/highAvailabilityAndLoadBalancing/';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+
+const prefix = 'highAvailabilityAndLoadBalancing/';
const pointers = [
{
@@ -33,6 +51,31 @@ const pointers = [
}
];
+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 ? 'chevron-up' : 'chevron-down'}/>
+ <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: React.PropTypes.string.isRequired,
@@ -46,42 +89,65 @@ class SoftwareProductComponentLoadBalancingView extends React.Component {
expanded: {}
};
- renderTextAreaItem(item) {
- return (
- <div className='question'>
- <div className={this.state.expanded[item.key] ? 'title' : 'title add-padding'}
- onClick={() => this.toggle(item.key)}>
- <FontAwesome name={this.state.expanded[item.key] ? 'chevron-up' : 'chevron-down'}/>
- {i18n(item.description)}
- {item.added && <div className='new-line'>{i18n(item.added)}</div>}
- </div>
- <div className={this.state.expanded[item.key] ? 'collapse in' : 'collapse'}>
- <div className='row'>
- <div className='col-md-9'>
- <ValidationInput
- type='textarea'
- pointer={`${prefix}${item.key}`}
- maxLength='1000' />
- </div>
- </div>
- </div>
- </div>
- );
- }
-
render() {
- let {qdata, qschema, onQDataChanged, isReadOnlyMode} = this.props;
+ let {dataMap, genericFieldInfo, onQDataChanged, isReadOnlyMode} = this.props;
return (
<div className='vsp-components-load-balancing'>
<div className='halb-data'>
- <div className='load-balancing-page-title'>{i18n('High Availability & Load Balancing')}</div>
- <ValidationForm
- onDataChanged={onQDataChanged}
- data={qdata} schema={qschema}
+ { genericFieldInfo && <Form
+ formReady={null}
+ isValid={true}
+ onSubmit={() => this.save()}
isReadOnlyMode={isReadOnlyMode}
hasButtons={false}>
- {pointers.map(pointer => this.renderTextAreaItem(pointer))}
- </ValidationForm>
+ <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>
);
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 ed7c5a116a..293e252dca 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
@@ -1,27 +1,25 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
import SoftwareProductComponentsMonitoringView from './SoftwareProductComponentsMonitoringView.jsx';
import SoftwareProductComponentsMonitoringAction from './SoftwareProductComponentsMonitoringActionHelper.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
export const mapStateToProps = ({softwareProduct}) => {
@@ -37,11 +35,12 @@ export const mapStateToProps = ({softwareProduct}) => {
};
};
-const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
+const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
return {
onDropMibFileToUpload: (formData, type) =>
SoftwareProductComponentsMonitoringAction.uploadSnmpFile(dispatch, {
softwareProductId,
+ version,
componentId,
formData,
type
@@ -49,9 +48,18 @@ const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
onDeleteSnmpFile: type => SoftwareProductComponentsMonitoringAction.deleteSnmpFile(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.')
+ }
+ }),
};
};
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 3faf571c09..64403faa78 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
@@ -1,80 +1,76 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import i18n from 'nfvo-utils/i18n/i18n.js';
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
-import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js';
import Configuration from 'sdc-app/config/Configuration.js';
import SoftwareProductComponentsMonitoringConstants, {actionTypes} from './SoftwareProductComponentsMonitoringConstants.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
const UPLOAD = true;
-function baseUrl(vspId, componentId) {
+function baseUrl(vspId, version, componentId) {
+ const versionId = version.id;
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-software-products/${vspId}/components/${componentId}/monitors`;
+ return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/components/${componentId}/monitors`;
}
-function snmpTrapUrl(vspId, componentId, isUpload) {
- return `${baseUrl(vspId, componentId)}/snmp-trap${isUpload ? '/upload' : ''}`;
+function snmpTrapUrl(vspId, version, componentId, isUpload) {
+ return `${baseUrl(vspId, version, componentId)}/snmp-trap${isUpload ? '/upload' : ''}`;
}
-function snmpPollUrl(vspId, componentId, isUpload) {
- return `${baseUrl(vspId, componentId)}/snmp${isUpload ? '/upload' : ''}`;
+function snmpPollUrl(vspId, version, componentId, isUpload) {
+ return `${baseUrl(vspId, version, componentId)}/snmp${isUpload ? '/upload' : ''}`;
}
let onInvalidFileSizeUpload = (dispatch) => dispatch({
- type: NotificationConstants.NOTIFY_ERROR,
+ type: modalActionTypes.GLOBAL_MODAL_ERROR,
data: {
title: i18n('Upload Failed'),
msg: i18n('no zip file was uploaded or zip file doesn\'t exist')
}
});
-let uploadSnmpTrapFile = (dispatch, {softwareProductId, componentId, formData}) => {
- RestAPIUtil.create(snmpTrapUrl(softwareProductId, componentId, UPLOAD), formData).then(()=> dispatch({
+let uploadSnmpTrapFile = (dispatch, {softwareProductId, version, componentId, formData}) => {
+ RestAPIUtil.post(snmpTrapUrl(softwareProductId, version, componentId, UPLOAD), formData).then(()=> dispatch({
type: actionTypes.SNMP_TRAP_UPLOADED, data: {filename: formData.get('upload').name}
}));
};
-let uploadSnmpPollFile = (dispatch, {softwareProductId, componentId, formData}) => {
- RestAPIUtil.create(snmpPollUrl(softwareProductId, componentId, UPLOAD), formData).then(()=> dispatch({
+let uploadSnmpPollFile = (dispatch, {softwareProductId, version, componentId, formData}) => {
+ RestAPIUtil.post(snmpPollUrl(softwareProductId, version, componentId, UPLOAD), formData).then(()=> dispatch({
type: actionTypes.SNMP_POLL_UPLOADED, data: {filename: formData.get('upload').name}
}));
};
-let deleteSnmpTrapFile = (dispatch, {softwareProductId, componentId}) => {
- RestAPIUtil.destroy(snmpTrapUrl(softwareProductId, componentId, !UPLOAD)).then(()=> dispatch({
+let deleteSnmpTrapFile = (dispatch, {softwareProductId, version, componentId}) => {
+ RestAPIUtil.destroy(snmpTrapUrl(softwareProductId, version, componentId, !UPLOAD)).then(()=> dispatch({
type: actionTypes.SNMP_TRAP_DELETED
}));
};
-let deleteSnmpPollFile = (dispatch, {softwareProductId, componentId}) => {
- RestAPIUtil.destroy(snmpPollUrl(softwareProductId, componentId, !UPLOAD)).then(()=> dispatch({
+let deleteSnmpPollFile = (dispatch, {softwareProductId, version, componentId}) => {
+ RestAPIUtil.destroy(snmpPollUrl(softwareProductId, version, componentId, !UPLOAD)).then(()=> dispatch({
type: actionTypes.SNMP_POLL_DELETED
}));
};
const SoftwareProductComponentsMonitoringAction = {
- fetchExistingFiles(dispatch, {softwareProductId, componentId}){
- RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId)}/snmp`).then(response =>
+ fetchExistingFiles(dispatch, {softwareProductId, version, componentId}){
+ RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/snmp`).then(response =>
dispatch({
type: actionTypes.SNMP_FILES_DATA_CHANGE,
data: {trapFilename: response.snmpTrap, pollFilename: response.snmpPoll}
@@ -82,13 +78,13 @@ const SoftwareProductComponentsMonitoringAction = {
);
},
- uploadSnmpFile(dispatch, {softwareProductId, componentId, formData, type}){
+ uploadSnmpFile(dispatch, {softwareProductId, version, componentId, formData, type}){
if (formData.get('upload').size) {
if (type === SoftwareProductComponentsMonitoringConstants.SNMP_TRAP) {
- uploadSnmpTrapFile(dispatch, {softwareProductId, componentId, formData});
+ uploadSnmpTrapFile(dispatch, {softwareProductId, version, componentId, formData});
}
else {
- uploadSnmpPollFile(dispatch, {softwareProductId, componentId, formData});
+ uploadSnmpPollFile(dispatch, {softwareProductId, version, componentId, formData});
}
}
else {
@@ -96,12 +92,12 @@ const SoftwareProductComponentsMonitoringAction = {
}
},
- deleteSnmpFile(dispatch, {softwareProductId, componentId, type}){
+ deleteSnmpFile(dispatch, {softwareProductId, version, componentId, type}){
if (type === SoftwareProductComponentsMonitoringConstants.SNMP_TRAP) {
- deleteSnmpTrapFile(dispatch, {softwareProductId, componentId});
+ deleteSnmpTrapFile(dispatch, {softwareProductId, version, componentId});
}
else {
- deleteSnmpPollFile(dispatch, {softwareProductId, componentId});
+ deleteSnmpPollFile(dispatch, {softwareProductId, version, componentId});
}
}
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 eeececb050..d908d36aaa 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
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
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 72e0a85b10..54513b9634 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
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductComponentsMonitoringConstants.js';
export default (state = {}, action) => {
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 ca090c5f2f..329cc70353 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
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React, {Component, PropTypes} from 'react';
import Dropzone from 'react-dropzone';
import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
@@ -46,7 +61,7 @@ class SoftwareProductComponentsMonitoringView extends Component {
return (
<Dropzone
className={`snmp-dropzone ${this.state.dragging ? 'active-dragging' : ''}`}
- onDrop={files => this.handleImport(files, {isReadOnlyMode, type, refAndName})}
+ onDrop={(acceptedFiles, rejectedFiles) => this.handleImport(acceptedFiles, rejectedFiles, {isReadOnlyMode, type, refAndName})}
onDragEnter={() => this.handleOnDragEnter(isReadOnlyMode)}
onDragLeave={() => this.setState({dragging:false})}
multiple={false}
@@ -70,7 +85,7 @@ class SoftwareProductComponentsMonitoringView extends Component {
className={`software-product-landing-view-top-block-col-upl${isReadOnlyMode ? ' disabled' : ''}`}>
<div className='drag-text'>{i18n('Drag & drop for upload')}</div>
<div className='or-text'>{i18n('or')}</div>
- <div className='upload-btn primary-btn' onClick={() => this.refs[refAndName].open()}>
+ <div className='upload-btn primary-btn' data-test-id={`monitoring-upload-${refAndName}`} onClick={() => this.refs[refAndName].open()}>
<span className='primary-btn-text'>{i18n('Select file')}</span>
</div>
</div>
@@ -95,17 +110,21 @@ class SoftwareProductComponentsMonitoringView extends Component {
}
}
- handleImport(files, {isReadOnlyMode, type, refAndName}) {
+ handleImport(files, rejectedFiles, {isReadOnlyMode, type, refAndName}) {
if (isReadOnlyMode) {
return;
}
-
- 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);
+ 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();
+ }
}
getFileTypeDisplayName(type) {
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 a412456e13..7cf1f0189e 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
@@ -1,53 +1,66 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import SoftwareProductComponentsNetworkActionHelper from './SoftwareProductComponentsNetworkActionHelper.js';
import SoftwareProductComponentsNICEditorView from './SoftwareProductComponentsNICEditorView.jsx';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+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';
export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data:currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct;
let {network: {nicEditor = {}}} = softwareProductComponents;
- let {data, qdata, qschema} = nicEditor;
+ let {data, qdata, genericFieldInfo, qgenericFieldInfo, dataMap, formReady} = nicEditor;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(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,
- qschema,
- isReadOnlyMode
+ dataMap,
+ isFormValid,
+ formReady,
+ genericFieldInfo,
+ qgenericFieldInfo,
+ isReadOnlyMode,
+ protocols
};
};
const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
return {
- onDataChanged: deltaData => SoftwareProductComponentsNetworkActionHelper.updateNICData(dispatch, {deltaData}),
- onSubmit: ({data, qdata}) => SoftwareProductComponentsNetworkActionHelper.saveNICDataAndQuestionnaire(dispatch, {softwareProductId, componentId, data, qdata}),
+ onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData,
+ formName: forms.NIC_EDIT_FORM}),
+ onSubmit: ({data, qdata, version}) => SoftwareProductComponentsNetworkActionHelper.saveNICDataAndQuestionnaire(dispatch, {softwareProductId, version, componentId, data, qdata}),
onCancel: () => SoftwareProductComponentsNetworkActionHelper.closeNICEditor(dispatch),
- onQDataChanged: ({data}) => SoftwareProductComponentsNetworkActionHelper.updateNICQuestionnaire(dispatch, {data})
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, forms.NIC_EDIT_FORM),
+ onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
+ qName: NIC_QUESTIONNAIRE}),
};
};
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 d49f9ccb1e..b3c9fe5d98 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
@@ -1,48 +1,43 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js';
+import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
export default (state = {}, action) => {
switch (action.type) {
case actionTypes.NICEditor.OPEN:
return {
...state,
- data: action.nic
+ data: action.nic,
+ genericFieldInfo: {
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ },
+ 'name' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ }
+ },
+ formName: forms.NIC_EDIT_FORM
};
case actionTypes.NICEditor.CLOSE:
return {};
- case actionTypes.NICEditor.NIC_QUESTIONNAIRE_UPDATE:
- return {
- ...state,
- qdata: action.payload.qdata || state.qdata,
- qschema: action.payload.qschema || state.qschema
- };
- case actionTypes.NICEditor.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
- }
- };
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 7393a835dc..aad06c82f0 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
@@ -1,321 +1,71 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
-
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import Acceptable from './nicEditorComponents/Acceptable.jsx';
+import FlowLength from './nicEditorComponents/FlowLength.jsx';
+import OutFlowTraffic from './nicEditorComponents/OutFlowTraffic.jsx';
+import InFlowTraffic from './nicEditorComponents/InFlowTraffic.jsx';
+import Sizing from './nicEditorComponents/Sizing.jsx';
+import Network from './nicEditorComponents/Network.jsx';
+import IpConfig from './nicEditorComponents/IpConfig.jsx';
+import Protocols from './nicEditorComponents/Protocols.jsx';
+import NameAndPurpose from './nicEditorComponents/NameAndPurpose.jsx';
class SoftwareProductComponentsNetworkEditorView extends React.Component {
render() {
- let {onCancel, isReadOnlyMode} = this.props;
- return (
- <ValidationForm
- ref='validationForm'
- hasButtons={true}
- onSubmit={ () => this.submit() }
- onReset={ () => onCancel() }
- labledButtons={true}
- isReadOnlyMode={isReadOnlyMode}
- className='vsp-components-network-editor'>
- {this.renderEditorFields()}
- </ValidationForm>
- );
- }
-
- renderEditorFields() {
- let {data = {}, qdata = {}, qschema = {}, onQDataChanged, onDataChanged, isReadOnlyMode} = this.props;
+ let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, qgenericFieldInfo, dataMap, onDataChanged, protocols, onQDataChanged} = this.props;
let {name, description, networkName} = data;
let netWorkValues = [{
enum: networkName,
title: networkName
}];
- return(
- <div className='editor-data'>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Name')}
- value={name}
- disabled={true}
- type='text'/>
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Purpose of NIC')}
- value={description}
- onChange={description => onDataChanged({description})}
- disabled={isReadOnlyMode}
- type='textarea'/>
- </div>
- </div>
- <ValidationForm
- onDataChanged={onQDataChanged}
- data={qdata}
- schema={qschema}
- isReadOnlyMode={isReadOnlyMode}
- hasButtons={false}>
- <div className='row'>
- <div className='part-title'>{i18n('Protocols')}</div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Protocols')}
- type='select'
- pointer='/protocols/protocols'/>
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Protocol with Highest Traffic Profile')}
- type='select'
- pointer='/protocols/protocolWithHighestTrafficProfile'/>
- </div>
- </div>
- <div className='row'>
- <div className='part-title'>{i18n('IP Configuration')}</div>
- <div className='col-md-3'>
- <ValidationInput
- label={i18n('IPv4 Required')}
- type='checkbox'
- pointer='/ipConfiguration/ipv4Required'/>
- </div>
- <div className='col-md-9'>
- <ValidationInput
- label={i18n('IPv6 Required')}
- type='checkbox'
- pointer='/ipConfiguration/ipv6Required'/>
- </div>
- </div>
- </ValidationForm>
- <div className='row'>
- <div className='part-title'>{i18n('Network')}</div>
- <div className='col-md-2'>
- <ValidationInput
- label={i18n('Internal')}
- disabled
- checked={true}
- className='network-radio disabled'
- type='radio'/>
- </div>
- <div className='col-md-4'>
- <ValidationInput
- label={i18n('External')}
- disabled
- checked={false}
- className='network-radio disabled'
- type='radio'/>
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Network')}
- type='select'
- disabled={true}
- values={netWorkValues}/>
- </div>
+ 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 name={name} description={description} onDataChanged={onDataChanged} isReadOnlyMode={isReadOnlyMode}/>
+ <Protocols protocols={protocols} qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
+ <IpConfig dataMap={dataMap} onQDataChanged={onQDataChanged} />
+ <Network networkValues={netWorkValues} />
+ <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>
- <ValidationForm
- onDataChanged={onQDataChanged}
- data={qdata}
- schema={qschema}
- isReadOnlyMode={isReadOnlyMode}
- hasButtons={false}>
- <div className='row'>
- <div className='part-title'>{i18n('Sizing')}</div>
- <div className='col-md-12'>
- <ValidationInput
- label={i18n('Describe Quality of Service')}
- type='textarea'
- pointer='/sizing/describeQualityOfService'/>
- </div>
- </div>
-
- <div className='row'>
- <div className='part-title'>{i18n('Inflow Traffic per second')}</div>
- </div>
-
- <div className='row'>
- <div className='col-md-6'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Packets')}</div>
- </div>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Peak')}
- type='text'
- pointer='/sizing/inflowTrafficPerSecond/packets/peak'/>
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Avg')}
- type='text'
- pointer='/sizing/inflowTrafficPerSecond/packets/avg'/>
- </div>
- </div>
- </div>
- <div className='col-md-6'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Bytes')}</div>
- </div>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Peak')}
- type='text'
- pointer='/sizing/inflowTrafficPerSecond/bytes/peak'/>
-
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Avg')}
- type='text'
- pointer='/sizing/inflowTrafficPerSecond/bytes/avg'/>
- </div>
- </div>
- </div>
- </div>
-
- <div className='row'>
- <div className='part-title'>{i18n('Outflow Traffic per second')}</div>
- </div>
-
- <div className='row'>
- <div className='col-md-6'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Packets')}</div>
- </div>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Peak')}
- type='text'
- pointer='/sizing/outflowTrafficPerSecond/packets/peak'/>
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Avg')}
- type='text'
- pointer='/sizing/outflowTrafficPerSecond/packets/avg'/>
-
- </div>
- </div>
- </div>
- <div className='col-md-6'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Bytes')}</div>
- </div>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Peak')}
- type='text'
- pointer='/sizing/outflowTrafficPerSecond/bytes/peak'/>
-
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Avg')}
- type='text'
- pointer='/sizing/outflowTrafficPerSecond/bytes/avg'/>
-
- </div>
- </div>
- </div>
- </div>
-
- <div className='row'>
- <div className='part-title'>{i18n('Flow Length')}</div>
- </div>
-
- <div className='row'>
- <div className='col-md-6'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Packets')}</div>
- </div>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Peak')}
- type='text'
- pointer='/sizing/flowLength/packets/peak'/>
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Avg')}
- type='text'
- pointer='/sizing/flowLength/packets/avg'/>
- </div>
- </div>
- </div>
- <div className='col-md-6'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Bytes')}</div>
- </div>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Peak')}
- type='text'
- pointer='/sizing/flowLength/bytes/peak'/>
-
- </div>
- <div className='col-md-6'>
- <ValidationInput
- label={i18n('Avg')}
- type='text'
- pointer='/sizing/flowLength/bytes/avg'/>
- </div>
- </div>
- </div>
- </div>
-
- <div className='row'>
- <div className='col-md-9'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Acceptable Jitter')}</div>
- </div>
- <div className='row'>
- <div className='col-md-4'>
- <ValidationInput
- label={i18n('Min')}
- type='text'
- pointer='/sizing/acceptableJitter/mean'/>
- </div>
- <div className='col-md-4'>
- <ValidationInput
- label={i18n('Max')}
- type='text'
- pointer='/sizing/acceptableJitter/max'/>
- </div>
- <div className='col-md-4'>
- <ValidationInput
- label={i18n('Var')}
- type='text'
- pointer='/sizing/acceptableJitter/variable'/>
- </div>
- </div>
- </div>
- <div className='col-md-3'>
- <div className='row'>
- <div className='part-title-small'>{i18n('Acceptable Packet Loss %')}</div>
- </div>
- <div className='row'>
- <div className='col-md-12'>
- <ValidationInput
- label={i18n('In Percent')}
- type='text'
- pointer='/sizing/acceptablePacketLoss'/>
- </div>
- </div>
- </div>
- </div>
- </ValidationForm>
+ </Form> }
</div>
-
);
}
+
submit() {
- let {data, qdata, onSubmit} = this.props;
- onSubmit({data, qdata});
+ let {data, qdata, onSubmit, version} = this.props;
+ onSubmit({data, qdata, version});
}
}
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 bc53e1a7af..5cfc88bdc9 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
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js';
export default (state = [], action) => {
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 8ff6b50189..bc061469b1 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
@@ -1,65 +1,60 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
-function baseUrl(softwareProductId, componentId) {
+function baseUrl(softwareProductId, version, componentId) {
+ const versionId = version.id;
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/components/${componentId}/nics`;
+ return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/nics`;
}
-function fetchNICQuestionnaire({softwareProductId, componentId, nicId, version}) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId)}/${nicId}/questionnaire${versionQuery}`);
+function fetchNICQuestionnaire({softwareProductId, version, componentId, nicId}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${nicId}/questionnaire`);
}
-function fetchNIC({softwareProductId, componentId, nicId, version}) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId)}/${nicId}${versionQuery}`);
+function fetchNIC({softwareProductId, version, componentId, nicId}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${nicId}`);
}
-function fetchNICsList({softwareProductId, componentId, version}) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId)}${versionQuery}`);
+function fetchNICsList({softwareProductId, version, componentId}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`);
}
-function saveNIC({softwareProductId, componentId, nic: {id, name, description, networkId}}) {
- return RestAPIUtil.save(`${baseUrl(softwareProductId, componentId)}/${id}`,{
+function saveNIC({softwareProductId, version, componentId, nic: {id, name, description, networkId}}) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${id}`,{
name,
description,
networkId
});
}
-function saveNICQuestionnaire({softwareProductId, componentId, nicId, qdata}) {
- return RestAPIUtil.save(`${baseUrl(softwareProductId, 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, componentId, version}) {
- return fetchNICsList({softwareProductId, componentId, version}).then((response) => {
+ fetchNICsList(dispatch, {softwareProductId, version, componentId}) {
+ return fetchNICsList({softwareProductId, version, componentId}).then((response) => {
dispatch({
type: actionTypes.NIC_LIST_UPDATE,
response: response.results
@@ -80,43 +75,24 @@ const SoftwareProductComponentNetworkActionHelper = {
});
},
- loadNICData({softwareProductId, componentId, nicId, version}) {
- return fetchNIC({softwareProductId, componentId, nicId, version});
- },
-
- loadNICQuestionnaire(dispatch, {softwareProductId, componentId, nicId, version}) {
- return fetchNICQuestionnaire({softwareProductId, componentId, nicId, version}).then((response) => {
- dispatch({
- type: actionTypes.NICEditor.NIC_QUESTIONNAIRE_UPDATE,
- payload: {
- qdata: response.data ? JSON.parse(response.data) : {},
- qschema: JSON.parse(response.schema)
- }
- });
- });
+ loadNICData({softwareProductId, version, componentId, nicId}) {
+ return fetchNIC({softwareProductId, version, componentId, nicId});
},
- updateNICData(dispatch, {deltaData}) {
- dispatch({
- type: actionTypes.NICEditor.DATA_CHANGED,
- deltaData
- });
- },
-
- updateNICQuestionnaire(dispatch, {data}) {
- dispatch({
- type: actionTypes.NICEditor.NIC_QUESTIONNAIRE_UPDATE,
- payload: {
- qdata: data
- }
+ 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, componentId, data, qdata}) {
+ saveNICDataAndQuestionnaire(dispatch, {softwareProductId, version, componentId, data, qdata}) {
SoftwareProductComponentNetworkActionHelper.closeNICEditor(dispatch);
return Promise.all([
- saveNICQuestionnaire({softwareProductId, componentId, nicId: data.id, qdata}),
- saveNIC({softwareProductId, componentId, nic: data}).then(() => {
+ saveNICQuestionnaire({softwareProductId, version, componentId, nicId: data.id, qdata}),
+ saveNIC({softwareProductId, version, componentId, nic: data}).then(() => {
dispatch({
type: actionTypes.NIC_LIST_EDIT,
nic: data
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 193f4b20b5..39c55d876c 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
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
@@ -26,8 +21,8 @@ export const actionTypes = keyMirror({
NICEditor: {
OPEN: null,
- CLOSE: null,
- NIC_QUESTIONNAIRE_UPDATE: null,
- DATA_CHANGED: null
+ CLOSE: null
}
});
+
+export const NIC_QUESTIONNAIRE = 'nic';
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 9172dc691a..c2bd8ce479 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
@@ -1,51 +1,47 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.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 ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data: currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct;
- let {network: {nicEditor = {}, nicList = []}, componentEditor: {data: componentData, qdata, qschema}} = softwareProductComponents;
+ let {network: {nicEditor = {}, nicList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
let {data} = nicEditor;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
let {version} = currentSoftwareProduct;
- let manualMode = nicList.length <= 0;
let isModalInEditMode = true;
return {
version,
componentData,
qdata,
- qschema,
+ dataMap,
+ qgenericFieldInfo,
isValidityData,
nicList,
isDisplayModal: Boolean(data),
isModalInEditMode,
- manualMode,
isReadOnlyMode
};
@@ -53,28 +49,28 @@ export const mapStateToProps = ({softwareProduct}) => {
const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
return {
- onQDataChanged: ({data}) => SoftwareProductComponentsActionHelper.componentQuestionnaireUpdated(dispatch, {data}),
- onAddNIC: () => SoftwareProductComponentsNetworkActionHelper.openNICEditor(dispatch),
+ onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
+ qName: COMPONENTS_QUESTIONNAIRE}),
onEditNicClick: (nic, version) => {
Promise.all([
SoftwareProductComponentsNetworkActionHelper.loadNICData({
softwareProductId,
+ version,
componentId,
- nicId: nic.id,
- version
+ nicId: nic.id
}),
SoftwareProductComponentsNetworkActionHelper.loadNICQuestionnaire(dispatch, {
softwareProductId,
+ version,
componentId,
- nicId: nic.id,
- version
+ nicId: nic.id
})
]).then(
([{data}]) => SoftwareProductComponentsNetworkActionHelper.openNICEditor(dispatch, {nic, data})
);
},
- onSubmit: ({qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
- {softwareProductId,
+ onSubmit: ({qdata, version}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
+ {softwareProductId, version,
vspComponentId: componentId,
qdata});
}
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 b3e17ff94b..f715016ba3 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
@@ -1,10 +1,26 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+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 ValidationInput from'nfvo-components/input/validation/ValidationInput.jsx';
+import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
+import Input from'nfvo-components/input/validation/Input.jsx';
import Modal from 'nfvo-components/modal/Modal.jsx';
import SoftwareProductComponentsNICEditor from './SoftwareProductComponentsNICEditor.js';
@@ -16,38 +32,56 @@ class SoftwareProductComponentsNetworkView extends React.Component {
};
render() {
- let {qdata, qschema, onQDataChanged, isModalInEditMode, isDisplayModal, softwareProductId, componentId, isReadOnlyMode} = this.props;
+ let {dataMap, qgenericFieldInfo, onQDataChanged, isModalInEditMode, isDisplayModal, softwareProductId, componentId, isReadOnlyMode} = this.props;
return(
<div className='vsp-components-network'>
<div className='network-data'>
<div>
- <ValidationForm
- onDataChanged={onQDataChanged}
- data={qdata}
- isReadOnlyMode={isReadOnlyMode}
- schema={qschema}
- hasButtons={false}>
+{ 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 input-row'>
+ <div className='row-flex-components'>
<div className='single-col'>
- <ValidationInput
+ <Input
+ data-test-id='protocolWithHighestTrafficProfileAcrossAllNICs'
label={i18n('Protocol with Highest Traffic Profile across all NICs')}
type='select'
- pointer='/network/networkCapacity/protocolWithHighestTrafficProfileAcrossAllNICs'/>
+ 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'>
- <ValidationInput
+ <Input
+ data-test-id='networkTransactionsPerSecond'
label={i18n('Network Transactions per Second')}
- type='text'
- pointer='/network/networkCapacity/networkTransactionsPerSecond'/>
+ 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>
- </ValidationForm>
+ </Form> }
</div>
{this.renderNicList()}
</div>
@@ -70,18 +104,16 @@ class SoftwareProductComponentsNetworkView extends React.Component {
renderNicList() {
const {localFilter} = this.state;
- let {onAddNIC, manualMode, isReadOnlyMode} = this.props;
- let onAdd = manualMode ? onAddNIC : false;
+ let {isReadOnlyMode} = this.props;
return (
<ListEditorView
title={i18n('Interfaces')}
- plusButtonTitle={i18n('Add NIC')}
filterValue={localFilter}
placeholder={i18n('Filter NICs by Name')}
- onAdd={onAdd}
isReadOnlyMode={isReadOnlyMode}
- onFilter={filter => this.setState({localFilter: filter})}>
- {!manualMode && this.filterList().map(nic => this.renderNicListItem(nic, isReadOnlyMode))}
+ onFilter={value => this.setState({localFilter: value})}
+ twoColumns>
+ {this.filterList().map(nic => this.renderNicListItem(nic, isReadOnlyMode))}
</ListEditorView>
);
}
@@ -92,22 +124,22 @@ class SoftwareProductComponentsNetworkView extends React.Component {
return (
<ListEditorItemView
key={id}
- className='list-editor-item-view'
isReadOnlyMode={isReadOnlyMode}
onSelect={() => onEditNicClick(nic, version)}>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Name')}</div>
+ <ListEditorItemViewField>
<div className='name'>{name}</div>
- </div>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Purpose of NIC')}</div>
- <div className='description'>{description}</div>
- </div>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Network')}</div>
- <div className='artifact-name'>{networkName}</div>
- </div>
+ </ListEditorItemViewField>
+ <ListEditorItemViewField>
+ <div className='details'>
+ <div className='title'>{i18n('Purpose of NIC')}</div>
+ <div className='description'>{description}</div>
+ </div>
+ <div className='details'>
+ <div className='title'>{i18n('Network')}</div>
+ <div className='artifact-name'>{networkName}</div>
+ </div>
+ </ListEditorItemViewField>
</ListEditorItemView>
);
@@ -128,8 +160,8 @@ class SoftwareProductComponentsNetworkView extends React.Component {
}
save() {
- let {onSubmit, qdata} = this.props;
- return onSubmit({qdata});
+ let {onSubmit, qdata, version} = this.props;
+ return onSubmit({qdata, version});
}
}
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
new file mode 100644
index 0000000000..524b95c3ad
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Acceptable.jsx
@@ -0,0 +1,75 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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>
+ <GridItem colSpan={3}>
+ <div className='part-title-small packets'>{i18n('Acceptable Jitter')}</div>
+ </GridItem>
+ <GridItem>
+ <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>
+ <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
new file mode 100644
index 0000000000..3745fc7c2e
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/FlowLength.jsx
@@ -0,0 +1,35 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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'},
+];
+
+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
new file mode 100644
index 0000000000..5476ed90e6
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/InFlowTraffic.jsx
@@ -0,0 +1,35 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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'},
+];
+
+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
new file mode 100644
index 0000000000..b3a5d21625
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/IpConfig.jsx
@@ -0,0 +1,45 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+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 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
new file mode 100644
index 0000000000..3dc153d27f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx
@@ -0,0 +1,54 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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, isReadOnlyMode, name, description}) => {
+
+ return (
+ <GridSection>
+ <GridItem colSpan={2}>
+ <Input
+ label={i18n('Name')}
+ value={name}
+ data-test-id='nic-name'
+ disabled={true}
+ type='text' />
+ </GridItem>
+ <GridItem colSpan={2}>
+ <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: React.PropTypes.string,
+ description: React.PropTypes.array,
+ onDataChanged: React.PropTypes.func,
+ isReadOnlyMode: React.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
new file mode 100644
index 0000000000..43afdbed3a
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx
@@ -0,0 +1,62 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import 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 Network = ({networkValues}) => {
+ return (
+ <GridSection title={i18n('Network')}>
+ <GridItem>
+ <Input
+ label={i18n('Internal')}
+ disabled
+ checked={true}
+ data-test-id='nic-internal'
+ className='network-radio disabled'
+ type='radio'/>
+ </GridItem>
+ <GridItem>
+ <Input
+ label={i18n('External')}
+ disabled
+ checked={false}
+ data-test-id='nic-external'
+ className='network-radio disabled'
+ type='radio'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <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: React.PropTypes.array
+};
+
+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
new file mode 100644
index 0000000000..80a3d1579b
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/OutFlowTraffic.jsx
@@ -0,0 +1,35 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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'},
+];
+
+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
new file mode 100644
index 0000000000..d7ee91bd15
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/PacketsBytes.jsx
@@ -0,0 +1,65 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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}) => {
+ return (
+ <GridItem>
+ <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: React.PropTypes.string,
+ value: React.PropTypes.string
+};
+
+const PacketsBytes = ({title, pointers = [], qgenericFieldInfo, dataMap, onQDataChanged}) => {
+ return(
+ <GridSection title={title}>
+ <GridItem colSpan={2}>
+ <div className='part-title-small packets'>{i18n('Packets')}</div>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <div className='part-title-small bytes'>{i18n('Bytes')}</div>
+ </GridItem>
+ {pointers.map(pointer => {return (<PointerInput key={pointer.value} label={pointer.label} value={pointer.value}
+ qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged} dataMap={dataMap} />);})}
+ </GridSection>
+ );
+};
+
+PacketsBytes.PropTypes = {
+ title: React.PropTypes.string,
+ pointers: React.PropTypes.array,
+ onQDataChanged: React.PropTypes.function,
+ dataMap: React.PropTypes.object,
+ qgenericFieldInfo: React.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
new file mode 100644
index 0000000000..3e8a9f4e77
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Protocols.jsx
@@ -0,0 +1,74 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+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')}>
+ <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}>
+ <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: React.PropTypes.array,
+ onQDataChanged: React.PropTypes.function,
+ dataMap: React.PropTypes.object,
+ qgenericFieldInfo: React.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
new file mode 100644
index 0000000000..1dd0045f7b
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Sizing.jsx
@@ -0,0 +1,39 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import 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')}>
+ <GridItem colSpan={4}>
+ <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 d535a34a82..b2133ad5d8 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
@@ -1,69 +1,65 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes} from './SoftwareProductComponentProcessesConstants.js';
-function baseUrl(softwareProductId, componentId) {
+function baseUrl(softwareProductId, version, componentId) {
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/components/${componentId}/processes`;
+ return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${version.id}/components/${componentId}/processes`;
}
-function fetchProcessesList({softwareProductId, componentId, version}) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId)}${versionQuery}`);
+function fetchProcessesList({softwareProductId, version, componentId}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`);
}
-function deleteProcess({softwareProductId, componentId, processId}) {
- return RestAPIUtil.destroy(`${baseUrl(softwareProductId, componentId)}/${processId}`);
+function deleteProcess({softwareProductId, version, componentId, processId}) {
+ return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${processId}`);
}
-function putProcess({softwareProductId, componentId, process}) {
- return RestAPIUtil.save(`${baseUrl(softwareProductId, componentId)}/${process.id}`, {
+function putProcess({softwareProductId, version, componentId, process}) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${process.id}`, {
name: process.name,
- description: process.description
+ description: process.description,
+ type: process.type === '' ? null : process.type
});
}
-function postProcess({softwareProductId,componentId, process}) {
- return RestAPIUtil.create(`${baseUrl(softwareProductId, componentId)}`, {
+function postProcess({softwareProductId, version, componentId, process}) {
+ return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}`, {
name: process.name,
- description: process.description
+ description: process.description,
+ type: process.type === '' ? null : process.type
});
}
-function uploadFileToProcess({softwareProductId, processId, componentId, formData}) {
- return RestAPIUtil.create(`${baseUrl(softwareProductId, 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, componentId, version}) {
+ fetchProcessesList(dispatch, {softwareProductId, version, componentId}) {
dispatch({
type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES,
processesList: []
});
- return fetchProcessesList({softwareProductId, componentId, version}).then(response => {
+ return fetchProcessesList({softwareProductId, version, componentId}).then(response => {
dispatch({
type: actionTypes.FETCH_SOFTWARE_PRODUCT_COMPONENTS_PROCESSES,
processesList: response.results
@@ -71,8 +67,8 @@ const SoftwareProductComponentProcessesActionHelper = {
});
},
- deleteProcess(dispatch, {process, softwareProductId, componentId}) {
- return deleteProcess({softwareProductId, processId:process.id, componentId}).then(() => {
+ 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
@@ -81,11 +77,11 @@ const SoftwareProductComponentProcessesActionHelper = {
},
- saveProcess(dispatch, {softwareProductId, componentId, previousProcess, process}) {
+ saveProcess(dispatch, {softwareProductId, version, componentId, previousProcess, process}) {
if (previousProcess) {
- return putProcess({softwareProductId,componentId, process}).then(() => {
+ return putProcess({softwareProductId, version, componentId, process}).then(() => {
if (process.formData && process.formData.name !== previousProcess.artifactName){
- uploadFileToProcess({softwareProductId, processId: process.id, formData: process.formData, componentId});
+ uploadFileToProcess({softwareProductId, version, processId: process.id, formData: process.formData, componentId});
}
dispatch({
type: actionTypes.EDIT_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
@@ -94,9 +90,9 @@ const SoftwareProductComponentProcessesActionHelper = {
});
}
else {
- return postProcess({softwareProductId, componentId, process}).then(response => {
+ return postProcess({softwareProductId, version, componentId, process}).then(response => {
if (process.formData) {
- uploadFileToProcess({softwareProductId, processId: response.value, formData: process.formData, componentId});
+ uploadFileToProcess({softwareProductId, version, processId: response.value, formData: process.formData, componentId});
}
dispatch({
type: actionTypes.ADD_SOFTWARE_PRODUCT_COMPONENTS_PROCESS,
@@ -133,12 +129,6 @@ const SoftwareProductComponentProcessesActionHelper = {
dispatch({
type:actionTypes.SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_CLOSE
});
- },
- processEditorDataChanged(dispatch, {deltaData}) {
- dispatch({
- type: actionTypes.processEditor.DATA_CHANGED,
- deltaData
- });
}
};
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 78a111a426..d15432b3fb 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
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
@@ -27,8 +22,15 @@ export const actionTypes = keyMirror({
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,
- processEditor: {
- DATA_CHANGED: 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'}
+ ]
+};
+
+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 0138023c30..9502e24b1a 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
@@ -1,31 +1,29 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+import 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';
-const mapStateToProps = ({softwareProduct}) => {
+export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductComponents: {componentProcesses = {}}} = softwareProduct;
let {processesList = [], processesEditor = {}} = componentProcesses;
- let {data} = processesEditor;
+ let {data, genericFieldInfo, formReady} = processesEditor;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
let previousData;
const processId = data ? data.id : null;
@@ -35,19 +33,23 @@ const mapStateToProps = ({softwareProduct}) => {
return {
data,
- previousData
+ genericFieldInfo,
+ previousData,
+ isFormValid,
+ formReady
};
};
-const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
+const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
return {
- onDataChanged: deltaData => SoftwareProductComponentProcessesActionHelper.processEditorDataChanged(dispatch, {deltaData}),
+ 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, previousProcess, componentId, process});
- }
+ SoftwareProductComponentProcessesActionHelper.saveProcess(dispatch, {softwareProductId, version, previousProcess, componentId, process});
+ },
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, SOFTWARE_PRODUCT_PROCESS_COMPONENTS_EDITOR_FORM)
};
};
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 f859f690e8..9afaa6d5fd 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
@@ -1,43 +1,53 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from './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 {};
-
- case actionTypes.processEditor.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
- }
- };
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 ca6d843af7..18f2ee129c 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
@@ -1,18 +1,48 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import Dropzone from 'react-dropzone';
-
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import {optionsInputValues as ComponentProcessesOptionsInputValues} from './SoftwareProductComponentProcessesConstants.js';
+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';
const SoftwareProductProcessEditorPropType = React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string,
description: React.PropTypes.string,
- artifactName: React.PropTypes.string
+ artifactName: React.PropTypes.string,
+ type: React.PropTypes.string
});
+const FileUploadBox = ({onClick}) => {
+ return (
+ <div className='file-upload-box'>
+ <div className='drag-text'>{i18n('Drag & drop for upload')}</div>
+ <div className='or-text'>{i18n('or')}</div>
+ <div className='upload-btn primary-btn' onClick={onClick}>
+ <span className='primary-btn-text'>{i18n('Select file')}</span>
+ </div>
+ </div>
+ );
+};
+
class SoftwareProductProcessesEditorView extends React.Component {
state = {
@@ -30,65 +60,91 @@ class SoftwareProductProcessesEditorView extends React.Component {
};
render() {
- let {isReadOnlyMode, onCancel, onDataChanged, data = {}} = this.props;
- let {name, description, artifactName} = data;
+ let {isReadOnlyMode, onCancel, onDataChanged, genericFieldInfo, data = {}} = this.props;
+ let {name, description, artifactName, type} = data;
return (
<div>
- <ValidationForm
+ { genericFieldInfo && <Form
ref='validationForm'
isReadOnlyMode={isReadOnlyMode}
hasButtons={true}
labledButtons={true}
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={files => this.handleImportSubmit(files)}
- onDragEnter={() => this.setState({dragging:true})}
- onDragLeave={() => this.setState({dragging:false})}
- multiple={false}
- disableClick={true}
- ref='processEditorFileInput'
- name='processEditorFileInput'
- accept='*.*'>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- onChange={name => onDataChanged({name})}
- label={i18n('Name')}
- value={name}
- validations={{validateName: true, maxLength: 120, required: true}}
- type='text'/>
- <ValidationInput
- label={i18n('Artifacts')}
- value={artifactName}
- type='text'
- disabled/>
- </div>
- <div className='col-md-6'>
- <div className='file-upload-box'>
- <div className='drag-text'>{i18n('Drag & drop for upload')}</div>
- <div className='or-text'>{i18n('or')}</div>
- <div className='upload-btn primary-btn' onClick={() => this.refs.processEditorFileInput.open()}>
- <span className='primary-btn-text'>{i18n('Select file')}</span>
- </div>
- </div>
- </div>
- </div>
- <ValidationInput
- onChange={description => onDataChanged({description})}
- label={i18n('Notes')}
- value={description}
- name='vsp-process-description'
- className='vsp-process-description'
- validations={{maxLength: 1000}}
- type='textarea'/>
- </Dropzone>
- </div>
- </ValidationForm>
+ <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>
+ <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}>
+ <FileUploadBox onClick={() => this.refs.processEditorFileInput.open()} />
+ </GridItem>
+ </GridSection>
+ <GridSection>
+ <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}>
+ <Input
+ label={i18n('Artifacts')}
+ data-test-id='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')}
+ data-test-id='process-type'
+ isValid={genericFieldInfo.type.isValid}
+ errorText={genericFieldInfo.type.errorText}
+ type='select'
+ className='input-options-select'
+ groupClassName='bootstrap-input-options' >
+ {ComponentProcessesOptionsInputValues.PROCESS_TYPE.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+ </GridItem>
+ </GridSection>
+ </Dropzone>
+ </div>
+ </Form>}
</div>
);
}
@@ -110,14 +166,25 @@ class SoftwareProductProcessesEditorView extends React.Component {
}
- handleImportSubmit(files) {
- let {onDataChanged} = this.props;
- this.setState({
- dragging: false,
- complete: '0',
- files
- });
- onDataChanged({artifactName: files[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);
+ }
+ }
+
}
}
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 5f6932897e..a8cb709194 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
@@ -1,30 +1,27 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
import SoftwareProductComponentProcessesActionHelper from './SoftwareProductComponentProcessesActionHelper.js';
import SoftwareProductComponentsProcessesListView from './SoftwareProductComponentsProcessesListView.jsx';
-const mapStateToProps = ({softwareProduct}) => {
+export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data:currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents: {componentProcesses = {}}} = softwareProduct;
let{processesList = [], processesEditor = {}} = componentProcesses;
@@ -42,12 +39,19 @@ const mapStateToProps = ({softwareProduct}) => {
};
-const mapActionsToProps = (dispatch, {softwareProductId}) => {
+const mapActionsToProps = (dispatch, {componentId, softwareProductId}) => {
return {
onAddProcess: () => SoftwareProductComponentProcessesActionHelper.openEditor(dispatch),
onEditProcessClick: (process) => SoftwareProductComponentProcessesActionHelper.openEditor(dispatch, process),
- onDeleteProcessClick: (process) => SoftwareProductComponentProcessesActionHelper.openDeleteProcessesConfirm(dispatch, {process, softwareProductId})
+ onDeleteProcessClick: (process, version) => dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n('Are you sure you want to delete "{name}"?', {name: process.name}),
+ onConfirmed: ()=> SoftwareProductComponentProcessesActionHelper.deleteProcess(dispatch,
+ {process, softwareProductId, version, componentId})
+ }
+ })
};
};
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 4bb124d52f..98e24a9c21 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
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductComponentProcessesConstants.js';
export default (state = [], action) => {
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesConfirmationModal.jsx
deleted file mode 100644
index 48fa862364..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesConfirmationModal.jsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import React from 'react';
-import {connect} from 'react-redux';
-import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
-import SoftwareProductComponentProcessesActionHelper from './SoftwareProductComponentProcessesActionHelper.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-function renderMsg(processToDelete) {
- let name = processToDelete ? processToDelete.name : '';
- let msg = i18n('Are you sure you want to delete "{name}"?', {name});
- return (
- <div>
- <p>{msg}</p>
- </div>
- );
-};
-
-const mapStateToProps = ({softwareProduct}) => {
- let {softwareProductEditor, softwareProductComponents} = softwareProduct;
- let {componentProcesses} = softwareProductComponents;
- let {processToDelete} = componentProcesses;
- let softwareProductId = softwareProductEditor.data.id;
- const show = processToDelete !== false;
- return {
- show,
- title: 'Warning!',
- type: 'warning',
- msg: renderMsg(processToDelete),
- confirmationDetails: {processToDelete, softwareProductId}
- };
-};
-
-const mapActionsToProps = (dispatch,{componentId, softwareProductId}) => {
- return {
- onConfirmed: ({processToDelete}) => {
- SoftwareProductComponentProcessesActionHelper.deleteProcess(dispatch, {process: processToDelete, softwareProductId, componentId});
- SoftwareProductComponentProcessesActionHelper.hideDeleteConfirm(dispatch);
- },
- onDeclined: () => {
- SoftwareProductComponentProcessesActionHelper.hideDeleteConfirm(dispatch);
- }
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
-
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 a8b07e9194..650d6d5ebc 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
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import Modal from 'nfvo-components/modal/Modal.jsx';
@@ -6,7 +21,6 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import SoftwareProductProcessesEditor from './SoftwareProductComponentProcessesEditor.js';
-import SoftwareProductComponentsProcessesConfirmationModal from './SoftwareProductComponentsProcessesConfirmationModal.jsx';
class SoftwareProductProcessesView extends React.Component {
@@ -22,12 +36,11 @@ class SoftwareProductProcessesView extends React.Component {
isModalInEditMode: React.PropTypes.bool,
onStorageSelect: React.PropTypes.func,
componentId: React.PropTypes.string,
- softwareProductId: React.PropTypes.string
+ softwareProductId: React.PropTypes.string,
+ currentSoftwareProduct: React.PropTypes.object
};
render() {
- let { softwareProductId, componentId} = this.props;
-
return (
<div className='vsp-processes-page'>
<div className='software-product-view'>
@@ -35,18 +48,15 @@ class SoftwareProductProcessesView extends React.Component {
{this.renderEditor()}
{this.renderProcessList()}
</div>
- <SoftwareProductComponentsProcessesConfirmationModal
- componentId={componentId}
- softwareProductId={softwareProductId}/>
</div>
</div>
);
}
renderEditor() {
- let {softwareProductId, componentId, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
+ let {softwareProductId, currentSoftwareProduct: {version}, componentId, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props;
return (
- <Modal show={isDisplayModal} bsSize='large' animation={true}>
+ <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>
@@ -54,6 +64,7 @@ class SoftwareProductProcessesView extends React.Component {
<SoftwareProductProcessesEditor
componentId={componentId}
softwareProductId={softwareProductId}
+ version={version}
isReadOnlyMode={isReadOnlyMode}/>
</Modal.Body>
</Modal>
@@ -72,7 +83,8 @@ class SoftwareProductProcessesView extends React.Component {
placeholder={i18n('Filter Process')}
onAdd={onAddProcess}
isReadOnlyMode={isReadOnlyMode}
- onFilter={filter => this.setState({localFilter: filter})}>
+ title={i18n('Process Details')}
+ onFilter={value => this.setState({localFilter: value})}>
{this.filterList().map(processes => this.renderProcessListItem(processes, isReadOnlyMode))}
</ListEditorView>
</div>
@@ -81,14 +93,14 @@ class SoftwareProductProcessesView extends React.Component {
renderProcessListItem(process, isReadOnlyMode) {
let {id, name, description, artifactName = ''} = process;
- let {onEditProcessClick, onDeleteProcessClick} = this.props;
+ let {currentSoftwareProduct: {version}, onEditProcessClick, onDeleteProcessClick} = this.props;
return (
<ListEditorItemView
key={id}
className='list-editor-item-view'
isReadOnlyMode={isReadOnlyMode}
onSelect={() => onEditProcessClick(process)}
- onDelete={() => onDeleteProcessClick(process)}>
+ onDelete={() => onDeleteProcessClick(process, version)}>
<div className='list-editor-item-view-field'>
<div className='title'>{i18n('Name')}</div>
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 fbd3f81ec2..18a3b1e8ff 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
@@ -1,47 +1,48 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+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';
+
const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct;
- let {componentEditor: {data: componentData , qdata, qschema}} = softwareProductComponents;
+ let {componentEditor: {data: componentData , qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap}} = softwareProductComponents;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentVSP);
return {
componentData,
qdata,
- qschema,
- isReadOnlyMode
+ isReadOnlyMode,
+ qGenericFieldInfo,
+ dataMap
};
};
-const mapActionToProps = (dispatch, {softwareProductId, componentId}) => {
+const mapActionToProps = (dispatch, {softwareProductId, version, componentId}) => {
return {
- onQDataChanged: ({data}) => SoftwareProductComponentsActionHelper.componentQuestionnaireUpdated(dispatch, {data}),
- onSubmit: ({qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch, {softwareProductId, vspComponentId: componentId, qdata});}
+ onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}),
+ onSubmit: ({componentData, qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch,
+ {softwareProductId, version, vspComponentId: componentId, componentData, qdata});
+ }
};
};
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 9c9600c376..28bdf8e5e5 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
@@ -1,8 +1,156 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from'nfvo-components/input/validation/ValidationInput.jsx';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+import 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 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>
+);
class SoftwareProductComponentStorageView extends React.Component {
@@ -14,110 +162,28 @@ class SoftwareProductComponentStorageView extends React.Component {
};
render() {
- let {qdata, qschema, onQDataChanged, onSubmit, isReadOnlyMode} = this.props;
+ let {onQDataChanged, dataMap, qGenericFieldInfo, isReadOnlyMode, onSubmit, qdata} = this.props;
return(
<div className='vsp-component-questionnaire-view'>
- <ValidationForm
- ref='storageValidationForm'
- hasButtons={false}
+ {qGenericFieldInfo && <Form
+ ref={form => this.form = form }
+ isValid={true}
+ formReady={null}
onSubmit={() => onSubmit({qdata})}
className='component-questionnaire-validation-form'
isReadOnlyMode={isReadOnlyMode}
- onDataChanged={onQDataChanged}
- data={qdata}
- schema={qschema}>
-
- <div className='section-title'>{i18n('Backup')}</div>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <div className='vertical-flex'>
- <label key='label' className='control-label'>{i18n('Backup Type')}</label>
- <div className='radio-options-content-row'>
- <ValidationInput
- label={i18n('On Site')}
- type='radiogroup'
- pointer={'/storage/backup/backupType'}
- className='radio-field'/>
- </div>
- </div>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Backup Solution')}
- pointer={'/storage/backup/backupSolution'}
- className='section-field'/>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Backup Storage Size (GB)')}
- pointer={'/storage/backup/backupStorageSize'}
- className='section-field'/>
- </div>
- <ValidationInput
- type='select'
- label={i18n('Backup NIC')}
- pointer={'/storage/backup/backupNIC'}
- className='section-field'/>
- </div>
- </div>
-
- <div className='section-title'>{i18n('Snapshot Backup')}</div>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Snapshot Frequency (hours)')}
- pointer={'/storage/snapshotBackup/snapshotFrequency'}
- className='section-field'/>
- </div>
- <div className='empty-two-col' />
- <div className='empty-col' />
- </div>
- </div>
-
- <div className='section-title'>{i18n('Log Backup')}</div>
- <div className='rows-section'>
- <div className='row-flex-components input-row'>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Size of Log Files (GB)')}
- pointer={'/storage/logBackup/sizeOfLogFiles'}
- className='section-field'/>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Log Retention Period (days)')}
- pointer={'/storage/logBackup/logRetentionPeriod'}
- className='section-field'/>
- </div>
- <div className='single-col'>
- <ValidationInput
- type='text'
- label={i18n('Log Backup Frequency (days)')}
- pointer={'/storage/logBackup/logBackupFrequency'}
- className='section-field'/>
- </div>
- <ValidationInput
- type='text'
- label={i18n('Log File Location')}
- pointer={'/storage/logBackup/logFileLocation'}
- className='section-field'/>
- </div>
- </div>
- </ValidationForm>
+ 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(){
- return this.refs.storageValidationForm.handleFormSubmit(new Event('dummy'));
+ return this.form.handleFormSubmit(new Event('dummy'));
}
}
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 46308f0045..19e2d5b0db 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js
@@ -1,48 +1,62 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
import SoftwareProductCreationActionHelper from './SoftwareProductCreationActionHelper.js';
import SoftwareProductCreationView from './SoftwareProductCreationView.jsx';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import SoftwareProductActionHelper from '../SoftwareProductActionHelper.js';
+
+export const mapStateToProps = ({finalizedLicenseModelList, softwareProductList, softwareProduct: {softwareProductCreation, softwareProductCategories} }) => {
+ let {genericFieldInfo} = softwareProductCreation;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
+ let VSPNames = {};
+ for (let i = 0; i < softwareProductList.length; i++) {
+ VSPNames[softwareProductList[i].name] = softwareProductList[i].id;
+ }
-const mapStateToProps = ({finalizedLicenseModelList, softwareProduct: {softwareProductCreation, softwareProductCategories} }) => {
return {
data: softwareProductCreation.data,
+ selectedVendorId: softwareProductCreation.selectedVendorId,
+ disableVendor: softwareProductCreation.disableVendor,
softwareProductCategories,
- finalizedLicenseModelList
+ finalizedLicenseModelList,
+ isFormValid,
+ formReady: softwareProductCreation.formReady,
+ genericFieldInfo,
+ VSPNames
};
};
-const mapActionsToProps = (dispatch) => {
+export const mapActionsToProps = (dispatch) => {
return {
- onDataChanged: deltaData => SoftwareProductCreationActionHelper.changeData(dispatch, {deltaData}),
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onCancel: () => SoftwareProductCreationActionHelper.resetData(dispatch),
onSubmit: (softwareProduct) => {
SoftwareProductCreationActionHelper.resetData(dispatch);
- SoftwareProductCreationActionHelper.createSoftwareProduct(dispatch, {softwareProduct}).then(softwareProductId => {
- let {vendorId: licenseModelId, licensingVersion} = softwareProduct;
- OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId, licenseModelId, licensingVersion});
+ SoftwareProductCreationActionHelper.createSoftwareProduct(dispatch, {softwareProduct}).then(response => {
+ SoftwareProductActionHelper.fetchSoftwareProductList(dispatch).then(() => {
+ let {vendorId: licenseModelId, licensingVersion} = softwareProduct;
+ OnboardingActionHelper.navigateToSoftwareProductLandingPage(dispatch, {softwareProductId: response.vspId, licenseModelId, licensingVersion});
+ });
});
- }
+ },
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
};
};
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 f4e51f198e..3b434e3ba4 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js
@@ -1,29 +1,26 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import 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} 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');
@@ -31,7 +28,7 @@ function baseUrl() {
}
function createSoftwareProduct(softwareProduct) {
- return RestAPIUtil.create(baseUrl(), {
+ return RestAPIUtil.post(baseUrl(), {
...softwareProduct,
icon: 'icon',
licensingData: {}
@@ -40,36 +37,39 @@ function createSoftwareProduct(softwareProduct) {
const SoftwareProductCreationActionHelper = {
- open(dispatch) {
+ open(dispatch, vendorId) {
SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
dispatch({
- type: actionTypes.OPEN
+ type: actionTypes.OPEN,
+ selectedVendorId: vendorId
});
+
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_SHOW,
+ data: {
+ modalComponentName: modalContentMapper.SOFTWARE_PRODUCT_CREATION,
+ title: i18n('New Software Product'),
+ modalComponentProps: {
+ vendorId
+ }
+ }
+ });
+
},
resetData(dispatch) {
+
dispatch({
- type: actionTypes.RESET_DATA
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
});
- },
- changeData(dispatch, {deltaData}) {
dispatch({
- type: actionTypes.DATA_CHANGED,
- deltaData
+ type: actionTypes.RESET_DATA
});
},
createSoftwareProduct(dispatch, {softwareProduct}) {
- return createSoftwareProduct(softwareProduct).then(response => {
- SoftwareProductActionHelper.addSoftwareProduct(dispatch, {
- softwareProduct: {
- ...softwareProduct,
- id: response.vspId
- }
- });
- return response.vspId;
- });
+ return createSoftwareProduct(softwareProduct);
}
};
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 0a9cdb911c..241d7985b1 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js
@@ -1,27 +1,23 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
OPEN: null,
- RESET_DATA: null,
- DATA_CHANGED: null
+ RESET_DATA: 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 5e3db09e56..f7a738518e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js
@@ -1,40 +1,58 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from './SoftwareProductCreationConstants.js';
+import {actionTypes, SP_CREATION_FORM_NAME} from './SoftwareProductCreationConstants.js';
export default (state = {}, action) => {
switch (action.type) {
case actionTypes.OPEN:
return {
...state,
- data: {},
- showModal: true
- };
- case actionTypes.DATA_CHANGED:
- return {
- ...state,
+ formName: SP_CREATION_FORM_NAME,
+ disableVendor: action.selectedVendorId ? true : false,
data: {
- ...state.data,
- ...action.deltaData
- }
+ 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}]
+ }
+ },
+ showModal: true
};
case actionTypes.RESET_DATA:
return {};
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 2c8f243457..11b696855b 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationView.jsx
@@ -1,11 +1,28 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
+import Validator from 'nfvo-utils/Validator.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import {SP_CREATION_FORM_NAME} from './SoftwareProductCreationConstants.js';
+import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js';
-
const SoftwareProductPropType = React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string,
@@ -21,50 +38,66 @@ class SoftwareProductCreationView extends React.Component {
data: SoftwareProductPropType,
finalizedLicenseModelList: React.PropTypes.array,
softwareProductCategories: React.PropTypes.array,
+ VSPNames: React.PropTypes.object,
onDataChanged: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired,
onCancel: React.PropTypes.func.isRequired
};
render() {
- let {softwareProductCategories, data = {}, onDataChanged, onCancel} = this.props;
+ let {softwareProductCategories, data = {}, onDataChanged, onCancel, genericFieldInfo, disableVendor} = this.props;
let {name, description, vendorId, subCategory} = data;
const vendorList = this.getVendorList();
-
return (
<div className='software-product-creation-page'>
- <ValidationForm
- ref='validationForm'
+ { genericFieldInfo && <Form
+ ref={(validationForm) => this.validationForm = validationForm}
hasButtons={true}
onSubmit={() => this.submit() }
onReset={() => onCancel() }
- labledButtons={true}>
+ labledButtons={true}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.validate() }>
<div className='software-product-form-row'>
<div className='software-product-inline-section'>
- <ValidationInput
+ <Input
value={name}
label={i18n('Name')}
- ref='software-product-name'
- onChange={name => onDataChanged({name})}
- validations={{validateName: true, maxLength: 25, required: true}}
+ 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'/>
- <ValidationInput
- onEnumChange={vendorId => onDataChanged({vendorId})}
- value={vendorId}
+ className='field-section'
+ data-test-id='new-vsp-name' />
+ <Input
label={i18n('Vendor')}
- values={vendorList}
- validations={{required: true}}
type='select'
- className='field-section'/>
- <ValidationInput
+ value={vendorId}
+ 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}
- onChange={subCategory => this.onSelectSubCategory(subCategory)}
- validations={{required: true}}
- className='options-input-category'>
+ 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 &&
@@ -74,20 +107,23 @@ class SoftwareProductCreationView extends React.Component {
<option key={sub.uniqueId} value={sub.uniqueId}>{`${sub.name} (${category.name})`}</option>)}
</optgroup>)
}
- </ValidationInput>
+ </Input>
</div>
<div className='software-product-inline-section'>
- <ValidationInput
+ <Input
value={description}
label={i18n('Description')}
- ref='description'
- onChange={description => onDataChanged({description})}
- validations={{freeEnglishText: true, maxLength: 1000, required: true}}
+ 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'/>
+ className='field-section'
+ data-test-id='new-vsp-description' />
</div>
</div>
- </ValidationForm>
+ </Form>}
</div>
);
}
@@ -95,29 +131,47 @@ class SoftwareProductCreationView extends React.Component {
getVendorList() {
let {finalizedLicenseModelList} = this.props;
- return [{enum: '', title: i18n('please select...')}].concat(finalizedLicenseModelList.map(vendor => {
- return {
- enum: vendor.id,
- title: vendor.vendorName
- };
- }));
+ return [{enum: '', title: i18n('please select...')}].concat(
+ sortByStringProperty(finalizedLicenseModelList, 'vendorName').map(vendor => {
+ return {
+ enum: vendor.id,
+ title: vendor.vendorName
+ };
+ })
+ );
}
- onSelectSubCategory(subCategory) {
- let {softwareProductCategories, onDataChanged} = this.props;
- let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(subCategory, softwareProductCategories);
- onDataChanged({category, subCategory});
+ onSelectVendor(e) {
+ const selectedIndex = e.target.selectedIndex;
+ const vendorId = e.target.options[selectedIndex].value;
+ this.props.onDataChanged({vendorId},SP_CREATION_FORM_NAME);
}
- create(){
- this.refs.validationForm.handleFormSubmit(new Event('dummy'));
+ 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() {
- const {data:softwareProduct, finalizedLicenseModelList} = this.props;
+ let {data:softwareProduct, finalizedLicenseModelList} = this.props;
softwareProduct.vendorName = finalizedLicenseModelList.find(vendor => vendor.id === softwareProduct.vendorId).vendorName;
this.props.onSubmit(softwareProduct);
}
+
+ 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);
+ }
}
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
new file mode 100644
index 0000000000..9540d3f869
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependencies.js
@@ -0,0 +1,40 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import {connect} from 'react-redux';
+
+import SoftwareProductDependenciesView from './SoftwareProductDependenciesView.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import SoftwareProductDependenciesActionHelper from './SoftwareProductDependenciesActionHelper.js';
+
+export const mapStateToProps = ({softwareProduct}) => {
+ let {softwareProductEditor: {data: currentSoftwareProduct = {}}, softwareProductDependencies, softwareProductComponents: {componentsList}} = softwareProduct;
+ let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+ return {
+ isReadOnlyMode,
+ softwareProductDependencies: softwareProductDependencies.length ? softwareProductDependencies : [{sourceId: '', targetId: '', relationType: 'dependsOn', id: 'fake'}],
+ componentsOptions: componentsList.map(component => ({value: component.id, label: component.name}))
+ };
+};
+
+const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
+ return {
+ onDataChanged: dependenciesList => SoftwareProductDependenciesActionHelper.updateDependencyList(dispatch, {dependenciesList}),
+ onAddDependency: () => SoftwareProductDependenciesActionHelper.addDependency(dispatch),
+ onSubmit: (dependenciesList) => SoftwareProductDependenciesActionHelper.saveDependencies(dispatch, {softwareProductId, version, dependenciesList})
+ };
+};
+
+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
new file mode 100644
index 0000000000..e47b33a577
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesActionHelper.js
@@ -0,0 +1,58 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {actionTypes} from './SoftwareProductDependenciesConstants.js';
+import uuid from 'uuid-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-dependency-model`;
+}
+
+function fetchDependency(softwareProductId, version) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
+}
+
+function postDependency(softwareProductId, version, dependenciesList) {
+ let modifedDependencyList = dependenciesList ? dependenciesList.filter(item => item.sourceId && item.targetId)
+ .map(item => ({sourceId: item.sourceId, targetId: item.targetId, relationType: item.relationType})) : [];
+ return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {componentDependencyModels:modifedDependencyList});
+}
+
+const SoftwareProductDependenciesActionHelper = {
+ updateDependencyList(dispatch, {dependenciesList}) {
+ dispatch({type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE, dependenciesList});
+ },
+ addDependency(dispatch) {
+ dispatch({type: actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY});
+ },
+ fetchDependencies(dispatch, {softwareProductId, version}) {
+ return fetchDependency(softwareProductId, version).then( response => {
+ const dependenciesList = response.results ? response.results.map(item => {return {...item, id: uuid.create().toString()};}) : [];
+ dispatch({
+ type: actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE,
+ dependenciesList
+ });
+ });
+ },
+ saveDependencies(dispatch, {softwareProductId, version, dependenciesList}) {
+ return postDependency(softwareProductId, version, dependenciesList);
+ }
+};
+
+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
new file mode 100644
index 0000000000..1f27ed8311
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesConstants.js
@@ -0,0 +1,29 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+import keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+ SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE: null,
+ ADD_SOFTWARE_PRODUCT_DEPENDENCY: null
+});
+
+export const relationTypes = {
+ DEPENDS_ON: 'dependsOn'
+};
+
+export const relationTypesOptions = [
+ {value: relationTypes.DEPENDS_ON, label: 'Depends On'}
+];
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js
new file mode 100644
index 0000000000..3fb479eedc
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesReducer.js
@@ -0,0 +1,36 @@
+
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import {actionTypes, relationTypes} from './SoftwareProductDependenciesConstants.js';
+import {checkCyclesAndMarkDependencies} from './SoftwareProductDependenciesUtils.js';
+import uuid from 'uuid-js';
+
+export default (state = [], action) => {
+ switch (action.type) {
+ case actionTypes.SOFTWARE_PRODUCT_DEPENDENCIES_LIST_UPDATE:
+ return checkCyclesAndMarkDependencies(action.dependenciesList);
+ case actionTypes.ADD_SOFTWARE_PRODUCT_DEPENDENCY:
+ return [...state, {
+ sourceId: null,
+ relationType: relationTypes.DEPENDS_ON,
+ targetId: null,
+ id: uuid.create()
+ }];
+ 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
new file mode 100644
index 0000000000..94d21bd49d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesUtils.js
@@ -0,0 +1,64 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import 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};
+}
+
+export function checkCyclesAndMarkDependencies(dependenciesList) {
+ 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});
+ }
+ }
+
+ 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
new file mode 100644
index 0000000000..da975a7be2
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx
@@ -0,0 +1,98 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+import 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} from './SoftwareProductDependenciesConstants.js';
+
+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);
+ }
+ });
+ }
+
+ render() {
+ let {componentsOptions, softwareProductDependencies, onDataChanged, onAddDependency, isReadOnlyMode} = this.props;
+ let canAdd = softwareProductDependencies.length < componentsOptions.length * (componentsOptions.length - 1);
+ 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];
+ }
+ });
+ return (
+ <div className='software-product-dependencies'>
+ <div className='software-product-dependencies-title'>{i18n('Dependencies')}</div>
+ <SelectActionTable
+ columns={['Source', 'Relation Type', 'Target']}
+ isReadOnlyMode={isReadOnlyMode}
+ onAdd={canAdd ? onAddDependency : undefined}
+ onAddItem={i18n('Add Rule')}>
+ {softwareProductDependencies.map(dependency => (
+ <SelectActionTableRow
+ key={dependency.id}
+ onDelete={() => onDataChanged(softwareProductDependencies.filter(currentDependency => currentDependency.id !== dependency.id))}
+ overlayMsg={i18n('There is a loop between selections')}
+ hasError={dependency.hasCycle}>
+ <SelectActionTableCell
+ options={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})}
+ selected={dependency.sourceId}
+ placeholder={i18n('Select VFC...')}
+ onChange={newSourceId => onDataChanged(softwareProductDependencies.map(currentDependency =>
+ ({...currentDependency, sourceId: currentDependency.id === dependency.id ? newSourceId : currentDependency.sourceId})
+ ))} />
+ <SelectActionTableCell options={relationTypesOptions} selected={dependency.relationType} clearable={false}/>
+ <SelectActionTableCell
+ placeholder={i18n('Select VFC...')}
+ options={this.filterTargets({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})}
+ selected={dependency.targetId}
+ onChange={newTargetId => onDataChanged(softwareProductDependencies.map(currentDependency =>
+ ({...currentDependency, targetId: currentDependency.id === dependency.id ? newTargetId : currentDependency.targetId})
+ ))} />
+ </SelectActionTableRow>
+ ))}
+ </SelectActionTable>
+ </div>
+ );
+ }
+
+ save() {
+ let {onSubmit, softwareProductDependencies} = this.props;
+ return onSubmit(softwareProductDependencies);
+ }
+}
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 16a100c664..ac0282e593 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetails.js
@@ -1,35 +1,33 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.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';
+
export const mapStateToProps = ({finalizedLicenseModelList, softwareProduct, licenseModel: {licenseAgreement, featureGroup}}) => {
- let {softwareProductEditor: {data: currentSoftwareProduct}, softwareProductCategories, softwareProductQuestionnaire} = softwareProduct;
+ let {softwareProductEditor: {data: currentSoftwareProduct, genericFieldInfo}, softwareProductCategories, softwareProductQuestionnaire} = softwareProduct;
let {licensingData = {}, licensingVersion} = currentSoftwareProduct;
let licenseAgreementList = [], filteredFeatureGroupsList = [];
- if(licensingVersion && licensingVersion !== '') {
- licenseAgreementList = licenseAgreement.licenseAgreementList;
+ licenseAgreementList = licenseAgreement.licenseAgreementList;
+ if(licensingVersion && 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));
@@ -38,9 +36,11 @@ export const mapStateToProps = ({finalizedLicenseModelList, softwareProduct, lic
}
}
}
- let {qdata, qschema} = softwareProductQuestionnaire;
+ let {qdata, qgenericFieldInfo : qGenericFieldInfo, dataMap} = softwareProductQuestionnaire;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
return {
currentSoftwareProduct,
softwareProductCategories,
@@ -48,16 +48,19 @@ export const mapStateToProps = ({finalizedLicenseModelList, softwareProduct, lic
featureGroupsList: filteredFeatureGroupsList,
finalizedLicenseModelList,
qdata,
- qschema,
- isReadOnlyMode
+ isReadOnlyMode,
+ isFormValid,
+ genericFieldInfo,
+ qGenericFieldInfo,
+ dataMap
};
};
export const mapActionsToProps = (dispatch) => {
return {
- onDataChanged: deltaData => SoftwareProductActionHelper.softwareProductEditorDataChanged(dispatch, {deltaData}),
- onVendorParamChanged: deltaData => SoftwareProductActionHelper.softwareProductEditorVendorChanged(dispatch, {deltaData}),
- onQDataChanged: ({data}) => SoftwareProductActionHelper.softwareProductQuestionnaireUpdate(dispatch, {data}),
+ 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) =>{ return SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {softwareProduct, qdata});}
};
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 e060706b37..d62207ff9f 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsReducer.js
@@ -1,55 +1,43 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from '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.OPEN:
- return {
- ...state,
- data: {}
- };
- case actionTypes.softwareProductEditor.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
- }
- };
- case actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION:
- return {
- ...state,
- uploadData:action.uploadData
- };
case actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED:
return {
...state,
isValidityData: action.isValidityData
};
- case actionTypes.softwareProductEditor.CLOSE:
- return {};
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:
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 75a5797dec..1d52da38b0 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx
@@ -1,9 +1,266 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React, {Component, PropTypes} from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import Form from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import InputOptions from 'nfvo-components/input/inputOptions/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';
+
+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
+ };
+
+ 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);
+ }
+
+ render (){
+ let {genericFieldInfo} = this.props;
+ return (
+ <div>
+ {genericFieldInfo && <GridSection title={i18n('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 => this.props.onDataChanged({name}, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS)}/>
+ <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,
+ 'vendorName'
+ ).map(lm => <option key={lm.id} value={lm.id}>{lm.vendorName}</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.object,
+ 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
+ };
+
+ onVendorParamChanged(e) {
+ const selectedIndex = e.target.selectedIndex;
+ const licensingVersion = e.target.options[selectedIndex].value;
+ this.props.onVendorParamChanged({vendorId: this.props.vendorId, licensingVersion:{id:licensingVersion, label: 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: []});
+ }
+
+ render(){
+ return (
+ <GridSection title={i18n('Licenses')}>
+ <GridItem>
+ <Input
+ data-test-id='vsp-licensing-version'
+ onChange={e => this.onVendorParamChanged(e)}
+ value={this.props.licensingVersion ? this.props.licensingVersion.id : ''}
+ label={i18n('Licensing Version')}
+ 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'
+ 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={()=>{}}
+ 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'
+ 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 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 {
@@ -17,7 +274,7 @@ class SoftwareProductDetails extends Component {
subCategory: PropTypes.string,
vendorId: PropTypes.string,
vendorName: PropTypes.string,
- licensingVersion: PropTypes.string,
+ licensingVersion: PropTypes.object,
licensingData: PropTypes.shape({
licenceAgreement: PropTypes.string,
featureGroups: PropTypes.array
@@ -31,7 +288,6 @@ class SoftwareProductDetails extends Component {
onDataChanged: PropTypes.func.isRequired,
onValidityChanged: PropTypes.func.isRequired,
qdata: PropTypes.object.isRequired,
- qschema: PropTypes.object.isRequired,
onQDataChanged: PropTypes.func.isRequired,
onVendorParamChanged: PropTypes.func.isRequired
};
@@ -40,161 +296,63 @@ class SoftwareProductDetails extends Component {
licensingVersionsList: []
};
- render() {
- let {softwareProductCategories, finalizedLicenseModelList, onDataChanged, featureGroupsList, licenseAgreementList, currentSoftwareProduct} = this.props;
- let {name, description, vendorId, licensingVersion, subCategory, licensingData = {}} = currentSoftwareProduct;
+ prepareDataForGeneralSection(){
+ let {softwareProductCategories, finalizedLicenseModelList, onDataChanged, currentSoftwareProduct, genericFieldInfo} = this.props;
+ let {name, description, vendorId, subCategory} = currentSoftwareProduct;
+ return {
+ name,
+ description,
+ vendorId,
+ subCategory,
+ softwareProductCategories,
+ finalizedLicenseModelList,
+ onDataChanged,
+ onVendorParamChanged: args => this.onVendorParamChanged(args),
+ onSelectSubCategory: args => this.onSelectSubCategory(args),
+ genericFieldInfo
+ };
+
+ }
+
+ prepareDataForLicensesSection(){
+ let { featureGroupsList, licenseAgreementList, currentSoftwareProduct } = this.props;
+ let {vendorId, licensingVersion, licensingData = {}} = currentSoftwareProduct;
let licensingVersionsList = this.state.licensingVersionsList.length > 0 ? this.state.licensingVersionsList : this.refreshVendorVersionsList(vendorId);
- let {qdata, qschema, onQDataChanged} = this.props;
+ return {
+ onVendorParamChanged: args => this.onVendorParamChanged(args),
+ vendorId,
+ licensingVersion,
+ licensingVersionsList,
+ licensingData,
+ onFeatureGroupsChanged: args => this.onFeatureGroupsChanged(args),
+ onLicensingDataChanged: args => this.onLicensingDataChanged(args),
+ featureGroupsList,
+ licenseAgreementList,
+ };
+
+ }
+
+ render() {
+ let {currentSoftwareProduct} = this.props;
+ let {qdata, onQDataChanged, dataMap, qGenericFieldInfo} = this.props;
let {isReadOnlyMode} = this.props;
return (
- <div className='vsp-details-page'>
+ <div className='vsp-details-page'>
<Form
- ref='validationForm'
+ 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}>
- <div className='section-title general'>{i18n('General')}</div>
- <div className='vsp-general-tab-inline-section'>
- <div className='vsp-general-tab-sub-section'>
- <ValidationInput
- label={i18n('Name')}
- type='text'
- value={name}
- onChange={name => onDataChanged({name})}
- validations={{validateName: true, maxLength: 120, required: true}}
- className='field-section'/>
- <ValidationInput
- label={i18n('Vendor')}
- type='select'
- selectedEnum={vendorId}
- onEnumChange={vendorId => this.onVendorParamChanged({vendorId})}
- className='field-section'>
- {finalizedLicenseModelList.map(lm => <option key={lm.id} value={lm.id}>{lm.vendorName}</option>)}
- </ValidationInput>
- <div className='input-row'>
- <ValidationInput
- label={i18n('Category')}
- type='select'
- selectedEnum={subCategory}
- onEnumChange={subCategory => this.onSelectSubCategory(subCategory)}
- className='field-section'>
- {
- 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>
- )
- }
- </ValidationInput>
- </div>
- </div>
- <div className='vsp-general-tab-sub-section input-row'>
- <ValidationInput
- label={i18n('Description')}
- type='textarea'
- value={description}
- onChange={description => onDataChanged({description})}
- className='field-section'
- validations={{required: true}}/>
- </div>
- </div>
- <div className='vsp-general-tab-section licenses'>
- <div className='section-title'>{i18n('Licenses')}</div>
- <div className='vsp-general-tab-inline-section input-row'>
- <ValidationInput
- onEnumChange={licensingVersion => this.onVendorParamChanged({vendorId, licensingVersion})}
- selectedEnum={licensingVersion}
- label={i18n('Licensing Version')}
- values={licensingVersionsList}
- type='select'
- className='field-section'/>
- <ValidationInput
- label={i18n('License Agreement')}
- type='select'
- selectedEnum={licensingData.licenseAgreement}
- className='field-section'
- onEnumChange={(licenseAgreement) => this.onLicensingDataChanged({licenseAgreement, featureGroups: []})}>
- <option key='placeholder' value=''>{i18n('Select...')}</option>
- {licenseAgreementList.map(la => <option value={la.id} key={la.id}>{la.name}</option>)}
- </ValidationInput>
- </div>
- <div className='vsp-general-tab-inline-section input-row'>
- {licensingData.licenseAgreement && (
- <ValidationInput
- type='select'
- isMultiSelect={true}
- onEnumChange={featureGroups => this.onFeatureGroupsChanged({featureGroups})}
- multiSelectedEnum={licensingData.featureGroups}
- name='feature-groups'
- label={i18n('Feature Groups')}
- clearable={false}
- values={featureGroupsList}/>)
- }
- </div>
- </div>
- </Form>
- <Form
- data={qdata}
- schema={qschema}
- onDataChanged={onQDataChanged}
- className='vsp-general-tab'
- hasButtons={false}
- isReadOnlyMode={isReadOnlyMode}>
- <div className='vsp-general-tab-section'>
- <div className='section-title'> {i18n('Availability')} </div>
- <div className='vsp-general-tab-inline-section'>
- <div className='vsp-general-tab-sub-section input-row'>
- <ValidationInput
- label={i18n('Use Availability Zones for High Availability')}
- type='checkbox'
- pointer='/general/availability/useAvailabilityZonesForHighAvailability'/>
- </div>
- </div>
- <div className='section-title'> {i18n('Regions')} </div>
- <div className='vsp-general-tab-inline-section'>
- <div className='vsp-general-tab-sub-section input-row'>
- <ValidationInput
- type='select'
- laebl='Ziv'
- pointer='/general/regionsData/regions'/>
- </div>
- </div>
- <div className='section-title'> {i18n('Storage Data Replication')} </div>
- <div className='vsp-general-tab-inline-section'>
- <div className='vsp-general-tab-sub-section'>
- <ValidationInput
- label={i18n('Storage Replication Size (GB)')}
- type='text'
- pointer='/general/storageDataReplication/storageReplicationSize'
- className='field-section'/>
- <ValidationInput
- label={i18n('Storage Replication Source')}
- type='text'
- pointer='/general/storageDataReplication/storageReplicationSource'
- className='field-section'/>
- </div>
- <div className='vsp-general-tab-sub-section'>
- <ValidationInput
- label={i18n('Storage Replication Frequency (minutes)')}
- type='text'
- pointer='/general/storageDataReplication/storageReplicationFrequency'
- className='field-section'/>
- <ValidationInput
- label={i18n('Storage Replication Destination')}
- type='text'
- pointer='/general/storageDataReplication/storageReplicationDestination'
- className='field-section'/>
- </div>
- </div>
- </div>
+ <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>
);
@@ -213,7 +371,9 @@ class SoftwareProductDetails extends Component {
licensingVersion,
licensingData: {}
};
- onVendorParamChanged(deltaData);
+
+ onVendorParamChanged(deltaData, forms.VENDOR_SOFTWARE_PRODUCT_DETAILS);
+
}
refreshVendorVersionsList(vendorId) {
@@ -229,20 +389,14 @@ class SoftwareProductDetails extends Component {
}];
if(finalVersions) {
finalVersions.forEach(version => licensingVersionsList.push({
- enum: version,
- title: version
+ enum: version.id,
+ title: version.label
}));
}
return licensingVersionsList;
}
- onSelectSubCategory(subCategory) {
- let {softwareProductCategories, onDataChanged} = this.props;
- let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(subCategory, softwareProductCategories);
- onDataChanged({category, subCategory});
- }
-
onFeatureGroupsChanged({featureGroups}) {
this.onLicensingDataChanged({featureGroups});
}
@@ -253,11 +407,17 @@ class SoftwareProductDetails extends Component {
...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);
}
save(){
- return this.refs.validationForm.handleFormSubmit(new Event('dummy'));
+ return this.validationForm.handleFormSubmit(new Event('dummy'));
}
}
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 7604f5841d..e8091bf8d1 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js
@@ -1,33 +1,27 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
-
import i18n from 'nfvo-utils/i18n/i18n.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
-import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js';
import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.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';
-const mapStateToProps = ({softwareProduct, licenseModel: {licenseAgreement}}) => {
+export const mapStateToProps = ({softwareProduct, licenseModel: {licenseAgreement}}) => {
let {softwareProductEditor: {data:currentSoftwareProduct = {}}, softwareProductComponents, softwareProductCategories = []} = softwareProduct;
let {licensingData = {}} = currentSoftwareProduct;
let {licenseAgreementList} = licenseAgreement;
@@ -35,6 +29,8 @@ const mapStateToProps = ({softwareProduct, licenseModel: {licenseAgreement}}) =>
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 = '';
@@ -62,27 +58,44 @@ const mapStateToProps = ({softwareProduct, licenseModel: {licenseAgreement}}) =>
const mapActionsToProps = (dispatch, {version}) => {
return {
- onDetailsSelect: ({id: softwareProductId, vendorId: licenseModelId}) => OnboardingActionHelper.navigateToSoftwareProductDetails(dispatch, {
+ onDetailsSelect: ({id: softwareProductId, vendorId: licenseModelId, version}) => OnboardingActionHelper.navigateToSoftwareProductDetails(dispatch, {
softwareProductId,
- licenseModelId
+ licenseModelId,
+ version
}),
- onAttachmentsSelect: ({id: softwareProductId}) => OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId}),
+ onAttachmentsSelect: ({id: softwareProductId}) => OnboardingActionHelper.navigateToSoftwareProductAttachments(dispatch, {softwareProductId, version}),
onUpload: (softwareProductId, formData) =>
SoftwareProductActionHelper.uploadFile(dispatch, {
softwareProductId,
formData,
- failedNotificationTitle: i18n('Upload validation failed')
+ failedNotificationTitle: i18n('Upload validation failed'),
+ version
}),
+
onUploadConfirmation: (softwareProductId, formData) =>
- SoftwareProductActionHelper.uploadConfirmation(dispatch, {
- softwareProductId,
- formData,
- failedNotificationTitle: i18n('Upload validation failed')}),
+ 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: NotificationConstants.NOTIFY_ERROR,
+ type: modalActionTypes.GLOBAL_MODAL_ERROR,
data: {
title: i18n('Upload Failed'),
+ confirmationButtonText: i18n('Continue'),
msg: i18n('no zip file was uploaded or zip file doesn\'t exist')
}
}),
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageUploadConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageUploadConfirmationModal.jsx
deleted file mode 100644
index 4a848834b2..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageUploadConfirmationModal.jsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import {connect} from 'react-redux';
-import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
-import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
-
-import i18n from 'nfvo-utils/i18n/i18n.js';
-
-const mapStateToProps = ({softwareProduct}) => {
- let {softwareProductEditor} = softwareProduct;
- let {uploadData} = softwareProductEditor;
- const show = uploadData ? true : false;
- return {
- show,
- title: 'Warning!',
- type: 'warning',
- msg: i18n('Upload will erase existing data. Do you want to continue?'),
- confirmationDetails: {uploadData}
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
- onConfirmed: ({uploadData}) => {
- let {softwareProductId, formData, failedNotificationTitle} = uploadData;
- SoftwareProductActionHelper.uploadFile(dispatch, {
- softwareProductId,
- formData,
- failedNotificationTitle
- });
- SoftwareProductActionHelper.hideUploadConfirm(dispatch);
- },
- onDeclined: () => {
- SoftwareProductActionHelper.hideUploadConfirm(dispatch);
- }
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
-
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 cf7c7a31a5..5fbf1b74b0 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import classnames from 'classnames';
import Dropzone from 'react-dropzone';
@@ -6,15 +21,14 @@ import Dropzone from 'react-dropzone';
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 ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
-import FontAwesome from 'react-fontawesome';
-import SoftwareProductLandingPageUploadConfirmationModal from './SoftwareProductLandingPageUploadConfirmationModal.jsx';
-
+import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
const SoftwareProductPropType = React.PropTypes.shape({
name: React.PropTypes.string,
description: React.PropTypes.string,
- version: React.PropTypes.string,
+ version: React.PropTypes.object,
id: React.PropTypes.string,
categoryId: React.PropTypes.string,
vendorId: React.PropTypes.string,
@@ -79,7 +93,6 @@ class SoftwareProductLandingPageView extends React.Component {
{
componentsList.length > 0 && this.renderComponents()
}
- <SoftwareProductLandingPageUploadConfirmationModal confirmationButtonText={i18n('Continue')}/>
</div>
);
}
@@ -101,29 +114,31 @@ class SoftwareProductLandingPageView extends React.Component {
onClick={() => onDetailsSelect(currentSoftwareProduct)}>
<div className='details-container'>
<div className='single-detail-section title-section'>
- <div>
- <div>{name}</div>
+ <div className='single-detail-section title-text'>
+ {name}
</div>
</div>
- <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'>
- {this.renderLicenseAgreement(licenseAgreementName)}
+ <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'>
+ {this.renderLicenseAgreement(licenseAgreementName)}
+ </div>
</div>
</div>
- </div>
- <div className='single-detail-section'>
- <div className='title'>{i18n('Description')}</div>
- <div className='description'>{description}</div>
+ <div className='single-detail-section'>
+ <div className='title'>{i18n('Description')}</div>
+ <div className='description'>{description}</div>
+ </div>
</div>
</div>
</div>
@@ -151,19 +166,13 @@ class SoftwareProductLandingPageView extends React.Component {
<div className='attachment-details'>{i18n('HEAT Templates')} (<span
className='attachment-details-count'>{details.heatTemplates}</span>)
</div>
- <div className='attachment-details'>{i18n('Images')} (<span
- className='attachment-details-count'>{details.images}</span>)
- </div>
- <div className='attachment-details'>{i18n('Other Artifacts')} (<span
- className='attachment-details-count'>{details.otherArtifacts}</span>)
- </div>
</div>
</div>
<div
className={classnames('software-product-landing-view-top-block-col-upl', {'disabled': isReadOnlyMode})}>
<div className='drag-text'>{i18n('Drag & drop for upload')}</div>
<div className='or-text'>{i18n('or')}</div>
- <div className='upload-btn primary-btn' onClick={() => this.refs.fileInput.open()}>
+ <div data-test-id='upload-btn' className='upload-btn primary-btn' onClick={() => this.refs.fileInput.open()}>
<span className='primary-btn-text'>{i18n('Select file')}</span>
</div>
</div>
@@ -180,7 +189,8 @@ class SoftwareProductLandingPageView extends React.Component {
title={i18n('Virtual Function Components')}
filterValue={localFilter}
placeholder={i18n('Filter Components')}
- onFilter={filter => this.setState({localFilter: filter})}>
+ onFilter={value => this.setState({localFilter: value})}
+ twoColumns>
{this.filterList().map(component => this.renderComponentsListItem(component))}
</ListEditorView>
);
@@ -194,21 +204,19 @@ class SoftwareProductLandingPageView extends React.Component {
key={name + Math.floor(Math.random() * (100 - 1) + 1).toString()}
className='list-editor-item-view'
onSelect={() => onComponentSelect({id, componentId})}>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Component')}</div>
+ <ListEditorItemViewField>
<div className='name'>{displayName}</div>
- </div>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Description')}</div>
+ </ListEditorItemViewField>
+ <ListEditorItemViewField>
<div className='description'>{description}</div>
- </div>
+ </ListEditorItemViewField>
</ListEditorItemView>
);
}
renderLicenseAgreement(licenseAgreementName) {
- if (!licenseAgreementName) {
- return (<FontAwesome name='exclamation-triangle' className='warning-icon'/>);
+ if (licenseAgreementName !== null && !licenseAgreementName) {
+ return (<div className='missing-license'><SVGIcon name='exclamation-triangle-full'/><div className='warning-text'>{i18n('Missing')}</div></div>);
}
return (licenseAgreementName);
}
@@ -242,6 +250,9 @@ class SoftwareProductLandingPageView extends React.Component {
this.startUploading(files);
}
else {
+ this.setState({
+ dragging: false
+ });
this.props.onInvalidFileSizeUpload();
}
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 dadc7777e1..6161eadba9 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworks.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
import SoftwareProductNetworksView from './SoftwareProductNetworksView.jsx';
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 d0e29bcfe5..4cb460ecc6 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksActionHelper.js
@@ -1,36 +1,31 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductNetworksConstants.js';
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
-function baseUrl(svpId) {
+function baseUrl(vspId, version) {
+ let {id: versionId} = version;
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-software-products/${svpId}/networks`;
+ return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/networks`;
}
function fetchNetworksList(softwareProductId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId)}${versionQuery}`);
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
}
const 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 d428d21a26..a3d5578dc4 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
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 0c9c62372a..e7c2fcb045 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductNetworksConstants.js';
export default (state = [], action) => {
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 bd47467fe1..024c5cc44c 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/networks/SoftwareProductNetworksView.jsx
@@ -1,8 +1,24 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
class SoftwareProductNetworksView extends React.Component {
@@ -27,7 +43,8 @@ class SoftwareProductNetworksView extends React.Component {
title={i18n('Networks')}
filterValue={localFilter}
placeholder={i18n('Filter Networks')}
- onFilter={filter => this.setState({localFilter: filter})}>
+ onFilter={value => this.setState({localFilter: value})}
+ twoColumns>
{this.filterList().map(network => this.renderNetworksListItem(network))}
</ListEditorView>
</div>
@@ -42,14 +59,15 @@ class SoftwareProductNetworksView extends React.Component {
className='list-editor-item-view'
isReadOnlyMode={true}>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('Name')}</div>
+ <ListEditorItemViewField>
<div className='name'>{name}</div>
- </div>
- <div className='list-editor-item-view-field'>
- <div className='title'>{i18n('DHCP')}</div>
- <div className='artifact-name'>{dhcp ? i18n('YES') : i18n('NO')}</div>
- </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>
);
}
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 5c3a8dae01..66926ce4b3 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcesses.js
@@ -1,30 +1,27 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
import SoftwareProductProcessesActionHelper from './SoftwareProductProcessesActionHelper.js';
import SoftwareProductProcessesView from './SoftwareProductProcessesView.jsx';
-const mapStateToProps = ({softwareProduct}) => {
+export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data: currentSoftwareProduct = {}}, softwareProductProcesses: {processesList, processesEditor}} = softwareProduct;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
let {data} = processesEditor;
@@ -42,7 +39,14 @@ const mapActionsToProps = (dispatch, {softwareProductId}) => {
return {
onAddProcess: () => SoftwareProductProcessesActionHelper.openEditor(dispatch),
onEditProcess: (process) => SoftwareProductProcessesActionHelper.openEditor(dispatch, process),
- onDeleteProcess: (process) => SoftwareProductProcessesActionHelper.openDeleteProcessesConfirm(dispatch, {process, softwareProductId})
+ onDeleteProcess: (process, version) => dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n('Are you sure you want to delete "{name}"?', {name: process.name}),
+ onConfirmed: ()=> SoftwareProductProcessesActionHelper.deleteProcess(dispatch,
+ {process, softwareProductId, version})
+ }
+ })
};
};
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 df5d08ffe5..8fd370b6cc 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesActionHelper.js
@@ -1,62 +1,57 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductProcessesConstants.js';
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
-function baseUrl(svpId) {
+function baseUrl(vspId, version) {
+ let {id: versionId} = version;
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-software-products/${svpId}/processes`;
+ return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/processes`;
}
-function putProcess(softwareProductId, process) {
- return RestAPIUtil.save(`${baseUrl(softwareProductId)}/${process.id}`, {
+function putProcess(softwareProductId, version, process) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, version)}/${process.id}`, {
name: process.name,
- description: process.description
+ description: process.description,
+ type: process.type === '' ? null : process.type
});
}
-function postProcess(softwareProductId, process) {
- return RestAPIUtil.create(`${baseUrl(softwareProductId)}`, {
+function postProcess(softwareProductId, version, process) {
+ return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
name: process.name,
- description: process.description
+ description: process.description,
+ type: process.type === '' ? null : process.type
});
}
-function deleteProcess(softwareProductId, processId) {
- return RestAPIUtil.destroy(`${baseUrl(softwareProductId)}/${processId}`);
+function deleteProcess(softwareProductId, version, processId) {
+ return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${processId}`);
}
-function uploadFileToProcess(softwareProductId, processId, formData)
+function uploadFileToProcess(softwareProductId, version, processId, formData)
{
- return RestAPIUtil.create(`${baseUrl(softwareProductId)}/${processId}/upload`, formData);
+ return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}/${processId}/upload`, formData);
}
function fetchProcesses(softwareProductId, version) {
- let versionQuery = version ? `?version=${version}` : '';
- return RestAPIUtil.fetch(`${baseUrl(softwareProductId)}${versionQuery}`);
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version)}`);
}
-
-
const SoftwareProductActionHelper = {
fetchProcessesList(dispatch, {softwareProductId, version}) {
@@ -80,8 +75,8 @@ const SoftwareProductActionHelper = {
});
},
- deleteProcess(dispatch, {process, softwareProductId}) {
- return deleteProcess(softwareProductId, process.id).then(() => {
+ deleteProcess(dispatch, {process, softwareProductId, version}) {
+ return deleteProcess(softwareProductId, version, process.id).then(() => {
dispatch({
type: actionTypes.DELETE_SOFTWARE_PRODUCT_PROCESS,
processId: process.id
@@ -96,18 +91,11 @@ const SoftwareProductActionHelper = {
});
},
- processEditorDataChanged(dispatch, {deltaData}) {
- dispatch({
- type: actionTypes.processEditor.DATA_CHANGED,
- deltaData
- });
- },
-
- saveProcess(dispatch, {softwareProductId, previousProcess, process}) {
+ saveProcess(dispatch, {softwareProductId, version, previousProcess, process}) {
if (previousProcess) {
- return putProcess(softwareProductId, process).then(() => {
+ return putProcess(softwareProductId, version, process).then(() => {
if (process.formData){
- uploadFileToProcess(softwareProductId, process.id, process.formData);
+ uploadFileToProcess(softwareProductId, version, process.id, process.formData);
}
dispatch({
type: actionTypes.EDIT_SOFTWARE_PRODUCT_PROCESS,
@@ -116,9 +104,9 @@ const SoftwareProductActionHelper = {
});
}
else {
- return postProcess(softwareProductId, process).then(response => {
+ return postProcess(softwareProductId, version, process).then(response => {
if (process.formData) {
- uploadFileToProcess(softwareProductId, response.value, process.formData);
+ uploadFileToProcess(softwareProductId, version, response.value, process.formData);
}
dispatch({
type: actionTypes.ADD_SOFTWARE_PRODUCT_PROCESS,
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConfirmationModal.jsx
deleted file mode 100644
index 0159352dae..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConfirmationModal.jsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import React from 'react';
-import {connect} from 'react-redux';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx';
-import SoftwareProductProcessesActionHelper from './SoftwareProductProcessesActionHelper.js';
-
-function renderMsg(processToDelete) {
- let name = processToDelete ? processToDelete.name : '';
- let msg = i18n('Are you sure you want to delete "{name}"?', {name});
- return (
- <div>
- <p>{msg}</p>
- </div>
- );
-};
-
-const mapStateToProps = ({softwareProduct}) => {
- let {softwareProductEditor, softwareProductProcesses} = softwareProduct;
- let {processToDelete} = softwareProductProcesses;
- let softwareProductId = softwareProductEditor.data.id;
-
- const show = processToDelete !== false;
- return {
- show,
- title: i18n('Warning!'),
- type: 'warning',
- msg: renderMsg(processToDelete),
- confirmationDetails: {processToDelete, softwareProductId}
- };
-};
-
-const mapActionsToProps = (dispatch) => {
- return {
- onConfirmed: ({processToDelete, softwareProductId}) => {
- SoftwareProductProcessesActionHelper.deleteProcess(dispatch, {process: processToDelete, softwareProductId});
- SoftwareProductProcessesActionHelper.hideDeleteConfirm(dispatch);
- },
- onDeclined: () => {
- SoftwareProductProcessesActionHelper.hideDeleteConfirm(dispatch);
- }
- };
-};
-
-export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView);
-
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 63f3067a89..6eee24cdde 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesConstants.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
@@ -27,8 +22,14 @@ export const actionTypes = keyMirror({
SOFTWARE_PRODUCT_PROCESS_EDITOR_OPEN: null,
SOFTWARE_PRODUCT_PROCESS_EDITOR_CLOSE: null,
FETCH_SOFTWARE_PRODUCT_PROCESSES: null,
- SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM: null,
- processEditor: {
- DATA_CHANGED: null
- }
+ SOFTWARE_PRODUCT_PROCESS_DELETE_CONFIRM: null
});
+
+export const optionsInputValues = {
+ 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 8dc48c50b1..ff787c357e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditor.js
@@ -1,31 +1,28 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {connect} from 'react-redux';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
import SoftwareProductProcessesActionHelper from './SoftwareProductProcessesActionHelper';
import SoftwareProductProcessesEditorView from './SoftwareProductProcessesEditorView.jsx';
+import {VSP_PROCESS_FORM} from './SoftwareProductProcessesConstants.js';
-const mapStateToProps = ({softwareProduct}) => {
+export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductProcesses: {processesList, processesEditor}} = softwareProduct;
- let {data} = processesEditor;
-
+ let {data, genericFieldInfo, formReady} = processesEditor;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
let previousData;
const processId = data ? data.id : null;
if(processId) {
@@ -34,18 +31,22 @@ const mapStateToProps = ({softwareProduct}) => {
return {
data,
- previousData
+ genericFieldInfo,
+ previousData,
+ isFormValid,
+ formReady
};
};
-const mapActionsToProps = (dispatch, {softwareProductId}) => {
+const mapActionsToProps = (dispatch, {softwareProductId, version}) => {
return {
- onDataChanged: deltaData => SoftwareProductProcessesActionHelper.processEditorDataChanged(dispatch, {deltaData}),
+ onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: VSP_PROCESS_FORM}),
onSubmit: ({previousProcess, process}) => {
SoftwareProductProcessesActionHelper.closeEditor(dispatch);
- SoftwareProductProcessesActionHelper.saveProcess(dispatch, {softwareProductId, previousProcess, process});
+ SoftwareProductProcessesActionHelper.saveProcess(dispatch, {softwareProductId, version, previousProcess, process});
},
- onClose: () => SoftwareProductProcessesActionHelper.closeEditor(dispatch)
+ onClose: () => SoftwareProductProcessesActionHelper.closeEditor(dispatch),
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, VSP_PROCESS_FORM)
};
};
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 cae25e2c89..11b89b17c2 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorReducer.js
@@ -1,43 +1,54 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
-import {actionTypes} from './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 {};
- case actionTypes.processEditor.DATA_CHANGED:
- return {
- ...state,
- data: {
- ...state.data,
- ...action.deltaData
- }
- };
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 c2c4aff382..137e4a2b4e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesEditorView.jsx
@@ -1,18 +1,50 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import Dropzone from 'react-dropzone';
import classnames from 'classnames';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx';
-import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx';
+import {optionsInputValues as ProcessesOptionsInputValues} from './SoftwareProductProcessesConstants.js';
+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';
const SoftwareProductProcessEditorPropType = React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string,
description: React.PropTypes.string,
- artifactName: React.PropTypes.string
+ artifactName: React.PropTypes.string,
+ type: React.PropTypes.string
});
+const FileUploadBox = ({onClick}) => {
+ return (
+ <div className='file-upload-box'>
+ <div className='drag-text'>{i18n('Drag & drop for upload')}</div>
+ <div className='or-text'>{i18n('or')}</div>
+ <div className='upload-btn primary-btn' onClick={onClick}>
+ <span className='primary-btn-text'>{i18n('Select file')}</span>
+ </div>
+ </div>
+ );
+};
+
+
class SoftwareProductProcessesEditorView extends React.Component {
state = {
@@ -30,63 +62,89 @@ class SoftwareProductProcessesEditorView extends React.Component {
};
render() {
- let {data = {}, isReadOnlyMode, onDataChanged, onClose} = this.props;
- let {name, description, artifactName} = data;
+ let {data = {}, isReadOnlyMode, onDataChanged, onClose, genericFieldInfo} = this.props;
+ let {name, description, artifactName, type} = data;
+
return (
- <ValidationForm
- ref='validationForm'
- hasButtons={true}
- labledButtons={true}
- isReadOnlyMode={isReadOnlyMode}
- onSubmit={ () => this.submit() }
- onReset={ () => onClose() }
- className='vsp-processes-editor'>
- <div className={classnames('vsp-processes-editor-data', {'disabled': isReadOnlyMode})}>
- <Dropzone
- className={classnames('vsp-process-dropzone-view', {'active-dragging': this.state.dragging})}
- onDrop={files => this.handleImportSubmit(files)}
- onDragEnter={() => this.setState({dragging: true})}
- onDragLeave={() => this.setState({dragging: false})}
- multiple={false}
- disableClick={true}
- ref='processEditorFileInput'
- name='processEditorFileInput'
- accept='*.*'>
- <div className='row'>
- <div className='col-md-6'>
- <ValidationInput
- onChange={name => onDataChanged({name})}
- label={i18n('Name')}
- value={name}
- validations={{validateName: true, maxLength: 120, required: true}}
- type='text'/>
- <ValidationInput
- label={i18n('Artifacts')}
- value={artifactName}
- type='text'
- disabled/>
- </div>
- <div className='col-md-6'>
- <div className='file-upload-box'>
- <div className='drag-text'>{i18n('Drag & drop for upload')}</div>
- <div className='or-text'>{i18n('or')}</div>
- <div className='upload-btn primary-btn' onClick={() => this.refs.processEditorFileInput.open()}>
- <span className='primary-btn-text'>{i18n('Select file')}</span>
- </div>
- </div>
- </div>
- </div>
- <ValidationInput
- onChange={description => onDataChanged({description})}
- label={i18n('Notes')}
- value={description}
- name='vsp-process-description'
- className='vsp-process-description'
- validations={{maxLength: 1000}}
- type='textarea'/>
- </Dropzone>
- </div>
- </ValidationForm>
+ <div>
+ {genericFieldInfo && <Form
+ ref='validationForm'
+ hasButtons={true}
+ labledButtons={true}
+ isReadOnlyMode={isReadOnlyMode}
+ onSubmit={ () => this.submit() }
+ onReset={ () => onClose() }
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm() }
+ className='vsp-processes-editor'>
+ <div className={classnames('vsp-processes-editor-data', {'disabled': isReadOnlyMode})}>
+ <Dropzone
+ className={classnames('vsp-process-dropzone-view', {'active-dragging': this.state.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>
+ <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}>
+ <FileUploadBox onClick={() => this.refs.processEditorFileInput.open()}/>
+ </GridItem>
+ </GridSection>
+ <GridSection>
+ <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}>
+ <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')}
+ data-test-id='process-type'
+ isValid={genericFieldInfo.type.isValid}
+ errorText={genericFieldInfo.type.errorText}
+ type='select'>
+ {ProcessesOptionsInputValues.PROCESS_TYPE.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+ </GridItem>
+ </GridSection>
+ </Dropzone>
+ </div>
+ </Form>}
+ </div>
);
}
@@ -108,14 +166,24 @@ class SoftwareProductProcessesEditorView extends React.Component {
}
- handleImportSubmit(files) {
- let {onDataChanged} = this.props;
- this.setState({
- dragging: false,
- complete: '0',
- files
- });
- onDataChanged({artifactName: files[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);
+ }
+ }
}
}
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 619a2dba0f..20390d1f60 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesListReducer.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import {actionTypes} from './SoftwareProductProcessesConstants.js';
export default (state = [], action) => {
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 a2aa3d414e..8f52434042 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/processes/SoftwareProductProcessesView.jsx
@@ -1,3 +1,18 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import Modal from 'nfvo-components/modal/Modal.jsx';
@@ -6,7 +21,7 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import SoftwareProductProcessesEditor from './SoftwareProductProcessesEditor.js';
-import SoftwareProductProcessesConfirmationModal from './SoftwareProductProcessesConfirmationModal.jsx';
+
class SoftwareProductProcessesView extends React.Component {
@@ -20,30 +35,29 @@ class SoftwareProductProcessesView extends React.Component {
onEditProcess: React.PropTypes.func.isRequired,
onDeleteProcess: React.PropTypes.func.isRequired,
isDisplayEditor: React.PropTypes.bool.isRequired,
- isReadOnlyMode: React.PropTypes.bool.isRequired
+ isReadOnlyMode: React.PropTypes.bool.isRequired,
+ currentSoftwareProduct:React.PropTypes.object
};
render() {
- let { currentSoftwareProduct} = this.props;
return (
<div className='software-product-landing-view-right-side vsp-processes-page'>
{this.renderEditor()}
{this.renderProcessList()}
- <SoftwareProductProcessesConfirmationModal softwareProductId={currentSoftwareProduct.id}/>
</div>
);
}
renderEditor() {
- let {currentSoftwareProduct: {id}, isModalInEditMode, isReadOnlyMode, isDisplayEditor} = this.props;
+ let {currentSoftwareProduct: {id, version}, isModalInEditMode, isReadOnlyMode, isDisplayEditor} = this.props;
return (
- <Modal show={isDisplayEditor} bsSize='large' animation={true}>
+ <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} isReadOnlyMode={isReadOnlyMode}/>
+ <SoftwareProductProcessesEditor softwareProductId={id} version={version} isReadOnlyMode={isReadOnlyMode}/>
</Modal.Body>
</Modal>
);
@@ -60,7 +74,8 @@ class SoftwareProductProcessesView extends React.Component {
placeholder={i18n('Filter Process')}
onAdd={onAddProcess}
isReadOnlyMode={isReadOnlyMode}
- onFilter={filter => this.setState({localFilter: filter})}>
+ title={i18n('Process Details')}
+ onFilter={value => this.setState({localFilter: value})}>
{this.filterList().map(processes => this.renderProcessListItem(processes, isReadOnlyMode))}
</ListEditorView>
);
@@ -68,14 +83,14 @@ class SoftwareProductProcessesView extends React.Component {
renderProcessListItem(process, isReadOnlyMode) {
let {id, name, description, artifactName = ''} = process;
- let {onEditProcess, onDeleteProcess} = this.props;
+ let {currentSoftwareProduct: {version}, onEditProcess, onDeleteProcess} = this.props;
return (
<ListEditorItemView
key={id}
className='list-editor-item-view'
isReadOnlyMode={isReadOnlyMode}
onSelect={() => onEditProcess(process)}
- onDelete={() => onDeleteProcess(process)}>
+ onDelete={() => onDeleteProcess(process, version)}>
<div className='list-editor-item-view-field'>
<div className='title'>{i18n('Name')}</div>
diff --git a/openecomp-ui/src/sdc-app/punch-outs.js b/openecomp-ui/src/sdc-app/punch-outs.js
index 46e84a60a4..78b64da846 100644
--- a/openecomp-ui/src/sdc-app/punch-outs.js
+++ b/openecomp-ui/src/sdc-app/punch-outs.js
@@ -1,23 +1,18 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
+/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
*/
-
import '../../resources/scss/onboarding.scss';
import 'dox-sequence-diagram-ui/src/main/webapp/res/sdc-sequencer.scss';
diff --git a/openecomp-ui/src/sdc-app/sdc.app.jsx b/openecomp-ui/src/sdc-app/sdc.app.jsx
index 0929fa0bb9..5fdea27fea 100644
--- a/openecomp-ui/src/sdc-app/sdc.app.jsx
+++ b/openecomp-ui/src/sdc-app/sdc.app.jsx
@@ -1,5 +1,19 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
import '../../resources/scss/bootstrap.scss';
-import '../../resources/css/font-awesome.min.css';
import 'react-select/dist/react-select.min.css';
import 'dox-sequence-diagram-ui/src/main/webapp/res/sdc-sequencer.scss';
import '../../resources/scss/style.scss';