aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components
diff options
context:
space:
mode:
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct/components')
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js44
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js65
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js88
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js14
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx14
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js169
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js11
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentComputeView.jsx25
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js116
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx38
-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/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js32
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js55
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx96
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js33
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js45
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx106
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js50
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx79
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx77
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js169
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js27
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js63
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js42
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx71
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js88
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js26
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx132
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageNavigationReducer.js32
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx48
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx47
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx39
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx4
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoring.js11
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js62
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringConstants.js31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js28
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx34
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js51
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js47
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js49
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx123
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js5
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorReducer.js9
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx9
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkActionHelper.js48
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js14
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js29
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx37
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx8
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx21
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesList.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentsProcessesListView.jsx2
58 files changed, 2367 insertions, 366 deletions
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 41e7556749..b13bde03c8 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentEditorReducer.js
@@ -17,6 +17,24 @@ import {actionTypes, forms} from './SoftwareProductComponentsConstants.js';
export default (state = {}, action) => {
switch (action.type) {
+ case actionTypes.COMPONENT_CREATE_OPEN:
+ return {
+ ...state,
+ formName: forms.CREATE_FORM,
+ formReady: null,
+ genericFieldInfo: {
+ 'displayName' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'validateName', data: true}, {type: 'maxLength', data: 25}]
+ },
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 1000}]
+ }
+ }
+ };
case actionTypes.COMPONENT_LOAD:
return {
...state,
@@ -34,6 +52,11 @@ export default (state = {}, action) => {
errorText: '',
validations: []
},
+ 'nfcFunction' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 30}]
+ },
'description' : {
isValid: true,
errorText: '',
@@ -41,6 +64,27 @@ export default (state = {}, action) => {
}
}
};
+ case actionTypes.COMPONENT_UPDATE:
+ return {
+ ...state,
+ data: action.component
+ };
+ case actionTypes.COMPONENT_QUESTIONNAIRE_UPDATE:
+ return {
+ ...state,
+ qdata: action.payload.qdata || state.qdata,
+ qschema: action.payload.qschema || state.qschema
+ };
+ case actionTypes.COMPONENT_DATA_CHANGED:
+ return {
+ ...state,
+ data: {
+ ...state.data,
+ ...action.deltaData
+ }
+ };
+ case actionTypes.COMPONENT_DATA_CLEAR:
+ return {};
default:
return state;
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js
new file mode 100644
index 0000000000..61aebdf293
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponents.js
@@ -0,0 +1,65 @@
+import {connect} from 'react-redux';
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+import SoftwareProductComponentsList from './SoftwareProductComponentsList.js';
+import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import SoftwareProductComponentsActionHelper from '../components/SoftwareProductComponentsActionHelper.js';
+import {onboardingMethod} from '../SoftwareProductConstants.js';
+import ConfirmationModalConstants from 'nfvo-components/modal/GlobalModalConstants.js';
+
+const generateMessage = (name) => {
+ return i18n(`Are you sure you want to delete ${name}?`);
+};
+
+const mapStateToProps = ({softwareProduct}) => {
+ let {softwareProductEditor: {data: currentSoftwareProduct}, softwareProductComponents} = softwareProduct;
+ let {componentsList} = softwareProductComponents;
+ let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+
+ return {
+ currentSoftwareProduct,
+ isReadOnlyMode,
+ componentsList,
+ isManual: currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL
+
+ };
+};
+
+class SoftwareProductComponentsView extends React.Component {
+ render() {
+ let {currentSoftwareProduct, isReadOnlyMode, componentsList, isManual, onDeleteComponent} = this.props;
+ return (
+ <SoftwareProductComponentsList
+ isReadOnlyMode={isReadOnlyMode}
+ componentsList={componentsList}
+ onDeleteComponent={onDeleteComponent}
+ isManual={isManual}
+ currentSoftwareProduct={currentSoftwareProduct}/>);
+ }
+
+}
+
+const mapActionToProps = (dispatch) => {
+ return {
+ onComponentSelect: ({id: softwareProductId, componentId, version}) => {
+ OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, {softwareProductId, componentId, version });
+ },
+ onAddComponent: (softwareProductId) => SoftwareProductComponentsActionHelper.addComponent(dispatch, {softwareProductId}),
+ onDeleteComponent: (component, softwareProductId, version) => dispatch({
+ type: ConfirmationModalConstants.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: generateMessage(component.displayName),
+ onConfirmed: ()=>SoftwareProductComponentsActionHelper.deleteComponent(dispatch,
+ {
+ softwareProductId,
+ componentId: component.id,
+ version
+ })
+ }
+ })
+ };
+};
+
+export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(SoftwareProductComponentsView);
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 4e526d3b56..71dc8325ad 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
@@ -18,6 +18,8 @@ import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes, COMPONENTS_QUESTIONNAIRE} from './SoftwareProductComponentsConstants.js';
import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import SoftwareProductComponentsImageActionHelper from './images/SoftwareProductComponentsImageActionHelper.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
function baseUrl(softwareProductId, version) {
const versionId = version.id;
@@ -46,17 +48,53 @@ function putSoftwareProductComponent(softwareProductId, version, vspComponentId,
name: vspComponent.name,
displayName: vspComponent.displayName,
vfcCode: vspComponent.vfcCode,
+ nfcFunction: vspComponent.nfcFunction,
description: vspComponent.description
});
}
+function deleteSoftwareProductComponent(softwareProductId, componentId, version) {
+ return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version)}/${componentId}`,);
+}
+
+
+function postSoftwareProductComponent(softwareProductId, vspComponent, version) {
+
+ return RestAPIUtil.post(`${baseUrl(softwareProductId, version)}`, {
+ name: vspComponent.displayName,
+ displayName: vspComponent.displayName,
+ description: vspComponent.description
+ });
+}
+
+
const SoftwareProductComponentsActionHelper = {
- fetchSoftwareProductComponents(dispatch, {softwareProductId, version}) {
+ fetchSoftwareProductComponents(dispatch, {softwareProductId, version, isFetchImageDetails = false}) {
return fetchSoftwareProductComponents(softwareProductId, version).then(response => {
- dispatch({
- type: actionTypes.COMPONENTS_LIST_UPDATE,
- componentsList: response.results
- });
+ let componentImagesCalls = [];
+ if (isFetchImageDetails && response.listCount) {
+ response.results.map(component => {
+ let componentId = component.id;
+ componentImagesCalls[componentImagesCalls.length] =
+ SoftwareProductComponentsImageActionHelper.fetchImagesList(dispatch, {
+ softwareProductId,
+ componentId,
+ version
+ });
+
+ });
+ return Promise.all(componentImagesCalls).then(() => {
+ dispatch({
+ type: actionTypes.COMPONENTS_LIST_UPDATE,
+ componentsList: response.results
+ });
+ });
+ } else {
+ dispatch({
+ type: actionTypes.COMPONENTS_LIST_UPDATE,
+ componentsList: response.results
+ });
+ }
});
},
@@ -110,7 +148,45 @@ const SoftwareProductComponentsActionHelper = {
type: actionTypes.COMPONENTS_LIST_UPDATE,
componentsList: []
});
- }
+ },
+
+ createSoftwareProductComponent(dispatch,{softwareProductId, componentData, version}) {
+ SoftwareProductComponentsActionHelper.closeComponentCreationModal(dispatch);
+ /* for mock only */
+
+ dispatch({
+ type: actionTypes.COMPONENTS_LIST_UPDATE,
+ componentsList: [{id: '123', ...componentData}]
+ });
+
+ postSoftwareProductComponent(softwareProductId, componentData, version).then(() => {
+ SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
+ });
+ },
+
+ clearComponentCreationData(dispatch) {
+ dispatch({
+ type: actionTypes.COMPONENT_DATA_CLEAR
+ });
+ },
+
+ closeComponentCreationModal(dispatch) {
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
+ });
+ SoftwareProductComponentsActionHelper.clearComponentCreationData(dispatch);
+ },
+
+ deleteComponent(dispatch, {softwareProductId, componentId, version}) {
+ deleteSoftwareProductComponent(softwareProductId, componentId, version);
+ dispatch({
+ type: actionTypes.COMPONENT_DELETE,
+ componentId: componentId
+ });
+ },
+
+
+
};
export default SoftwareProductComponentsActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js
index 9307b099ed..35633b65cf 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js
@@ -18,7 +18,13 @@ import keyMirror from 'nfvo-utils/KeyMirror.js';
export const actionTypes = keyMirror({
COMPONENTS_LIST_UPDATE: null,
COMPONENTS_LIST_EDIT: null,
- COMPONENT_LOAD: null
+ COMPONENT_UPDATE: null,
+ COMPONENT_DATA_CHANGED: null,
+ COMPONENT_DATA_CLEAR: null,
+ COMPONENT_QUESTIONNAIRE_UPDATE: null,
+ COMPONENT_DELETE: null,
+ COMPONENT_LOAD: null,
+ COMPONENT_CREATE_OPEN: null
});
export const storageConstants = keyMirror({
@@ -30,16 +36,20 @@ export const storageConstants = keyMirror({
export const forms = keyMirror({
ALL_SPC_FORMS: null,
- NIC_EDIT_FORM: null
+ NIC_EDIT_FORM: null,
+ CREATE_FORM: null,
+ IMAGE_EDIT_FORM: null
});
export const COMPONENTS_QUESTIONNAIRE = 'component';
+export const COMPONENTS_COMPUTE_QUESTIONNAIRE = 'compute';
export const navigationItems = keyMirror({
STORAGE: 'Storage',
PROCESS_DETAILS: 'Process Details',
MONITORING: 'Monitoring',
NETWORK: 'Network',
+ IMAGES: 'Images',
COMPUTE: 'Compute',
LOAD_BALANCING: 'High Availability & Load Balancing'
});
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 f789a92c6f..bd4c2fa884 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsList.js
@@ -14,21 +14,16 @@
* permissions and limitations under the License.
*/
import {connect} from 'react-redux';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
import SoftwareProductComponentsListView from './SoftwareProductComponentsListView.jsx';
import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
-import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
-
-
-const mapStateToProps = ({softwareProduct}) => {
- let {softwareProductEditor: {data: currentSoftwareProduct}, softwareProductComponents} = softwareProduct;
- let {componentsList} = softwareProductComponents;
- let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
+import SoftwareProductComponentsActionHelper from '../components/SoftwareProductComponentsActionHelper.js';
+import {actionTypes as globalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js';
- return {
- currentSoftwareProduct,
- isReadOnlyMode,
- componentsList
- };
+const generateMessage = (name) => {
+ return i18n(`Are you sure you want to delete ${name}?`);
};
@@ -36,8 +31,21 @@ const mapActionToProps = (dispatch) => {
return {
onComponentSelect: ({id: softwareProductId, componentId, version}) => {
OnboardingActionHelper.navigateToSoftwareProductComponentGeneralAndUpdateLeftPanel(dispatch, {softwareProductId, componentId, version });
- }
+ },
+ onAddComponent: (softwareProductId) => SoftwareProductActionHelper.addComponent(dispatch, {softwareProductId, modalClassName: 'create-vfc-modal'}),
+ onDeleteComponent: (component, softwareProductId, version) => dispatch({
+ type: globalModalActions.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: generateMessage(component.displayName),
+ onConfirmed: ()=>SoftwareProductComponentsActionHelper.deleteComponent(dispatch,
+ {
+ softwareProductId,
+ componentId: component.id,
+ version
+ })
+ }
+ })
};
};
-export default connect(mapStateToProps, mapActionToProps, null, {withRef: true})(SoftwareProductComponentsListView);
+export default connect(null, mapActionToProps, null, {withRef: true})(SoftwareProductComponentsListView);
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 c7aaca5573..92211e0fd2 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListReducer.js
@@ -22,6 +22,8 @@ export default (state = [], action) => {
case actionTypes.COMPONENTS_LIST_EDIT:
const indexForEdit = state.findIndex(component => component.id === action.component.id);
return [...state.slice(0, indexForEdit), action.component, ...state.slice(indexForEdit + 1)];
+ case actionTypes.COMPONENT_DELETE:
+ return state.filter(component => component.id !== action.componentId);
default:
return state;
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx
index c28831fbde..a2a1964299 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsListView.jsx
@@ -40,11 +40,11 @@ class SoftwareProductComponentsListView extends React.Component {
};
render() {
- let {componentsList = []} = this.props;
+ let {componentsList = [], isManual} = this.props;
return (
<div className=''>
{
- componentsList.length > 0 && this.renderComponents()
+ (componentsList.length > 0 || isManual) && this.renderComponents()
}
</div>
);
@@ -52,15 +52,16 @@ class SoftwareProductComponentsListView extends React.Component {
renderComponents() {
const {localFilter} = this.state;
- let {isReadOnlyMode} = this.props;
-
+ const {isManual, onAddComponent, isReadOnlyMode, currentSoftwareProduct: {id: softwareProductId}, componentsList } = this.props;
return (
<ListEditorView
title={i18n('Virtual Function Components')}
filterValue={localFilter}
placeholder={i18n('Filter Components')}
onFilter={value => this.setState({localFilter: value})}
- isReadOnlyMode={isReadOnlyMode}
+ isReadOnlyMode={isReadOnlyMode || !!this.filterList().length}
+ plusButtonTitle={i18n('Add Component')}
+ onAdd={isManual && componentsList.length === 0 ? () => onAddComponent(softwareProductId) : false}
twoColumns>
{this.filterList().map(component => this.renderComponentsListItem(component))}
</ListEditorView>
@@ -69,11 +70,12 @@ class SoftwareProductComponentsListView extends React.Component {
renderComponentsListItem(component) {
let {id: componentId, name, displayName, description = ''} = component;
- let {currentSoftwareProduct: {id, version}, onComponentSelect} = this.props;
+ let {currentSoftwareProduct: {id, version}, onComponentSelect, isManual, isReadOnlyMode, onDeleteComponent} = this.props;
return (
<ListEditorItemView
key={name + Math.floor(Math.random() * (100 - 1) + 1).toString()}
className='list-editor-item-view'
+ onDelete={isManual && !isReadOnlyMode ? () => onDeleteComponent(component, id, version) : false}
onSelect={() => onComponentSelect({id, componentId, version})}>
<ListEditorItemViewField>
<div className='name'>{displayName}</div>
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js
new file mode 100644
index 0000000000..02c09fbdf8
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js
@@ -0,0 +1,169 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes} from './computeComponents/computeFlavor/ComputeFlavorConstants.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import {actionTypes as globalModalActionTypes, modalSizes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import {COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+
+function baseUrl(softwareProductId, componentId, version) {
+ const versionId = version.id;
+ const restPrefix = Configuration.get('restPrefix');
+ return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/compute-flavors`;
+}
+
+function baseUrlVSPLevel(softwareProductId, version){
+ const versionId = version.id;
+ const restPrefix = Configuration.get('restPrefix');
+ return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/compute-flavors`;
+}
+
+function fetchComputesList(softwareProductId, componentId, version){
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}`);
+}
+
+function fetchComputesListForVSP(softwareProductId, version){
+ return RestAPIUtil.fetch(`${baseUrlVSPLevel(softwareProductId, version)}`);
+}
+
+function fetchCompute(softwareProductId, componentId, computeId, version) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}/${computeId}`);
+}
+
+function fetchComputeQuestionnaire({softwareProductId, componentId, computeId, version}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, componentId, version)}/${computeId}/questionnaire`);
+}
+
+function postCompute({softwareProductId, componentId, compute, version}) {
+ return RestAPIUtil.post(baseUrl(softwareProductId, componentId, version), compute);
+}
+
+function putCompute({softwareProductId, componentId, compute, version}) {
+ const computeData = {
+ name: compute.name,
+ description: compute.description
+ };
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, componentId, version)}/${compute.id}`, computeData);
+}
+
+function putComputeQuestionnaire({softwareProductId, componentId, computeId, qdata, version}) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, componentId, version)}/${computeId}/questionnaire`, qdata);
+}
+
+function deleteCompute({softwareProductId, componentId, computeId, version}) {
+ return RestAPIUtil.destroy(`${baseUrl(softwareProductId, componentId, version)}/${computeId}`);
+}
+
+
+const ComputeFlavorActionHelper = {
+ openComputeEditor(dispatch, {props}) {
+ dispatch({
+ type: actionTypes.computeEditor.LOAD_EDITOR_DATA,
+ compute: props.compute || {}
+ });
+ dispatch({
+ type: globalModalActionTypes.GLOBAL_MODAL_SHOW,
+ data: {
+ modalComponentName: modalContentMapper.COMPONENT_COMPUTE_FLAVOR_EDITOR,
+ modalClassName: `compute-flavor-editor-modal-${props.compute ? 'edit' : 'create'}`,
+ modalComponentProps: {...props, size: props.compute ? modalSizes.LARGE : undefined, dialogClassName:'compute-flavor-editor-modal'},
+ title: `${props.compute ? i18n('Edit Compute Flavor') : i18n('Create New Compute Flavor')}`
+ }
+ });
+ },
+
+ closeComputeEditor(dispatch){
+ dispatch({
+ type: globalModalActionTypes.GLOBAL_MODAL_CLOSE
+ });
+ dispatch({
+ type: actionTypes.computeEditor.CLEAR_DATA
+ });
+ },
+
+ fetchComputesList(dispatch, {softwareProductId, componentId, version}) {
+ return fetchComputesList(softwareProductId, componentId, version).then(response => dispatch({
+ type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED,
+ response
+ }));
+ },
+
+ fetchComputesListForVSP(dispatch, {softwareProductId, version}) {
+ return fetchComputesListForVSP(softwareProductId, version).then(response => dispatch({
+ type: actionTypes.COMPUTE_FLAVORS_LIST_LOADED,
+ response
+ }));
+ },
+
+ loadComputeData({softwareProductId, componentId, computeId, version}) {
+ return fetchCompute(softwareProductId, componentId, computeId, version);
+ },
+
+ loadComputeQuestionnaire(dispatch, {softwareProductId, componentId, computeId, version}) {
+ return fetchComputeQuestionnaire({softwareProductId, componentId, computeId, version}).then(response =>
+ ValidationHelper.qDataLoaded(dispatch, {qName: COMPONENTS_COMPUTE_QUESTIONNAIRE ,response: {
+ qdata: response.data ? JSON.parse(response.data) : {},
+ qschema: JSON.parse(response.schema)
+ }})
+ );
+ },
+
+ loadCompute(dispatch, {softwareProductId, componentId, version, computeId, isReadOnlyMode}){
+ return ComputeFlavorActionHelper.loadComputeData({softwareProductId, componentId, computeId, version}).then(({data}) =>
+ ComputeFlavorActionHelper.loadComputeQuestionnaire(dispatch, {softwareProductId, componentId, computeId, version}).then(() =>
+ ComputeFlavorActionHelper.openComputeEditor(dispatch, {props: {softwareProductId, componentId, version, isReadOnlyMode, compute: {id: computeId, ...data}}})
+ ));
+ },
+
+ saveComputeDataAndQuestionnaire(dispatch, {softwareProductId, componentId, data: compute, qdata, version}) {
+ ComputeFlavorActionHelper.closeComputeEditor(dispatch);
+ if(compute.id) {
+ return Promise.all([
+ putComputeQuestionnaire({softwareProductId, componentId, computeId: compute.id, qdata, version}),
+ putCompute({softwareProductId, componentId, compute, version}).then(() => {
+ dispatch({
+ type: actionTypes.COMPUTE_LIST_EDIT,
+ compute
+ });
+ })
+ ]);
+ }
+ else {
+ return postCompute({softwareProductId, componentId, compute, version}).then(response =>
+ dispatch({
+ type: actionTypes.ADD_COMPUTE,
+ compute: {
+ ...compute,
+ id: response.id,
+ componentId
+ }
+ })
+ );
+ }
+ },
+
+ deleteCompute(dispatch, {softwareProductId, componentId, computeId, version}) {
+ return deleteCompute({softwareProductId, componentId, computeId, version}).then(() => dispatch({
+ type: actionTypes.DELETE_COMPUTE,
+ computeId
+ }));
+ }
+};
+
+export default ComputeFlavorActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/SoftwareProductComponentCompute.js
index e97477b54d..bb8df29b82 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
@@ -19,18 +19,23 @@ import SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwarePr
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';
+import {onboardingMethod} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
-const mapStateToProps = ({softwareProduct}) => {
+const mapStateToProps = ({softwareProduct, currentScreen: {props: {softwareProductId, componentId}}}) => {
let {softwareProductEditor: {data: currentVSP}, softwareProductComponents} = softwareProduct;
- let {componentEditor: {qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
+ let {componentEditor: {qdata, dataMap, qgenericFieldInfo}, computeFlavor: {computesList: computeFlavorsList}} = softwareProductComponents;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentVSP);
return {
qdata,
dataMap,
qgenericFieldInfo,
- isReadOnlyMode
+ isReadOnlyMode,
+ softwareProductId,
+ componentId,
+ computeFlavorsList,
+ isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL
};
};
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 8c197f0d49..dd524a35f3 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
@@ -15,9 +15,9 @@
*/
import React from 'react';
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 ComputeFlavors from './computeComponents/ComputeFlavors.js';
import Validator from 'nfvo-utils/Validator.js';
class SoftwareProductComponentComputeView extends React.Component {
@@ -26,13 +26,15 @@ class SoftwareProductComponentComputeView extends React.Component {
dataMap: React.PropTypes.object,
qgenericFieldInfo: React.PropTypes.object,
isReadOnlyMode: React.PropTypes.bool,
+ isManual: React.PropTypes.bool,
onQDataChanged: React.PropTypes.func.isRequired,
qValidateData: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired
};
render() {
- let {qdata, dataMap, qgenericFieldInfo, isReadOnlyMode, onQDataChanged, qValidateData, onSubmit} = this.props;
+ let {softwareProductId, componentId, version, qdata, dataMap, qgenericFieldInfo, isReadOnlyMode, onQDataChanged, qValidateData,
+ onSubmit, computeFlavorsList, isManual} = this.props;
return (
<div className='vsp-component-questionnaire-view'>
@@ -44,11 +46,12 @@ class SoftwareProductComponentComputeView extends React.Component {
onSubmit={() => onSubmit({qdata})}
className='component-questionnaire-validation-form'
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} />
+ <ComputeFlavors computeFlavorsList={computeFlavorsList} softwareProductId={softwareProductId} componentId={componentId}
+ version={version} isReadOnlyMode={isReadOnlyMode} isManual={isManual}/>
</Form> }
</div>
);
@@ -60,12 +63,24 @@ class SoftwareProductComponentComputeView extends React.Component {
validateMin(value, state) {
let maxVal = state.dataMap['compute/numOfVMs/maximum'];
- return Validator.validateItem(value,maxVal,'maximum');
+ // we are allowed to have an empty maxval, that will allow all minvals.
+ // if we do not have a minval than there is no point to check it either.
+ if (value === undefined || maxVal === undefined) {
+ return { isValid: true, errorText: '' };
+ } else {
+ return Validator.validateItem(value, maxVal,'maximum');
+ }
}
validateMax(value, state) {
let minVal = state.dataMap['compute/numOfVMs/minimum'];
- return Validator.validateItem(value,minVal,'minimum');
+ if (minVal === undefined ) {
+ // having no minimum is the same as 0, maximum value doesn't need to be checked
+ // against it.
+ return { isValid: true, errorText: '' };
+ } else {
+ return Validator.validateItem(value,minVal,'minimum');
+ }
}
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js
new file mode 100644
index 0000000000..c72d42c11f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/ComputeFlavors.js
@@ -0,0 +1,116 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 i18n from 'nfvo-utils/i18n/i18n.js';
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import ComputeFlavorActionHelper from 'sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+
+const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
+ return {
+ onAddComputeClick: (isReadOnlyMode) => ComputeFlavorActionHelper.openComputeEditor(dispatch, {props: {softwareProductId, componentId, isReadOnlyMode, version}}),
+ onEditCompute: ({computeId, isReadOnlyMode}) => ComputeFlavorActionHelper.loadCompute(dispatch, {softwareProductId, componentId, version, computeId, isReadOnlyMode}),
+ onDeleteCompute: ({id, name}) => dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n(`Are you sure you want to delete "${name}"?`),
+ onConfirmed: () => ComputeFlavorActionHelper.deleteCompute(dispatch, {softwareProductId, componentId, computeId: id, version})
+ }
+ })
+ };
+};
+
+const computeItemPropType = React.PropTypes.shape({
+ id: React.PropTypes.string,
+ name: React.PropTypes.string,
+ description: React.PropTypes.string
+});
+
+class ComputeFlavors extends React.Component {
+
+ static propTypes = {
+ isReadOnlyMode: React.PropTypes.bool,
+ isManual: React.PropTypes.bool,
+ onAddComputeClick: React.PropTypes.func,
+ computeFlavorsList: React.PropTypes.arrayOf(computeItemPropType)
+ };
+
+ state = {
+ localFilter: ''
+ };
+
+ render() {
+ const {localFilter} = this.state;
+ const {isReadOnlyMode, isManual, onAddComputeClick, onEditCompute, onDeleteCompute} = this.props;
+ return (
+ <div className='computes-list'>
+ <ListEditorView
+ title={i18n('Computes')}
+ plusButtonTitle={i18n('Add Compute')}
+ onAdd={isManual ? () => onAddComputeClick(isReadOnlyMode) : null}
+ isReadOnlyMode={isReadOnlyMode}
+ onFilter={isManual ? value => this.setState({localFilter: value}) : null}
+ filterValue={localFilter}
+ twoColumns>
+ {this.filterList().map(computeItem =>
+ <ComputeItem key={computeItem.id}
+ computeItem={computeItem} isReadOnlyMode={isReadOnlyMode} isManual={isManual}
+ onEditCompute={onEditCompute} onDeleteCompute={onDeleteCompute}/>)
+ }
+ </ListEditorView>
+ </div>
+ );
+ }
+
+ filterList() {
+ const {computeFlavorsList = []} = this.props;
+
+ const {localFilter} = this.state;
+ if (localFilter.trim()) {
+ const filter = new RegExp(escape(localFilter), 'i');
+ return computeFlavorsList.filter(({name = '', description = ''}) => {
+ return escape(name).match(filter) || escape(description).match(filter);
+ });
+ }
+ else {
+ return computeFlavorsList;
+ }
+ }
+}
+
+const ComputeItem = ({computeItem, isReadOnlyMode, isManual, onEditCompute, onDeleteCompute}) => {
+ const {id, name, description} = computeItem;
+ return (
+ <ListEditorItemView
+ key={'item_' + id}
+ className='list-editor-item-view'
+ isReadOnlyMode={isReadOnlyMode}
+ onSelect={() => onEditCompute({computeId: id, isReadOnlyMode})}
+ onDelete={isManual ? () => onDeleteCompute({id, name}) : null}>
+
+ <div className='list-editor-item-view-field'>
+ <div className='name'>{name}</div>
+ </div>
+ <div className='list-editor-item-view-field'>
+ <div className='description'>{description}</div>
+ </div>
+ </ListEditorItemView>
+ );
+};
+
+export default connect(null, mapActionsToProps, null, {withRef: true})(ComputeFlavors);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx
index 7a730d6f94..16bf599834 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/GuestOs.jsx
@@ -24,17 +24,6 @@ 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>
@@ -58,6 +47,16 @@ const GuestOs = ({qgenericFieldInfo, dataMap, onQDataChanged}) => {
<GridItem colSpan={2}/>
<GridItem colSpan={2}>
<Input
+ data-test-id='guestOS-name'
+ label={i18n('Guest OS')}
+ type='textarea'
+ onChange={(tools) => onQDataChanged({'compute/guestOS/name' : tools})}
+ isValid={qgenericFieldInfo['compute/guestOS/name'].isValid}
+ errorText={qgenericFieldInfo['compute/guestOS/name'].errorText}
+ value={dataMap['compute/guestOS/name']} />
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
data-test-id='guestOS-tools'
type='textarea'
label={i18n('Guest OS Tools:')}
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx
index efeedc653e..ddde4391d9 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/NumberOfVms.jsx
@@ -45,44 +45,6 @@ const NumberOfVms = ({qgenericFieldInfo, dataMap, onQDataChanged, qValidateData,
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>
);
};
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
deleted file mode 100644
index 39f84807a2..0000000000
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/VmSizing.jsx
+++ /dev/null
@@ -1,68 +0,0 @@
-/*!
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this 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/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js
new file mode 100644
index 0000000000..41728eefb0
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorConstants.js
@@ -0,0 +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 keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const COMPUTE_FLAVOR_FORM = 'COMPUTE_FLAVOR_FORM';
+
+export const actionTypes = keyMirror({
+ ADD_COMPUTE: null,
+ COMPUTE_FLAVORS_LIST_LOADED: null,
+ COMPUTE_LIST_EDIT: null,
+ EDIT_COMPUTE_FLAVOR: null,
+ DELETE_COMPUTE: null,
+ CONFIRM_DELETE_COMPUTE: null,
+ computeEditor: {
+ LOAD_EDITOR_DATA: null,
+ CLEAR_DATA: null
+ }
+});
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js
new file mode 100644
index 0000000000..caec0702fd
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditor.js
@@ -0,0 +1,55 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 ComputeFlavorEditorView from './ComputeFlavorEditorView.jsx';
+import {COMPUTE_FLAVOR_FORM} from './ComputeFlavorConstants.js';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import ComputeFlavorActionHelper from 'sdc-app/onboarding/softwareProduct/components/compute/ComputeFlavorActionHelper.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import {COMPONENTS_COMPUTE_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import {onboardingMethod} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+
+export const mapStateToProps = ({softwareProduct: {softwareProductEditor, softwareProductComponents: {computeFlavor: {computeEditor = {}}}}}) => {
+ const {data: currentSoftwareProduct = {}} = softwareProductEditor;
+ const isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+ let {data , qdata, qgenericFieldInfo, dataMap, genericFieldInfo, formReady} = computeEditor;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
+ return {
+ data,
+ qdata,
+ qgenericFieldInfo,
+ dataMap,
+ genericFieldInfo,
+ isReadOnlyMode,
+ isFormValid,
+ formReady,
+ isManual: currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL
+ };
+};
+
+
+const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
+ return {
+ onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: COMPUTE_FLAVOR_FORM}),
+ onQDataChanged: deltaData => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_COMPUTE_QUESTIONNAIRE}),
+ onCancel: () => ComputeFlavorActionHelper.closeComputeEditor(dispatch),
+ onSubmit: ({data, qdata}) => ComputeFlavorActionHelper.saveComputeDataAndQuestionnaire(dispatch, {softwareProductId, componentId, data, qdata, version}),
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, COMPUTE_FLAVOR_FORM)
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(ComputeFlavorEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.jsx
new file mode 100644
index 0000000000..8f8a504629
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorEditorView.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 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 VmSizing from './VmSizing.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+
+class ComputeEditorView extends React.Component {
+
+ static propTypes = {
+ data: React.PropTypes.object,
+ qdata: React.PropTypes.object,
+ qschema: React.PropTypes.object,
+ isReadOnlyMode: React.PropTypes.bool,
+ isManual: React.PropTypes.bool,
+ onDataChanged: React.PropTypes.func.isRequired,
+ onQDataChanged: React.PropTypes.func.isRequired,
+ onSubmit: React.PropTypes.func.isRequired,
+ onCancel: React.PropTypes.func.isRequired
+ };
+
+ render() {
+ let {data = {}, qdata = {}, qgenericFieldInfo, dataMap, genericFieldInfo, isReadOnlyMode, isManual, isFormValid, formReady,
+ onDataChanged, onQDataChanged, onSubmit, onCancel, onValidateForm} = this.props;
+ const {id, name, description} = data;
+ const edittingComputeMode = Boolean(id);
+
+ return (
+ <div className='vsp-component-computeFlavor-view'>
+ {genericFieldInfo && <Form
+ ref={(form) => {
+ this.form = form;
+ }}
+ hasButtons={true}
+ onSubmit={ () => onSubmit({data, qdata}) }
+ onReset={ () => onCancel() }
+ labledButtons={true}
+ isReadOnlyMode={isReadOnlyMode}
+ isValid={isFormValid}
+ formReady={formReady}
+ onValidateForm={() => onValidateForm() }
+ className='component-questionnaire-validation-form'
+ submitButtonText={edittingComputeMode ? i18n('Save') : i18n('Create')}>
+ <GridSection>
+ <GridItem colSpan={edittingComputeMode ? 2 : 4}>
+ <Input
+ disabled={!isManual}
+ data-test-id='name'
+ type='text'
+ label={i18n('Flavor Name')}
+ value={name}
+ onChange={name => onDataChanged({name})}
+ isValid={genericFieldInfo['name'].isValid}
+ errorText={genericFieldInfo['name'].errorText}
+ isRequired/>
+ </GridItem>
+ <GridItem colSpan={edittingComputeMode ? 2 : 4}>
+ <Input
+ data-test-id='description'
+ type='textarea'
+ label={i18n('Description')}
+ value={description}
+ onChange={description => onDataChanged({description})}
+ isValid={genericFieldInfo['description'].isValid}
+ errorText={genericFieldInfo['description'].errorText}/>
+ </GridItem>
+ </GridSection>
+ {edittingComputeMode && <VmSizing qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged}/>}
+ </Form>
+ }
+ </div>
+ );
+ }
+
+ save(){
+ return this.form.handleFormSubmit(new Event('dummy'));
+ }
+}
+
+export default ComputeEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js
new file mode 100644
index 0000000000..6c02f36c90
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.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 {actionTypes} from './ComputeFlavorConstants.js';
+
+export default (state = [], action) => {
+ switch (action.type) {
+ case actionTypes.COMPUTE_FLAVORS_LIST_LOADED:
+ return [...action.response.results];
+ case actionTypes.ADD_COMPUTE:
+ return [...state, action.compute];
+ case actionTypes.COMPUTE_LIST_EDIT:
+ const indexForEdit = state.findIndex(({id}) => id === action.compute.id);
+ return [...state.slice(0, indexForEdit), action.compute, ...state.slice(indexForEdit + 1)];
+ case actionTypes.DELETE_COMPUTE:
+ return state.filter(({id}) => id !== action.computeId);
+ default:
+ return state;
+ }
+}; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.js
new file mode 100644
index 0000000000..a476f85a19
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/ComputeFlavorReducer.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, COMPUTE_FLAVOR_FORM} from './ComputeFlavorConstants.js';
+
+export default (state = {}, action) => {
+ switch (action.type) {
+ case actionTypes.computeEditor.LOAD_EDITOR_DATA:
+ return {
+ ...state,
+ formName: COMPUTE_FLAVOR_FORM,
+ data: action.compute,
+ formReady: null,
+ genericFieldInfo: {
+ name: {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true }]
+ },
+ description: {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 300}]
+ }
+ }
+ };
+ case actionTypes.computeEditor.CLEAR_DATA:
+ return {};
+ default:
+ return state;
+ }
+};
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx
new file mode 100644
index 0000000000..8b30468362
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/compute/computeComponents/computeFlavor/VmSizing.jsx
@@ -0,0 +1,106 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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({'vmSizing/numOfCPUs' : tools})}
+ isValid={qgenericFieldInfo['vmSizing/numOfCPUs'].isValid}
+ errorText={qgenericFieldInfo['vmSizing/numOfCPUs'].errorText}
+ value={dataMap['vmSizing/numOfCPUs']} />
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='fileSystemSizeGB'
+ type='number'
+ label={i18n('File System Size (GB)')}
+ onChange={(tools) => onQDataChanged({'vmSizing/fileSystemSizeGB' : tools})}
+ isValid={qgenericFieldInfo['vmSizing/fileSystemSizeGB'].isValid}
+ errorText={qgenericFieldInfo['vmSizing/fileSystemSizeGB'].errorText}
+ value={dataMap['vmSizing/fileSystemSizeGB']} />
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='persistentStorageVolumeSize'
+ type='number'
+ label={i18n('Persistent Storage/Volume Size (GB)')}
+ onChange={(tools) => onQDataChanged({'vmSizing/persistentStorageVolumeSize' : tools})}
+ isValid={qgenericFieldInfo['vmSizing/persistentStorageVolumeSize'].isValid}
+ errorText={qgenericFieldInfo['vmSizing/persistentStorageVolumeSize'].errorText}
+ value={dataMap['vmSizing/persistentStorageVolumeSize']} />
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='ioOperationsPerSec'
+ type='number'
+ label={i18n('I/O Operations (per second)')}
+ onChange={(tools) => onQDataChanged({'vmSizing/ioOperationsPerSec' : tools})}
+ isValid={qgenericFieldInfo['vmSizing/ioOperationsPerSec'].isValid}
+ errorText={qgenericFieldInfo['vmSizing/ioOperationsPerSec'].errorText}
+ value={dataMap['vmSizing/ioOperationsPerSec']} />
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='numOfVMs-cpuOverSubscriptionRatio'
+ label={i18n('CPU Oversubscription Ratio')}
+ type='select'
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ isValid={qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].isValid}
+ errorText={qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].errorText}
+ value={dataMap['vmSizing/cpuOverSubscriptionRatio']}
+ onChange={(e) => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onQDataChanged({'vmSizing/cpuOverSubscriptionRatio' : val});}
+ }>
+ <option key='placeholder' value=''>{i18n('Select...')}</option>
+ {qgenericFieldInfo['vmSizing/cpuOverSubscriptionRatio'].enum.map(cpuOSR => <option value={cpuOSR.enum} key={cpuOSR.enum}>{cpuOSR.title}</option>)}
+ </Input>
+ </GridItem>
+ <GridItem>
+ <Input
+ data-test-id='numOfVMs-memoryRAM'
+ type='select'
+ label={i18n('Memory - RAM')}
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ isValid={qgenericFieldInfo['vmSizing/memoryRAM'].isValid}
+ errorText={qgenericFieldInfo['vmSizing/memoryRAM'].errorText}
+ value={dataMap['vmSizing/memoryRAM']}
+ onChange={(e) => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onQDataChanged({'vmSizing/memoryRAM' : val});}
+ }>
+ <option key='placeholder' value=''>{i18n('Select...')}</option>
+ {qgenericFieldInfo['vmSizing/memoryRAM'].enum.map(mRAM => <option value={mRAM.enum} key={mRAM.enum}>{mRAM.title}</option>)}
+ </Input>
+ </GridItem>
+ </GridSection>
+ );
+};
+
+export default VmSizing;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.js
new file mode 100644
index 0000000000..e85b6b6504
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreation.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 {connect} from 'react-redux';
+import SoftwareProductComponentCreationView from './SoftwareProductComponentCreationView.jsx';
+import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import {forms} from '../SoftwareProductComponentsConstants.js';
+
+export const mapStateToProps = ({softwareProduct}) => {
+ let {softwareProductComponents: {componentEditor: {data, genericFieldInfo, formReady}}, softwareProductEditor: {data: {version}}} = softwareProduct;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+ return {
+ data,
+ genericFieldInfo,
+ formReady,
+ isFormValid,
+ version
+ };
+};
+
+
+const mapActionsToProps = (dispatch, {softwareProductId}) => {
+ return {
+ onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.CREATE_FORM}),
+ //onDataChanged: deltaData => SoftwareProductComponentsActionHelper.componentDataChanged(dispatch, {deltaData}),
+ onSubmit: (componentData, version) => {
+ return SoftwareProductComponentsActionHelper.createSoftwareProductComponent(dispatch,
+ {softwareProductId, componentData, version});
+ },
+ onCancel: () => SoftwareProductComponentsActionHelper.closeComponentCreationModal(dispatch),
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
+ };
+
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentCreationView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.jsx
new file mode 100644
index 0000000000..55bcc818f5
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/creation/SoftwareProductComponentCreationView.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 i18n from 'nfvo-utils/i18n/i18n.js';
+
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+import {forms} from '../SoftwareProductComponentsConstants.js';
+
+class ComponentCreationView extends React.Component {
+ render() {
+ let {data = {}, onDataChanged, onCancel, genericFieldInfo} = this.props;
+ let {displayName, description} = data;
+ return(
+ <div>
+ {
+ genericFieldInfo && <Form
+ ref='validationForm'
+ hasButtons={true}
+ onSubmit={ () => this.submit() }
+ onReset={ () => onCancel() }
+ submitButtonText={i18n('Create')}
+ labledButtons={true}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm(forms.CREATE_FORM) }
+ className='entitlement-pools-form'>
+ <GridSection>
+ <GridItem colSpan={4}>
+ <Input
+ data-test-id='name'
+ onChange={displayName => onDataChanged({displayName})}
+ label={i18n('Name')}
+ isRequired={true}
+ isValid={genericFieldInfo.displayName.isValid}
+ errorText={genericFieldInfo.displayName.errorText}
+ value={displayName}
+ type='text'/>
+ </GridItem>
+ <GridItem colSpan={4}>
+ <Input
+ label={i18n('Description')}
+ onChange={description => onDataChanged({description})}
+ value={description}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ data-test-id='description'
+ type='textarea'/>
+ </GridItem>
+ </GridSection>
+ </Form>
+ }
+ </div>
+ );
+ }
+
+ submit() {
+ const {onSubmit, data, version} = this.props;
+ onSubmit(data, version);
+ }
+}
+
+export default ComponentCreationView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneral.js
index 34374aa7fb..7b4135028b 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
@@ -22,6 +22,7 @@ import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/Soft
import {forms, COMPONENTS_QUESTIONNAIRE} from '../SoftwareProductComponentsConstants.js';
+import {onboardingMethod} from '../../SoftwareProductConstants.js';
export const mapStateToProps = ({softwareProduct}) => {
@@ -34,6 +35,7 @@ export const mapStateToProps = ({softwareProduct}) => {
componentData,
qdata,
isReadOnlyMode,
+ isManual: currentVSP.onboardingMethod === onboardingMethod.MANUAL,
genericFieldInfo,
qGenericFieldInfo,
dataMap,
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 e4595f97d6..6aa51d1609 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/general/SoftwareProductComponentsGeneralView.jsx
@@ -21,7 +21,7 @@ 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}) => (
+const GeneralSection = ({onDataChanged, displayName, vfcCode, nfcFunction, description, isReadOnlyMode, genericFieldInfo, isManual}) => (
<GridSection title={i18n('General')}>
{/* disabled until backend will be ready to implement it
<div className='validation-input-wrapper'>
@@ -37,9 +37,9 @@ const GeneralSection = ({onDataChanged, displayName, vfcCode, description, isRea
data-test-id='name'
label={i18n('Name')}
value={displayName}
- disabled={true}
+ disabled={!isManual || isReadOnlyMode}
type='text'/>
- <Input
+ {!isManual && <Input
data-test-id='vfcCode'
label={i18n('Naming Code')}
value={vfcCode}
@@ -47,6 +47,15 @@ const GeneralSection = ({onDataChanged, displayName, vfcCode, description, isRea
errorText={genericFieldInfo.vfcCode.errorText}
onChange={vfcCode => onDataChanged({vfcCode})}
disabled={isReadOnlyMode}
+ type='text'/> }
+ <Input
+ data-test-id='nfcFunction'
+ label={i18n('Function')}
+ value={nfcFunction}
+ isValid={genericFieldInfo.nfcFunction.isValid}
+ errorText={genericFieldInfo.nfcFunction.errorText}
+ onChange={nfcFunction => onDataChanged({nfcFunction})}
+ disabled={isReadOnlyMode}
type='text'/>
</GridItem>
<GridItem colSpan={2}>
@@ -63,7 +72,7 @@ const GeneralSection = ({onDataChanged, displayName, vfcCode, description, isRea
</GridItem>
<GridItem />
</GridSection>
- );
+);
const HypervisorSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
<GridSection title={i18n('Hypervisor')}>
@@ -110,64 +119,26 @@ const HypervisorSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
);
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>
+ <GridSection title={i18n('Disk')}>
<GridItem>
<Input
data-test-id='bootDiskSizePerVM'
- onChange={(bootDiskSizePerVM) => onQDataChanged({'general/image/bootDiskSizePerVM' : bootDiskSizePerVM})}
+ onChange={(bootDiskSizePerVM) => onQDataChanged({'general/disk/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']}/>
+ isValid={qgenericFieldInfo['general/disk/bootDiskSizePerVM'].isValid}
+ errorText={qgenericFieldInfo['general/disk/bootDiskSizePerVM'].errorText}
+ value={dataMap['general/disk/bootDiskSizePerVM']}/>
</GridItem>
<GridItem>
<Input
data-test-id='ephemeralDiskSizePerVM'
- onChange={(ephemeralDiskSizePerVM) => onQDataChanged({'general/image/ephemeralDiskSizePerVM' : ephemeralDiskSizePerVM})}
+ onChange={(ephemeralDiskSizePerVM) => onQDataChanged({'general/disk/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']}/>
+ isValid={qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'].isValid}
+ errorText={qgenericFieldInfo['general/disk/ephemeralDiskSizePerVM'].errorText}
+ value={dataMap['general/disk/ephemeralDiskSizePerVM']}/>
</GridItem>
</GridSection>
);
@@ -257,7 +228,7 @@ const CloneSection = ({dataMap, onQDataChanged, qgenericFieldInfo}) => (
class SoftwareProductComponentsGeneralView extends React.Component {
render() {
- let {onQDataChanged, onDataChanged, genericFieldInfo, dataMap, qGenericFieldInfo, componentData: {displayName, vfcCode, description}, isReadOnlyMode} = this.props;
+ let {isManual, onQDataChanged, onDataChanged, genericFieldInfo, dataMap, qGenericFieldInfo, componentData: {displayName, vfcCode, nfcFunction, description}, isReadOnlyMode} = this.props;
return(
<div className='vsp-components-general'>
<div className='general-data'>
@@ -271,7 +242,9 @@ class SoftwareProductComponentsGeneralView extends React.Component {
onDataChanged={onDataChanged}
displayName={displayName}
vfcCode={vfcCode}
+ nfcFunction={nfcFunction}
description={description}
+ isManual={isManual}
isReadOnlyMode={isReadOnlyMode}
genericFieldInfo={genericFieldInfo}/>
<HypervisorSection onQDataChanged={onQDataChanged} dataMap={dataMap} qgenericFieldInfo={qGenericFieldInfo}/>
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js
new file mode 100644
index 0000000000..34198281b7
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js
@@ -0,0 +1,169 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 i18n from 'nfvo-utils/i18n/i18n.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import {IMAGE_QUESTIONNAIRE} from './SoftwareProductComponentsImageConstants.js';
+import {actionTypes} from './SoftwareProductComponentsImageConstants.js';
+
+function baseUrl(softwareProductId, version, componentId) {
+ const versionId = version.id;
+ const restPrefix = Configuration.get('restPrefix');
+ return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/images`;
+}
+
+function fetchImagesList({softwareProductId, componentId, version}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`);
+}
+
+function fetchImage({softwareProductId, componentId, imageId, version}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${imageId}`);
+}
+
+function destroyImage({softwareProductId, componentId, version, imageId}) {
+ return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${imageId}`);
+}
+
+function createImage({softwareProductId, componentId, version, data}) {
+ return RestAPIUtil.post(baseUrl(softwareProductId, version, componentId), {
+ fileName: data.fileName
+ });
+}
+
+function fetchImageQuestionnaire({softwareProductId, componentId, imageId, version}) {
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${imageId}/questionnaire`);
+}
+
+function saveImage({softwareProductId, version, componentId, image: {id, fileName}}) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${id}`,{
+ fileName
+ });
+
+}
+
+function saveImageQuestionnaire({softwareProductId, componentId, version, imageId, qdata}) {
+ return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${imageId}/questionnaire`, qdata);
+}
+
+const SoftwareProductComponentImagesActionHelper = {
+ fetchImagesList(dispatch, {softwareProductId, componentId, version}) {
+ dispatch({
+ type: actionTypes.IMAGES_LIST_UPDATE,
+ response: []
+ });
+
+ return fetchImagesList({softwareProductId, componentId, version}).then((response) => {
+ dispatch({
+ type: actionTypes.IMAGES_LIST_UPDATE,
+ response: response.results,
+ componentId : componentId
+ });
+ });
+ },
+
+ deleteImage(dispatch, {softwareProductId, componentId, version, imageId}) {
+ return destroyImage({softwareProductId, componentId, version, imageId}).then(() => {
+ return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version});
+ });
+ },
+
+ loadImageData({softwareProductId, componentId, imageId, version}) {
+ return fetchImage({softwareProductId, componentId, imageId, version});
+ },
+
+ openEditImageEditor(dispatch, {image, softwareProductId, componentId, version, isReadOnlyMode, modalClassName}) {
+ return SoftwareProductComponentImagesActionHelper.loadImageData({softwareProductId, componentId, imageId: image.id, version}).then(({data}) => {
+ SoftwareProductComponentImagesActionHelper.loadImageQuestionnaire(dispatch, {
+ softwareProductId,
+ componentId,
+ imageId: image.id,
+ version
+ }).then(() => {
+ SoftwareProductComponentImagesActionHelper.openImageEditor(dispatch, {
+ softwareProductId,
+ componentId,
+ version,
+ isReadOnlyMode,
+ modalClassName,
+ image,
+ data
+ });
+ });
+ });
+ },
+
+ openImageEditor(dispatch, {image = {}, data = {}, softwareProductId, componentId, version, isReadOnlyMode}) {
+
+ let title = (image && image.id) ? i18n('Edit Image') : i18n('Create New Image');
+ let className = (image && image.id) ? 'image-edit-editor-model' : 'image-new-editor-modal';
+
+ dispatch({
+ type: actionTypes.ImageEditor.OPEN,
+ image: {...data, id: image.id}
+ });
+
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_SHOW,
+ data: {
+ modalComponentName: modalContentMapper.SOFTWARE_PRODUCT_COMPONENT_IMAGE_EDITOR,
+ title: title,
+ modalComponentProps: {softwareProductId, componentId, version, isReadOnlyMode, dialogClassName:className}
+ }
+ });
+ },
+
+ closeImageEditor(dispatch) {
+
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
+ });
+
+ dispatch({
+ type: actionTypes.ImageEditor.CLOSE
+ });
+ },
+
+ loadImageQuestionnaire(dispatch, {softwareProductId, componentId, imageId, version}) {
+ return fetchImageQuestionnaire({softwareProductId, componentId, imageId, version}).then((response) => {
+ ValidationHelper.qDataLoaded(dispatch, {qName: IMAGE_QUESTIONNAIRE ,response: {
+ qdata: response.data ? JSON.parse(response.data) : {},
+ qschema: JSON.parse(response.schema)
+ }});
+ });
+ },
+
+ saveImageDataAndQuestionnaire(dispatch, {softwareProductId, componentId, version, data, qdata}) {
+ SoftwareProductComponentImagesActionHelper.closeImageEditor(dispatch);
+ if (data !== null && data.id) {
+ // editor in edit mode
+ return Promise.all([
+ saveImageQuestionnaire({softwareProductId, version, componentId, imageId: data.id, qdata}),
+ saveImage({softwareProductId, version, componentId, image: data}).then(() => {
+ return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version});
+ })
+ ]);
+ } else {
+ // editor in create mode
+ createImage({softwareProductId, componentId, version, data}).then(() => {
+ return SoftwareProductComponentImagesActionHelper.fetchImagesList(dispatch, {softwareProductId, componentId, version});
+ });
+ }
+ }
+};
+export default SoftwareProductComponentImagesActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.js
new file mode 100644
index 0000000000..6b6c9a30e5
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageConstants.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 keyMirror from 'nfvo-utils/KeyMirror.js';
+
+export const actionTypes = keyMirror({
+ IMAGES_LIST_UPDATE: null,
+
+ ImageEditor: {
+ CLOSE: null,
+ OPEN: null
+ }
+});
+
+export const IMAGE_QUESTIONNAIRE = 'image';
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js
new file mode 100644
index 0000000000..49d891c9df
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditor.js
@@ -0,0 +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 {connect} from 'react-redux';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import SoftwareProductComponentsImageActionHelper from './SoftwareProductComponentsImageActionHelper.js';
+import SoftwareProductComponentsImageEditorView from './SoftwareProductComponentsImageEditorView.jsx';
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
+import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import {IMAGE_QUESTIONNAIRE} from './SoftwareProductComponentsImageConstants.js';
+
+export const mapStateToProps = ({softwareProduct}) => {
+
+ let {softwareProductEditor: {data:currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct;
+
+ let {images: {imageEditor = {}}} = softwareProductComponents;
+ let {data, qdata, genericFieldInfo, qgenericFieldInfo, dataMap, formReady} = imageEditor;
+ let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+ let {version, onboardingMethod} = currentSoftwareProduct;
+ let isManual = onboardingMethod === onboardingMethodTypes.MANUAL;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo) && ValidationHelper.checkFormValid(qgenericFieldInfo);
+
+ return {
+ version,
+ currentSoftwareProduct,
+ isValidityData,
+ data,
+ qdata,
+ dataMap,
+ isFormValid,
+ formReady,
+ genericFieldInfo,
+ qgenericFieldInfo,
+ isReadOnlyMode,
+ isManual: isManual
+ };
+};
+
+const mapActionsToProps = (dispatch, {softwareProductId, componentId, version}) => {
+ return {
+ onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: forms.IMAGE_EDIT_FORM}),
+ onSubmit: ({data, qdata}) => SoftwareProductComponentsImageActionHelper.saveImageDataAndQuestionnaire(dispatch, {softwareProductId, componentId, version, data, qdata}),
+ onCancel: () => SoftwareProductComponentsImageActionHelper.closeImageEditor(dispatch),
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, forms.IMAGE_EDIT_FORM),
+ onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
+ qName: IMAGE_QUESTIONNAIRE}),
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(SoftwareProductComponentsImageEditorView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.js
new file mode 100644
index 0000000000..0ab785a97f
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorReducer.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 {actionTypes} from './SoftwareProductComponentsImageConstants.js';
+import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+
+export default (state = {}, action) => {
+ switch (action.type) {
+ case actionTypes.ImageEditor.CLOSE:
+ return {};
+ case actionTypes.ImageEditor.OPEN:
+ return {
+ ...state,
+ data: {
+ ...action.image
+ },
+ genericFieldInfo: {
+ 'fileName' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'validateName', data: true}]
+ }
+ },
+ formName: forms.IMAGE_EDIT_FORM
+ };
+ default:
+ return state;
+ }
+};
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx
new file mode 100644
index 0000000000..300f8edcc3
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageEditorView.jsx
@@ -0,0 +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 Form from 'nfvo-components/input/validation/Form.jsx';
+
+import FileDetails from './imagesEditorComponents/FileDetails.jsx';
+import ImageDetails from './imagesEditorComponents/ImageDetails.jsx';
+
+class SoftwareProductComponentsImageEditorView extends React.Component {
+ static propTypes = {
+ onDataChanged: React.PropTypes.func.isRequired,
+ onSubmit: React.PropTypes.func.isRequired,
+ onCancel: React.PropTypes.func.isRequired
+ };
+
+ render() {
+ let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, genericFieldInfo, qgenericFieldInfo, dataMap, onDataChanged, isManual, onQDataChanged} = this.props;
+ let {id, fileName} = data;
+ let editingMode = Boolean(id);
+ return (
+ <div>
+ {genericFieldInfo && <Form
+ ref={(form) => { this.form = form; }}
+ hasButtons={true}
+ onSubmit={ () => this.submit() }
+ onReset={ () => onCancel() }
+ labledButtons={true}
+ isReadOnlyMode={isReadOnlyMode}
+ isValid={isFormValid}
+ formReady={formReady}
+ submitButtonText={editingMode ? i18n('Save') : i18n('Create')}
+ onValidateForm={() => onValidateForm() }
+ className='vsp-components-image-editor'>
+ <div className='editor-data'>
+ <FileDetails
+ editingMode={editingMode}
+ genericFieldInfo={genericFieldInfo}
+ qgenericFieldInfo={qgenericFieldInfo}
+ fileName={fileName}
+ onDataChanged={onDataChanged}
+ isManual={isManual}
+ dataMap={dataMap}
+ onQDataChanged={onQDataChanged}/>
+ {editingMode && <ImageDetails dataMap={dataMap}qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged}/>}
+ </div>
+ </Form>}
+ </div>
+ );
+ }
+ submit() {
+ let {data, qdata, onSubmit, version} = this.props;
+ onSubmit({data, qdata, version});
+ }
+}
+
+export default SoftwareProductComponentsImageEditorView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js
new file mode 100644
index 0000000000..86c4e072d4
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js
@@ -0,0 +1,88 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 i18n from 'nfvo-utils/i18n/i18n.js';
+
+import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import SoftwareProductComponentsImageListView from './SoftwareProductComponentsImageListView.jsx';
+import ImageHelper from './SoftwareProductComponentsImageActionHelper.js';
+import SoftwareProductComponentsImagesActionHelper from './SoftwareProductComponentsImageActionHelper.js';
+import SoftwareProductComponentsActionHelper from '../SoftwareProductComponentsActionHelper.js';
+import {COMPONENTS_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+
+import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
+
+export const mapStateToProps = ({softwareProduct}) => {
+
+ let {softwareProductEditor: {data: currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct;
+ let {images: {imagesList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
+ let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+ let {version, onboardingMethod} = currentSoftwareProduct;
+ let isManual = onboardingMethod === onboardingMethodTypes.MANUAL;
+
+ return {
+ version,
+ componentData,
+ qdata,
+ dataMap,
+ qgenericFieldInfo,
+ isValidityData,
+ imagesList,
+ isReadOnlyMode,
+ isManual : isManual
+ };
+};
+
+const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
+ return {
+ onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
+ qName: COMPONENTS_QUESTIONNAIRE}),
+ onAddImage: (version, isReadOnlyMode) => {
+ SoftwareProductComponentsImagesActionHelper.openImageEditor(dispatch,
+ {isReadOnlyMode, softwareProductId,
+ componentId, version}
+ );},
+ onDeleteImage: ((image, version) => {
+ let shortenedFileName = (image.fileName.length > 40) ? image.fileName.substr(0,40) + '...' : image.fileName;
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_WARNING,
+ data: {
+ msg: i18n(`Are you sure you want to delete "${shortenedFileName}"?`),
+ onConfirmed: () => ImageHelper.deleteImage(dispatch, {
+ softwareProductId,
+ componentId,
+ version,
+ imageId: image.id
+ })
+ }
+ });
+ }),
+ onEditImageClick: (image, version, isReadOnlyMode) => {
+ SoftwareProductComponentsImagesActionHelper.openEditImageEditor(dispatch, {
+ image, isReadOnlyMode, softwareProductId, componentId, version, modalClassName: 'image-modal-edit'}
+ );
+ },
+ onSubmit: ({qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
+ {softwareProductId,
+ vspComponentId: componentId,
+ qdata});
+ }
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps, null, {withRef: true})(SoftwareProductComponentsImageListView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js
new file mode 100644
index 0000000000..5dd2fb623b
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListReducer.js
@@ -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 {actionTypes} from './SoftwareProductComponentsImageConstants.js';
+
+export default (state = [], action) => {
+ switch (action.type) {
+
+ case actionTypes.IMAGES_LIST_UPDATE:
+ return [...action.response];
+ default:
+ return state;
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx
new file mode 100644
index 0000000000..ccf5b9d6b1
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx
@@ -0,0 +1,132 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 Form from 'nfvo-components/input/validation/Form.jsx';
+
+import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
+import Input from'nfvo-components/input/validation/Input.jsx';
+
+class SoftwareProductComponentsImageListView extends React.Component {
+ state = {
+ localFilter: ''
+ };
+
+ render() {
+ let {dataMap, onQDataChanged, isReadOnlyMode, qgenericFieldInfo} = this.props;
+ return(
+ <div className='vsp-components-image'>
+ <div className='image-data'>
+ <div>
+ { qgenericFieldInfo && <Form
+ formReady={null}
+ isValid={true}
+ onSubmit={() => this.save()}
+ isReadOnlyMode={isReadOnlyMode}
+ hasButtons={false}>
+
+ <h3 className='section-title'>{i18n('Image')}</h3>
+ <div className='rows-section'>
+ <div className='row-flex-components'>
+ <div className='single-col'>
+ <Input
+ data-test-id='providedBy'
+ label={i18n('Image provided by')}
+ type='select'
+ isValid={qgenericFieldInfo['general/image/providedBy'].isValid}
+ errorText={qgenericFieldInfo['general/image/providedBy'].errorText}
+ value={dataMap['general/image/providedBy']}
+ onChange={(e) => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onQDataChanged({'general/image/providedBy' : val});}
+ }>
+ <option key='placeholder' value=''>{i18n('Select...')}</option>
+ { qgenericFieldInfo['general/image/providedBy'].enum.map(proto =>
+ <option value={proto.enum} key={proto.enum}>{proto.title}</option>) }
+ </Input>
+ </div>
+ <div className='empty-two-col' />
+ </div>
+ </div>
+
+ </Form> }
+ </div>
+ </div>
+ {this.renderImagesList()}
+ </div>
+ );
+ };
+
+ renderImagesList() {
+ const {localFilter} = this.state;
+ let {isReadOnlyMode, onAddImage, isManual, version} = this.props;
+
+ return (
+ <ListEditorView
+ title={i18n('Images')}
+ filterValue={localFilter}
+ placeholder={i18n('Filter Images by Name')}
+ isReadOnlyMode={isReadOnlyMode}
+ onFilter={value => this.setState({localFilter: value})}
+ onAdd={isManual ? () => onAddImage(version, isReadOnlyMode) : null}
+ plusButtonTitle={i18n('Add Image')}
+ twoColumns>
+ {this.filterList().map(image => this.renderImagesListItem(image, isReadOnlyMode))}
+ </ListEditorView>
+ );
+ };
+
+
+ renderImagesListItem(image, isReadOnlyMode) {
+ let {id, fileName} = image;
+ let {onEditImageClick, version, isManual, onDeleteImage} = this.props;
+ return (
+ <ListEditorItemView
+ key={id}
+ isReadOnlyMode={isReadOnlyMode}
+ onSelect={() => onEditImageClick(image, version, isReadOnlyMode)}
+ onDelete={isManual ? () => onDeleteImage(image, version) : null}>
+
+ <ListEditorItemViewField>
+ <div className='image-filename-cell'><span className='image-filename'>{fileName}</span></div>
+ </ListEditorItemViewField>
+ </ListEditorItemView>
+ );
+ }
+
+ filterList() {
+ let {imagesList} = this.props;
+ let {localFilter} = this.state;
+ if (localFilter.trim()) {
+ const filter = new RegExp(escape(localFilter), 'i');
+ return imagesList.filter(({fileName = ''}) => {
+ return escape(fileName).match(filter);
+ });
+ }
+ else {
+ return imagesList;
+ }
+ }
+
+ save() {
+ let {onSubmit, qdata} = this.props;
+ return onSubmit({qdata});
+ }
+}
+export default SoftwareProductComponentsImageListView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageNavigationReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageNavigationReducer.js
new file mode 100644
index 0000000000..20d1f5dd18
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageNavigationReducer.js
@@ -0,0 +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 {actionTypes} from './SoftwareProductComponentsImageConstants.js';
+
+export default (state = {}, action) => {
+ switch (action.type) {
+
+ case actionTypes.IMAGES_LIST_UPDATE:
+ if (action.componentId) {
+ return {
+ ...state,
+ [action.componentId] : (action.response && action.response.length > 0)
+ };
+ }
+ return state;
+ default:
+ return state;
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.jsx
new file mode 100644
index 0000000000..ca58b697a2
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/FileDetails.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 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';
+import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
+
+import Format from './Format.jsx';
+import Version from './Version.jsx';
+
+const FileDetails = ({editingMode, fileName, onDataChanged, isManual, dataMap, onQDataChanged, genericFieldInfo, qgenericFieldInfo}) => {
+ let fileNameCols = (editingMode) ? 3 : 4;
+ return(
+ <GridSection>
+ <GridItem colSpan={fileNameCols}>
+ <Input
+ disabled={!isManual}
+ onChange={fileName => onDataChanged({fileName}, forms.IMAGE_EDIT_FORM)}
+ label={i18n('Image Name')}
+ data-test-id='image-filename'
+ value={fileName}
+ isValid={genericFieldInfo.fileName.isValid}
+ errorText={genericFieldInfo.fileName.errorText}
+ isRequired={true}
+ type='text'
+ className='image-filename'/>
+ </GridItem>
+ {editingMode && <Version isManual={isManual} dataMap={dataMap} qgenericFieldInfo={qgenericFieldInfo} onQDataChanged={onQDataChanged}/>}
+ {editingMode && <Format isManual={isManual} qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged}/>}
+ </GridSection>
+ );
+};
+export default FileDetails;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx
new file mode 100644
index 0000000000..1f71c6b277
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Format.jsx
@@ -0,0 +1,47 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 GridItem from 'nfvo-components/grid/GridItem.jsx';
+
+
+const Format = ({isManual, dataMap, qgenericFieldInfo, onQDataChanged}) => {
+ return(
+ <GridItem colSpan={2}>
+ <Input
+ disabled={!isManual}
+ data-test-id='image-format'
+ type='select'
+ label={i18n('Format')}
+ className='input-options-select'
+ groupClassName='bootstrap-input-options'
+ isValid={qgenericFieldInfo['format'].isValid}
+ errorText={qgenericFieldInfo['format'].errorText}
+ value={dataMap['format']}
+ onChange={(e) => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onQDataChanged({'format' : val});}
+ }>
+ <option key='placeholder' value=''>{i18n('Select...')}</option>
+ {qgenericFieldInfo['format'].enum.map(hv => <option value={hv.enum} key={hv.enum}>{hv.title}</option>)}
+ </Input>
+ </GridItem>
+ );
+};
+export default Format;
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.jsx
new file mode 100644
index 0000000000..24e54bbbcb
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/ImageDetails.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 ImageDetails = ({dataMap, qgenericFieldInfo, onQDataChanged}) => {
+ return(
+ <GridSection title={i18n('Image Details')}>
+ <GridItem colSpan={2}>
+ <Input
+ data-test-id='image-md5'
+ className='image-md5'
+ type='text'
+ label={i18n('md5')}
+ onChange={(md5) => onQDataChanged({'md5' : md5})}
+ isValid={qgenericFieldInfo['md5'].isValid}
+ errorText={qgenericFieldInfo['md5'].errorText}
+ value={dataMap['md5']}/>
+ </GridItem>
+ </GridSection>
+ );
+};
+export default ImageDetails;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.jsx
new file mode 100644
index 0000000000..3cac9a51b8
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/imagesEditorComponents/Version.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 GridItem from 'nfvo-components/grid/GridItem.jsx';
+
+
+const Version = ({isManual, dataMap, qgenericFieldInfo, onQDataChanged}) => {
+ return(
+ <GridItem colSpan={1}>
+ <Input
+ disabled={!isManual}
+ data-test-id='image-version'
+ type='text'
+ className='image-version'
+ label={i18n('Version')}
+ onChange={(version) => onQDataChanged({'version' : version})}
+ isValid={qgenericFieldInfo['version'].isValid}
+ errorText={qgenericFieldInfo['version'].errorText}
+ value={dataMap['version']}/>
+ </GridItem>
+ );
+};
+export default Version;
+
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/loadBalancing/SoftwareProductComponentLoadBalancingRefView.jsx
index dc86771400..9ae9e359b0 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
@@ -14,7 +14,7 @@
* permissions and limitations under the License.
*/
import React from 'react';
-import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
+import SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
import Form from 'nfvo-components/input/validation/Form.jsx';
@@ -56,7 +56,7 @@ const TextAreaItem = ({item, toggle, expanded, genericFieldInfo, dataMap, onQDat
<div className={expanded ? 'title' : 'title add-padding'}
data-test-id={`btn-${item.key}`}
onClick={() => toggle(item.key)}>
- <SVGIcon name={expanded ? 'chevron-up' : 'chevron-down'}/>
+ <SVGIcon name={expanded ? 'chevronUp' : 'chevronDown'}/>
<span className='title-text'>{i18n(item.description)}</span>
{item.added && <div className='new-line'>{i18n(item.added)}</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 293e252dca..730beba545 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
@@ -25,20 +25,19 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data:currentVSP = {}}, softwareProductComponents: {monitoring}} = softwareProduct;
- let {trapFilename, pollFilename} = monitoring;
+ let filenames = monitoring;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentVSP);
return {
isReadOnlyMode,
- trapFilename,
- pollFilename
+ filenames
};
};
const mapActionsToProps = (dispatch, {softwareProductId, version, componentId}) => {
return {
onDropMibFileToUpload: (formData, type) =>
- SoftwareProductComponentsMonitoringAction.uploadSnmpFile(dispatch, {
+ SoftwareProductComponentsMonitoringAction.uploadFile(dispatch, {
softwareProductId,
version,
componentId,
@@ -46,7 +45,7 @@ const mapActionsToProps = (dispatch, {softwareProductId, version, componentId})
type
}),
- onDeleteSnmpFile: type => SoftwareProductComponentsMonitoringAction.deleteSnmpFile(dispatch, {
+ onDeleteFile: type => SoftwareProductComponentsMonitoringAction.deleteFile(dispatch, {
softwareProductId,
version,
componentId,
@@ -57,7 +56,7 @@ const mapActionsToProps = (dispatch, {softwareProductId, version, componentId})
type: modalActionTypes.GLOBAL_MODAL_ERROR,
data: {
title: i18n('Upload Failed'),
- msg: i18n('Expected "zip" file. Please check the provided file type.')
+ 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 64403faa78..3db708bc92 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js
@@ -16,23 +16,13 @@
import i18n from 'nfvo-utils/i18n/i18n.js';
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
-import SoftwareProductComponentsMonitoringConstants, {actionTypes} from './SoftwareProductComponentsMonitoringConstants.js';
+import {actionTypes} from './SoftwareProductComponentsMonitoringConstants.js';
import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
-const UPLOAD = true;
-
function baseUrl(vspId, version, componentId) {
const versionId = version.id;
const restPrefix = Configuration.get('restPrefix');
- return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/components/${componentId}/monitors`;
-}
-
-function snmpTrapUrl(vspId, version, componentId, isUpload) {
- return `${baseUrl(vspId, version, componentId)}/snmp-trap${isUpload ? '/upload' : ''}`;
-}
-
-function snmpPollUrl(vspId, version, componentId, isUpload) {
- return `${baseUrl(vspId, version, componentId)}/snmp${isUpload ? '/upload' : ''}`;
+ return `${restPrefix}/v1.0/vendor-software-products/${vspId}/versions/${versionId}/components/${componentId}/uploads`;
}
let onInvalidFileSizeUpload = (dispatch) => dispatch({
@@ -43,62 +33,42 @@ let onInvalidFileSizeUpload = (dispatch) => 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 uploadFile = (dispatch, {softwareProductId, version, componentId, formData, type}) => {
+ return RestAPIUtil.post(`${baseUrl(softwareProductId, version, componentId)}/types/${type}`, formData).then(()=> dispatch({
+ type: actionTypes.MONITOR_UPLOADED, data: {filename: formData.get('upload').name, type : type}
}));
};
-let 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 deleteFile = (dispatch, {softwareProductId, version, componentId, type}) => {
+ return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/types/${type}`).then(()=> dispatch({
+ type: actionTypes.MONITOR_DELETED,
+ data : { type: type}
}));
};
-let deleteSnmpTrapFile = (dispatch, {softwareProductId, version, componentId}) => {
- RestAPIUtil.destroy(snmpTrapUrl(softwareProductId, version, componentId, !UPLOAD)).then(()=> dispatch({
- type: actionTypes.SNMP_TRAP_DELETED
- }));
-};
-
-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, version, componentId}){
- RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/snmp`).then(response =>
+ return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`).then(response =>
dispatch({
- type: actionTypes.SNMP_FILES_DATA_CHANGE,
- data: {trapFilename: response.snmpTrap, pollFilename: response.snmpPoll}
+ type: actionTypes.MONITOR_FILES_DATA_CHANGE,
+ data: response
})
);
},
- uploadSnmpFile(dispatch, {softwareProductId, version, componentId, formData, type}){
+ uploadFile(dispatch, {softwareProductId, version, componentId, formData, type}){
if (formData.get('upload').size) {
- if (type === SoftwareProductComponentsMonitoringConstants.SNMP_TRAP) {
- uploadSnmpTrapFile(dispatch, {softwareProductId, version, componentId, formData});
- }
- else {
- uploadSnmpPollFile(dispatch, {softwareProductId, version, componentId, formData});
- }
+ return uploadFile(dispatch, {softwareProductId, version, componentId, formData, type});
}
else {
onInvalidFileSizeUpload(dispatch);
}
},
- deleteSnmpFile(dispatch, {softwareProductId, version, componentId, type}){
- if (type === SoftwareProductComponentsMonitoringConstants.SNMP_TRAP) {
- deleteSnmpTrapFile(dispatch, {softwareProductId, version, componentId});
- }
- else {
- deleteSnmpPollFile(dispatch, {softwareProductId, version, componentId});
- }
+ deleteFile(dispatch, {softwareProductId, version, componentId, type}){
+ return deleteFile(dispatch, {softwareProductId, version, componentId, type});
}
};
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 d908d36aaa..bf2cbd2a3f 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
@@ -14,20 +14,31 @@
* 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({
+ MONITOR_FILES_DATA_CHANGE: null,
+ MONITOR_UPLOADED: null,
+ MONITOR_DELETED: null
+});
- SNMP_FILES_DATA_CHANGE: null,
+export const fileTypes = {
+ SNMP_TRAP: 'SNMP_TRAP',
+ SNMP_POLL: 'SNMP_POLL',
+ VES_EVENT: 'VES_EVENTS'
+};
- SNMP_TRAP_UPLOADED: null,
- SNMP_POLL_UPLOADED: null,
+export const type2Name = {
+ SNMP_TRAP: 'snmpTrap',
+ SNMP_POLL: 'snmpPoll',
+ VES_EVENTS: 'vesEvent'
+};
- SNMP_TRAP_DELETED: null,
- SNMP_POLL_DELETED: null
-});
-export default keyMirror({
- SNMP_TRAP: null,
- SNMP_POLL: null
-});
+export const type2Title = {
+ SNMP_TRAP : i18n('SNMP Trap'),
+ SNMP_POLL : i18n('SNMP Poll'),
+ VES_EVENTS: i18n('VES')
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js
index 54513b9634..f5cfe6f06d 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringReducer.js
@@ -13,35 +13,21 @@
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-import {actionTypes} from './SoftwareProductComponentsMonitoringConstants.js';
+import {actionTypes, type2Name} from './SoftwareProductComponentsMonitoringConstants.js';
export default (state = {}, action) => {
switch (action.type) {
- case actionTypes.SNMP_FILES_DATA_CHANGE:
+ case actionTypes.MONITOR_FILES_DATA_CHANGE:
+ return action.data;
+ case actionTypes.MONITOR_UPLOADED:
return {
...state,
- trapFilename: action.data.trapFilename,
- pollFilename: action.data.pollFilename
+ [type2Name[action.data.type]]: action.data.filename
};
- case actionTypes.SNMP_TRAP_UPLOADED:
+ case actionTypes.MONITOR_DELETED:
return {
...state,
- trapFilename: action.data.filename
- };
- case actionTypes.SNMP_POLL_UPLOADED:
- return {
- ...state,
- pollFilename: action.data.filename
- };
- case actionTypes.SNMP_TRAP_DELETED:
- return {
- ...state,
- trapFilename: undefined
- };
- case actionTypes.SNMP_POLL_DELETED:
- return {
- ...state,
- pollFilename: undefined
+ [type2Name[action.data.type]]: undefined
};
default:
return state;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx
index 329cc70353..2ad48ec84b 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
@@ -19,14 +19,15 @@ import ButtonGroup from 'react-bootstrap/lib/ButtonGroup.js';
import ButtonToolbar from 'react-bootstrap/lib/ButtonToolbar.js';
import Button from 'react-bootstrap/lib/Button.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import SoftwareProductComponentsMonitoringConstants from './SoftwareProductComponentsMonitoringConstants.js';
+import {fileTypes, type2Title, type2Name} from './SoftwareProductComponentsMonitoringConstants.js';
+
+
class SoftwareProductComponentsMonitoringView extends Component {
static propTypes = {
isReadOnlyMode: PropTypes.bool,
- trapFilename: PropTypes.string,
- pollFilename: PropTypes.string,
+ filenames: PropTypes.object,
softwareProductId: PropTypes.string,
onDropMibFileToUpload: PropTypes.func,
@@ -38,26 +39,24 @@ class SoftwareProductComponentsMonitoringView extends Component {
};
+
+
render() {
return (
<div className='vsp-component-monitoring'>
- {this.renderDropzoneWithType(SoftwareProductComponentsMonitoringConstants.SNMP_TRAP)}
- {this.renderDropzoneWithType(SoftwareProductComponentsMonitoringConstants.SNMP_POLL)}
+ {this.renderDropzoneWithType(fileTypes.VES_EVENT)}
+ {this.renderDropzoneWithType(fileTypes.SNMP_TRAP)}
+ {this.renderDropzoneWithType(fileTypes.SNMP_POLL)}
</div>
);
}
renderDropzoneWithType(type) {
- let {isReadOnlyMode, trapFilename, pollFilename} = this.props;
- let fileName;
- if (type === SoftwareProductComponentsMonitoringConstants.SNMP_TRAP) {
- fileName = trapFilename;
- }
- else {
- fileName = pollFilename;
- }
+ let {isReadOnlyMode, filenames} = this.props;
+ let fileByType = type2Name[type];
+ let fileName = (filenames) ? filenames[fileByType] : undefined;
let refAndName = `fileInput${type.toString()}`;
- let typeDisplayName = this.getFileTypeDisplayName(type);
+ let typeDisplayName = type2Title[type];
return (
<Dropzone
className={`snmp-dropzone ${this.state.dragging ? 'active-dragging' : ''}`}
@@ -97,7 +96,7 @@ class SoftwareProductComponentsMonitoringView extends Component {
<ButtonToolbar>
<ButtonGroup>
<Button disabled>{filename}</Button>
- <Button className='delete-button' onClick={()=>this.props.onDeleteSnmpFile(type)}>X</Button>
+ <Button className='delete-button' onClick={()=>this.props.onDeleteFile(type)}>X</Button>
</ButtonGroup>
</ButtonToolbar>
);
@@ -126,11 +125,6 @@ class SoftwareProductComponentsMonitoringView extends Component {
this.props.onFileUploadError();
}
}
-
- getFileTypeDisplayName(type) {
- return type === SoftwareProductComponentsMonitoringConstants.SNMP_TRAP ? 'SNMP Trap' : 'SNMP Poll';
- }
-
}
export default SoftwareProductComponentsMonitoringView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.js
new file mode 100644
index 0000000000..865367a734
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreation.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 NICCreationActionHelper from './NICCreationActionHelper.js';
+import NICCreationView from './NICCreationView.jsx';
+import SoftwareProductComponentsNetworkActionHelper from '../SoftwareProductComponentsNetworkActionHelper.js';
+import {networkTypes, NIC_CREATION_FORM_NAME} from '../SoftwareProductComponentsNetworkConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+
+export const mapStateToProps = ({softwareProduct}) => {
+ let {softwareProductEditor: {data:currentSoftwareProduct = {}}, softwareProductComponents} = softwareProduct;
+ let {network: {nicCreation = {}}} = softwareProductComponents;
+ let {data, genericFieldInfo, formReady} = nicCreation;
+ data = {...data, networkType: networkTypes.EXTERNAL};
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
+ return {
+ currentSoftwareProduct,
+ data,
+ genericFieldInfo,
+ isFormValid,
+ formReady
+ };
+};
+
+const mapActionsToProps = (dispatch) => {
+ return {
+ onDataChanged: deltaData => ValidationHelper.dataChanged(dispatch, {deltaData, formName: NIC_CREATION_FORM_NAME}),
+ onCancel: () => NICCreationActionHelper.close(dispatch),
+ onSubmit: ({nic, softwareProductId, componentId, version}) => {
+ NICCreationActionHelper.close(dispatch);
+ SoftwareProductComponentsNetworkActionHelper.createNIC(dispatch, {nic, softwareProductId, componentId, version});
+ },
+ onValidateForm: () => ValidationHelper.validateForm(dispatch, NIC_CREATION_FORM_NAME)
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(NICCreationView);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js
new file mode 100644
index 0000000000..ad28c86b81
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationActionHelper.js
@@ -0,0 +1,47 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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 '../SoftwareProductComponentsNetworkConstants';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
+
+export default {
+
+ open(dispatch, {softwareProductId, componentId, modalClassName}) {
+ dispatch({
+ type: actionTypes.NICCreation.OPEN
+ });
+
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_SHOW,
+ data: {
+ modalComponentName: modalContentMapper.NIC_CREATION,
+ title: i18n('Create NEW NIC'),
+ modalClassName,
+ modalComponentProps: {softwareProductId, componentId}
+ }
+ });
+ },
+
+ close(dispatch){
+ dispatch({
+ type: modalActionTypes.GLOBAL_MODAL_CLOSE
+ });
+ dispatch({
+ type: actionTypes.NICCreation.CLEAR_DATA
+ });
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js
new file mode 100644
index 0000000000..c7e2495b3d
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationReducer.js
@@ -0,0 +1,49 @@
+/*!
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this 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, NIC_CREATION_FORM_NAME} from '../SoftwareProductComponentsNetworkConstants.js';
+
+export default (state = {}, action) => {
+ switch (action.type) {
+ case actionTypes.NICCreation.OPEN:
+ return {
+ ...state,
+ data: {},
+ formName: NIC_CREATION_FORM_NAME,
+ formReady: null,
+ genericFieldInfo: {
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 1000}]
+ },
+ 'name' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data : true}]
+ },
+ 'networkDescription' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 50}]
+ }
+ }
+ };
+ case actionTypes.NICCreation.CLEAR_DATA:
+ return {};
+ default:
+ return state;
+ }
+};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.jsx
new file mode 100644
index 0000000000..3cb731a421
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/NICCreation/NICCreationView.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 from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+
+const NICPropType = React.PropTypes.shape({
+ id: React.PropTypes.string,
+ name: React.PropTypes.string,
+ description: React.PropTypes.string,
+ networkId: React.PropTypes.string
+});
+
+class NICCreationView extends React.Component {
+
+ static propTypes = {
+ data: NICPropType,
+ onDataChanged: React.PropTypes.func.isRequired,
+ onSubmit: React.PropTypes.func.isRequired,
+ onCancel: React.PropTypes.func.isRequired
+ };
+
+ render() {
+ let {data = {}, onDataChanged, genericFieldInfo, isFormValid, onValidateForm, formReady} = this.props;
+ let {name, description, networkDescription} = data;
+ return (
+ <div>
+ {genericFieldInfo && <Form
+ ref={(form) => this.form = form}
+ hasButtons={true}
+ onSubmit={ () => this.submit() }
+ submitButtonText={data.id ? i18n('Save') : i18n('Create')}
+ onReset={ () => this.props.onCancel() }
+ labledButtons={true}
+ isValid={isFormValid}
+ onValidateForm={() => onValidateForm()}
+ formReady={formReady} >
+ <GridSection>
+ <GridItem colSpan={4}>
+ <Input
+ value={name}
+ label={i18n('Name')}
+ data-test-id='nic-name'
+ onChange={name => onDataChanged({name})}
+ isRequired={true}
+ type='text'
+ isValid={genericFieldInfo['name'].isValid}
+ errorText={genericFieldInfo['name'].errorText}
+ className='field-section'/>
+ <Input
+ value={description}
+ label={i18n('Description')}
+ data-test-id='nic-description'
+ onChange={description => onDataChanged({description})}
+ isValid={genericFieldInfo['description'].isValid}
+ errorText={genericFieldInfo['description'].errorText}
+ type='textarea'
+ className='field-section'/>
+ </GridItem>
+ </GridSection>
+ <GridSection title={i18n('Network')}>
+ <GridItem colSpan={2}>
+ <div className='form-group'>
+ <label className='control-label'>{i18n('Network Type')}</label>
+ <div className='network-type-radio'>
+ <Input
+ label={i18n('Internal')}
+ disabled
+ checked={false}
+ data-test-id='nic-internal'
+ className='network-radio disabled'
+ type='radio'/>
+ <Input
+ label={i18n('External')}
+ disabled
+ checked={true}
+ data-test-id='nic-external'
+ className='network-radio disabled'
+ type='radio'/>
+ </div>
+ </div>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ value={networkDescription}
+ label={i18n('Network Description')}
+ data-test-id='nic-network-description'
+ onChange={networkDescription => onDataChanged({networkDescription})}
+ isValid={genericFieldInfo['networkDescription'].isValid}
+ errorText={genericFieldInfo['networkDescription'].errorText}
+ type='text'
+ className='field-section'/>
+ </GridItem>
+ </GridSection>
+ </Form>}
+ </div>
+ );
+ }
+
+
+ submit() {
+ const {data: nic, softwareProductId, componentId, currentSoftwareProduct} = this.props;
+ this.props.onSubmit({nic, softwareProductId, componentId, version: currentSoftwareProduct.version});
+ }
+}
+
+export default NICCreationView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditor.js
index 7cf1f0189e..b47c7e0f99 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
@@ -20,6 +20,7 @@ import VersionControllerUtils from 'nfvo-components/panel/versionController/Vers
import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsConstants.js';
import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
+import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
export const mapStateToProps = ({softwareProduct}) => {
@@ -28,6 +29,7 @@ export const mapStateToProps = ({softwareProduct}) => {
let {network: {nicEditor = {}}} = softwareProductComponents;
let {data, qdata, genericFieldInfo, qgenericFieldInfo, dataMap, formReady} = nicEditor;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
+ let {onboardingMethod} = currentSoftwareProduct;
let protocols = [];
if(qdata && qdata.protocols && qdata.protocols.protocols && qdata.protocols.protocols.length){
protocols = qdata.protocols.protocols;
@@ -47,7 +49,8 @@ export const mapStateToProps = ({softwareProduct}) => {
genericFieldInfo,
qgenericFieldInfo,
isReadOnlyMode,
- protocols
+ protocols,
+ isManual: onboardingMethod === onboardingMethodTypes.MANUAL
};
};
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 b3c9fe5d98..dd37135d77 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
@@ -18,7 +18,7 @@ import {forms} from 'sdc-app/onboarding/softwareProduct/components/SoftwareProdu
export default (state = {}, action) => {
switch (action.type) {
- case actionTypes.NICEditor.OPEN:
+ case actionTypes.NICEditor.FILL_DATA:
return {
...state,
data: action.nic,
@@ -31,12 +31,17 @@ export default (state = {}, action) => {
'name' : {
isValid: true,
errorText: '',
+ validations: [{type: 'required', data : true}]
+ },
+ 'networkDescription' : {
+ isValid: true,
+ errorText: '',
validations: []
}
},
formName: forms.NIC_EDIT_FORM
};
- case actionTypes.NICEditor.CLOSE:
+ case actionTypes.NICEditor.CLEAR_DATA:
return {};
default:
return state;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNICEditorView.jsx
index aad06c82f0..8a4c55a411 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
@@ -28,8 +28,9 @@ import NameAndPurpose from './nicEditorComponents/NameAndPurpose.jsx';
class SoftwareProductComponentsNetworkEditorView extends React.Component {
render() {
- let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, qgenericFieldInfo, dataMap, onDataChanged, protocols, onQDataChanged} = this.props;
- let {name, description, networkName} = data;
+ let {onCancel, onValidateForm, isReadOnlyMode, isFormValid, formReady, data = {}, qgenericFieldInfo,
+ dataMap, onDataChanged, protocols, onQDataChanged, isManual, genericFieldInfo} = this.props;
+ let {name, description, networkName, networkType, networkDescription} = data;
let netWorkValues = [{
enum: networkName,
title: networkName
@@ -48,10 +49,10 @@ class SoftwareProductComponentsNetworkEditorView extends React.Component {
onValidateForm={() => onValidateForm() }
className='vsp-components-network-editor'>
<div className='editor-data'>
- <NameAndPurpose name={name} description={description} onDataChanged={onDataChanged} isReadOnlyMode={isReadOnlyMode}/>
+ <NameAndPurpose isManual={isManual} name={name} description={description} onDataChanged={onDataChanged} isReadOnlyMode={isReadOnlyMode} genericFieldInfo={genericFieldInfo} />
<Protocols protocols={protocols} qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
<IpConfig dataMap={dataMap} onQDataChanged={onQDataChanged} />
- <Network networkValues={netWorkValues} />
+ <Network networkDescription={networkDescription} onDataChanged={onDataChanged} networkValues={netWorkValues} isReadOnlyMode={isReadOnlyMode} networkType={networkType} />
<Sizing qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
<InFlowTraffic qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
<OutFlowTraffic qgenericFieldInfo={qgenericFieldInfo} dataMap={dataMap} onQDataChanged={onQDataChanged} />
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 bc061469b1..a3cfe65128 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
@@ -15,8 +15,11 @@
*/
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
import {actionTypes} from './SoftwareProductComponentsNetworkConstants.js';
+import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js';
+import {modalContentMapper as modalPagesMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
import {NIC_QUESTIONNAIRE} from 'sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkConstants.js';
@@ -26,6 +29,14 @@ function baseUrl(softwareProductId, version, componentId) {
return `${restPrefix}/v1.0/vendor-software-products/${softwareProductId}/versions/${versionId}/components/${componentId}/nics`;
}
+function createNIC({nic, vspId, componentId, version}) {
+ return RestAPIUtil.post(baseUrl(vspId, version, componentId), {
+ name: nic.name,
+ description: nic.description,
+ networkDescription: nic.networkDescription,
+ networkType: nic.networkType
+ });
+}
function fetchNICQuestionnaire({softwareProductId, version, componentId, nicId}) {
return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}/${nicId}/questionnaire`);
@@ -39,11 +50,16 @@ function fetchNICsList({softwareProductId, version, componentId}) {
return RestAPIUtil.fetch(`${baseUrl(softwareProductId, version, componentId)}`);
}
-function saveNIC({softwareProductId, version, componentId, nic: {id, name, description, networkId}}) {
+function deleteNIC({softwareProductId, componentId, nicId, version}) {
+ return RestAPIUtil.destroy(`${baseUrl(softwareProductId, version, componentId)}/${nicId}`);
+}
+function saveNIC({softwareProductId, version, componentId, nic: {id, name, description, networkId, networkType, networkDescription}}) {
return RestAPIUtil.put(`${baseUrl(softwareProductId, version, componentId)}/${id}`,{
name,
description,
- networkId
+ networkId,
+ networkDescription,
+ networkType
});
}
@@ -62,23 +78,45 @@ const SoftwareProductComponentNetworkActionHelper = {
});
},
- openNICEditor(dispatch, {nic = {}, data = {}}) {
+ openNICEditor(dispatch, {nic = {}, data = {}, softwareProductId, componentId, isReadOnlyMode, modalClassName}) {
dispatch({
- type: actionTypes.NICEditor.OPEN,
+ type: actionTypes.NICEditor.FILL_DATA,
nic: {...data, id: nic.id}
});
+ dispatch({
+ type: GlobalModalActions.GLOBAL_MODAL_SHOW,
+ data: {
+ modalClassName,
+ modalComponentProps: {softwareProductId, componentId, isReadOnlyMode},
+ modalComponentName: modalPagesMapper.NIC_EDITOR,
+ title: i18n('Edit NIC')
+ }
+ });
},
closeNICEditor(dispatch) {
dispatch({
- type: actionTypes.NICEditor.CLOSE
+ type: GlobalModalActions.GLOBAL_MODAL_CLOSE
+ });
+ dispatch({
+ type: actionTypes.NICEditor.CLEAR_DATA
});
},
+ createNIC(dispatch, {nic, softwareProductId, componentId, version}){
+ return createNIC({nic, vspId: softwareProductId, componentId, version}).then(() => {
+ return SoftwareProductComponentNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version});
+ });
+ },
loadNICData({softwareProductId, version, componentId, nicId}) {
return fetchNIC({softwareProductId, version, componentId, nicId});
},
+ deleteNIC(dispatch, {softwareProductId, componentId, nicId, version}) {
+ return deleteNIC({softwareProductId, componentId, nicId, version}).then(() => {
+ return SoftwareProductComponentNetworkActionHelper.fetchNICsList(dispatch, {softwareProductId, componentId, version});
+ });
+ },
loadNICQuestionnaire(dispatch, {softwareProductId, version, componentId, nicId}) {
return fetchNICQuestionnaire({softwareProductId, version, componentId, nicId}).then((response) => {
ValidationHelper.qDataLoaded(dispatch, {qName: NIC_QUESTIONNAIRE ,response: {
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 39c55d876c..8ef8fe8c18 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
@@ -20,9 +20,19 @@ export const actionTypes = keyMirror({
NIC_LIST_UPDATE: null,
NICEditor: {
+ FILL_DATA: null,
+ CLEAR_DATA: null,
+ },
+ NICCreation: {
OPEN: null,
- CLOSE: null
- }
+ CLEAR_DATA: null,
+ DATA_CHANGED: null
+ },
});
+export const networkTypes = {
+ EXTERNAL: 'External',
+ INTERNAL: 'Internal'
+};
export const NIC_QUESTIONNAIRE = 'nic';
+export const NIC_CREATION_FORM_NAME = 'nicCreation';
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkList.js
index c2bd8ce479..0fa877e90f 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
@@ -14,6 +14,7 @@
* 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 SoftwareProductComponentsActionHelper from 'sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js';
@@ -21,16 +22,17 @@ import SoftwareProductComponentsNetworkListView from './SoftwareProductComponent
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';
+import {actionTypes as GlobalModalActions} from 'nfvo-components/modal/GlobalModalConstants.js';
+import NICCreationActionHelper from './NICCreation/NICCreationActionHelper.js';
+import {onboardingMethod as onboardingMethodTypes} from '../../SoftwareProductConstants.js';
export const mapStateToProps = ({softwareProduct}) => {
let {softwareProductEditor: {data: currentSoftwareProduct = {}, isValidityData = true}, softwareProductComponents} = softwareProduct;
- let {network: {nicEditor = {}, nicList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
- let {data} = nicEditor;
+ let {network: {nicList = []}, componentEditor: {data: componentData, qdata, dataMap, qgenericFieldInfo}} = softwareProductComponents;
let isReadOnlyMode = VersionControllerUtils.isReadOnly(currentSoftwareProduct);
- let {version} = currentSoftwareProduct;
- let isModalInEditMode = true;
+ let {version, onboardingMethod} = currentSoftwareProduct;
return {
version,
@@ -40,9 +42,8 @@ export const mapStateToProps = ({softwareProduct}) => {
qgenericFieldInfo,
isValidityData,
nicList,
- isDisplayModal: Boolean(data),
- isModalInEditMode,
- isReadOnlyMode
+ isReadOnlyMode,
+ isManual: onboardingMethod === onboardingMethodTypes.MANUAL
};
};
@@ -51,7 +52,16 @@ const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
return {
onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData,
qName: COMPONENTS_QUESTIONNAIRE}),
- onEditNicClick: (nic, version) => {
+ onAddNic: () => NICCreationActionHelper.open(dispatch, {softwareProductId, componentId, modalClassName: 'network-nic-modal-create'}),
+ onDeleteNic: (nic, version) => dispatch({
+ type: GlobalModalActions.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n(`Are you sure you want to delete "${nic.name}"?`),
+ onConfirmed: () => SoftwareProductComponentsNetworkActionHelper.deleteNIC(dispatch, {softwareProductId,
+ componentId, nicId: nic.id, version})
+ }
+ }),
+ onEditNicClick: (nic, version, isReadOnlyMode) => {
Promise.all([
SoftwareProductComponentsNetworkActionHelper.loadNICData({
softwareProductId,
@@ -66,7 +76,8 @@ const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
nicId: nic.id
})
]).then(
- ([{data}]) => SoftwareProductComponentsNetworkActionHelper.openNICEditor(dispatch, {nic, data})
+ ([{data}]) => SoftwareProductComponentsNetworkActionHelper.openNICEditor(dispatch, {nic, data,
+ isReadOnlyMode, softwareProductId, componentId, modalClassName: 'network-nic-modal-edit'})
);
},
onSubmit: ({qdata, version}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
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 f715016ba3..5a159b4a87 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
@@ -21,9 +21,7 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import ListEditorItemViewField from 'nfvo-components/listEditor/ListEditorItemViewField.jsx';
import Input from'nfvo-components/input/validation/Input.jsx';
-import Modal from 'nfvo-components/modal/Modal.jsx';
-import SoftwareProductComponentsNICEditor from './SoftwareProductComponentsNICEditor.js';
class SoftwareProductComponentsNetworkView extends React.Component {
@@ -32,7 +30,7 @@ class SoftwareProductComponentsNetworkView extends React.Component {
};
render() {
- let {dataMap, qgenericFieldInfo, onQDataChanged, isModalInEditMode, isDisplayModal, softwareProductId, componentId, isReadOnlyMode} = this.props;
+ let {dataMap, qgenericFieldInfo, onQDataChanged, isReadOnlyMode} = this.props;
return(
<div className='vsp-components-network'>
@@ -85,26 +83,14 @@ class SoftwareProductComponentsNetworkView extends React.Component {
</div>
{this.renderNicList()}
</div>
- <Modal show={isDisplayModal} bsSize='large' animation={true} className='network-nic-modal'>
- <Modal.Header>
- <Modal.Title>{isModalInEditMode ? i18n('Edit NIC') : i18n('Create New NIC')}</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- {
- <SoftwareProductComponentsNICEditor
- softwareProductId={softwareProductId}
- componentId={componentId}
- isReadOnlyMode={isReadOnlyMode}/>
- }
- </Modal.Body>
- </Modal>
+
</div>
);
}
renderNicList() {
const {localFilter} = this.state;
- let {isReadOnlyMode} = this.props;
+ let {isReadOnlyMode, onAddNic, isManual} = this.props;
return (
<ListEditorView
title={i18n('Interfaces')}
@@ -112,6 +98,8 @@ class SoftwareProductComponentsNetworkView extends React.Component {
placeholder={i18n('Filter NICs by Name')}
isReadOnlyMode={isReadOnlyMode}
onFilter={value => this.setState({localFilter: value})}
+ onAdd={isManual ? onAddNic : null}
+ plusButtonTitle={i18n('Add NIC')}
twoColumns>
{this.filterList().map(nic => this.renderNicListItem(nic, isReadOnlyMode))}
</ListEditorView>
@@ -120,25 +108,26 @@ class SoftwareProductComponentsNetworkView extends React.Component {
renderNicListItem(nic, isReadOnlyMode) {
let {id, name, description, networkName = ''} = nic;
- let {onEditNicClick, version} = this.props;
+ let {onEditNicClick, version, isManual, onDeleteNic} = this.props;
return (
<ListEditorItemView
key={id}
isReadOnlyMode={isReadOnlyMode}
- onSelect={() => onEditNicClick(nic, version)}>
+ onSelect={() => onEditNicClick(nic, version, isReadOnlyMode)}
+ onDelete={isManual ? () => onDeleteNic(nic, version) : null}>
<ListEditorItemViewField>
<div className='name'>{name}</div>
</ListEditorItemViewField>
<ListEditorItemViewField>
- <div className='details'>
- <div className='title'>{i18n('Purpose of NIC')}</div>
- <div className='description'>{description}</div>
+ <div className={isManual ? 'details-col' : 'details'}>
+ <div className={isManual ? 'manual-title' : 'title'}>{i18n('Purpose of NIC')}</div>
+ <div className={isManual ? 'description' : ''}>{description ? description : i18n('N/A')}</div>
</div>
- <div className='details'>
+ {!isManual && <div className='details'>
<div className='title'>{i18n('Network')}</div>
<div className='artifact-name'>{networkName}</div>
- </div>
+ </div>}
</ListEditorItemViewField>
</ListEditorItemView>
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx
index 3dc153d27f..bc692e753c 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/NameAndPurpose.jsx
@@ -19,7 +19,7 @@ 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}) => {
+const NameAndPurpose = ({onDataChanged, genericFieldInfo, isReadOnlyMode, name, description, isManual}) => {
return (
<GridSection>
@@ -28,7 +28,11 @@ const NameAndPurpose = ({onDataChanged, isReadOnlyMode, name, description}) => {
label={i18n('Name')}
value={name}
data-test-id='nic-name'
- disabled={true}
+ disabled={!isManual}
+ isRequired={true}
+ onChange={name => onDataChanged({name})}
+ isValid={genericFieldInfo['name'].isValid}
+ errorText={genericFieldInfo['name'].errorText}
type='text' />
</GridItem>
<GridItem colSpan={2}>
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx
index 43afdbed3a..8d9b79e67f 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/nicEditorComponents/Network.jsx
@@ -18,15 +18,17 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
import Input from 'nfvo-components/input/validation/Input.jsx';
import GridSection from 'nfvo-components/grid/GridSection.jsx';
import GridItem from 'nfvo-components/grid/GridItem.jsx';
+import { networkTypes } from '../SoftwareProductComponentsNetworkConstants.js';
-const Network = ({networkValues}) => {
+const Network = ({networkValues, networkType, networkDescription, onDataChanged, isReadOnlyMode}) => {
+ const isExternal = networkType === networkTypes.EXTERNAL;
return (
<GridSection title={i18n('Network')}>
<GridItem>
<Input
label={i18n('Internal')}
disabled
- checked={true}
+ checked={!isExternal}
data-test-id='nic-internal'
className='network-radio disabled'
type='radio'/>
@@ -35,12 +37,21 @@ const Network = ({networkValues}) => {
<Input
label={i18n('External')}
disabled
- checked={false}
+ checked={isExternal}
data-test-id='nic-external'
className='network-radio disabled'
type='radio'/>
</GridItem>
<GridItem colSpan={2}>
+ {isExternal ?
+ <Input
+ label={i18n('Network Description')}
+ value={networkDescription}
+ data-test-id='nic-network-description'
+ onChange={networkDescription => onDataChanged({networkDescription})}
+ disabled={isReadOnlyMode}
+ type='text'/>
+ :
<Input
label={i18n('Network')}
data-test-id='nic-network'
@@ -48,8 +59,8 @@ const Network = ({networkValues}) => {
className='input-options-select'
groupClassName='bootstrap-input-options'
disabled={true} >
- {networkValues.map(val => <option key={val.enum} value={val.enum}>{val.title}</option>)}
- </Input>
+ {networkValues.map(val => <option key={val.enum} value={val.enum}>{val.title}</option>)}
+ </Input>}
</GridItem>
</GridSection>
);
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 a8cb709194..826201162c 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
@@ -47,7 +47,7 @@ const mapActionsToProps = (dispatch, {componentId, softwareProductId}) => {
onDeleteProcessClick: (process, version) => dispatch({
type: modalActionTypes.GLOBAL_MODAL_WARNING,
data:{
- msg: i18n('Are you sure you want to delete "{name}"?', {name: process.name}),
+ msg: i18n(`Are you sure you want to delete "${process.name}"?`),
onConfirmed: ()=> SoftwareProductComponentProcessesActionHelper.deleteProcess(dispatch,
{process, softwareProductId, version, componentId})
}
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 650d6d5ebc..93d5ce886a 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
@@ -44,7 +44,7 @@ class SoftwareProductProcessesView extends React.Component {
return (
<div className='vsp-processes-page'>
<div className='software-product-view'>
- <div className='software-product-landing-view-right-side flex-column'>
+ <div className='software-product-landing-view-right-side vsp-components-processes-page flex-column'>
{this.renderEditor()}
{this.renderProcessList()}
</div>