diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx')
-rw-r--r-- | openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx | 253 |
1 files changed, 95 insertions, 158 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx index c52999ca46..66fb2f8356 100644 --- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsView.jsx @@ -1,182 +1,119 @@ -import React from 'react'; -import FontAwesome from 'react-fontawesome'; -import classNames from 'classnames'; -import Collapse from 'react-bootstrap/lib/Collapse.js'; - +/*! + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +import React, {Component, PropTypes} from 'react'; +import Tabs from 'react-bootstrap/lib/Tabs.js'; +import Tab from 'react-bootstrap/lib/Tab.js'; +import {tabsMapping} from './SoftwareProductAttachmentsConstants.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {nodeTypes, mouseActions} from './SoftwareProductAttachmentsConstants'; - -const typeToIcon = Object.freeze({ - heat: 'building-o', - volume: 'database', - network: 'cloud', - artifact: 'gear', - env: 'server', - other: 'cube' -}); +import Icon from 'nfvo-components/icon/Icon.jsx'; +import HeatValidation from './validation/HeatValidation.js'; -const leftPanelWidth = 250; - -class SoftwareProductAttachmentsView extends React.Component { +class HeatScreenView extends Component { static propTypes = { - attachmentsTree: React.PropTypes.object.isRequired + isValidationAvailable: PropTypes.bool, + goToOverview: PropTypes.bool }; + state = { - treeWidth: '400' + activeTab: tabsMapping.SETUP }; render() { - let {attachmentsTree, errorList} = this.props; - let {treeWidth} = this.state; + let {isValidationAvailable, isReadOnlyMode, heatDataExist, onDownload, softwareProductId, onProcessAndValidate, heatSetup, HeatSetupComponent, onGoToOverview, version, ...other} = this.props; return ( - <div className='software-product-attachments'> - <div className='software-product-attachments-tree' style={{'width' : treeWidth + 'px'}}> - <div className='tree-wrapper'> - { - attachmentsTree && attachmentsTree.children && attachmentsTree.children.map((child, ind) => this.renderNode(child, [ind])) - } - </div> + <div className='vsp-attachments-view'> + <div className='attachments-view-controllers'> + {(this.state.activeTab === tabsMapping.SETUP) && + <Icon + iconClassName={heatDataExist ? '' : 'disabled'} + className={heatDataExist ? '' : 'disabled'} + image='download' + label={i18n('Download HEAT')} + onClick={heatDataExist ? () => onDownload({heatCandidate: heatSetup, isReadOnlyMode, version}) : undefined} + data-test-id='download-heat'/>} + {(this.state.activeTab === tabsMapping.VALIDATION && softwareProductId) && + <Icon + iconClassName={this.props.goToOverview ? '' : 'disabled'} + className={`go-to-overview-icon ${this.props.goToOverview ? '' : 'disabled'}`} + labelClassName='go-to-overview-label' + onClick={this.props.goToOverview ? onGoToOverview : undefined} + image='go-to-overview' + label={i18n('Go to Overview')} + data-test-id='go-to-overview'/>} + <Icon + image='upload' + label={i18n('Upload New HEAT')} + className={isReadOnlyMode ? 'disabled' : ''} + iconClassName={isReadOnlyMode ? 'disabled' : ''} + onClick={evt => {this.refs.hiddenImportFileInput.click(evt);}} + data-test-id='upload-heat'/> + <input + ref='hiddenImportFileInput' + type='file' + name='fileInput' + accept='.zip' + onChange={evt => this.handleImport(evt)}/> </div> - <div onMouseDown={(e) => this.onChangeTreeWidth(e)} className='software-product-attachments-separator'/> - - <div className='software-product-attachments-error-list'> - {errorList.length ? this.renderErrorList(errorList) : <div className='no-errors'>{attachmentsTree.children ? - i18n('VALIDATION SUCCESS') : i18n('THERE IS NO HEAT DATA TO PRESENT') }</div>} - </div> - </div> - ); - } - - renderNode(node, path) { - let isFolder = node.children && node.children.length > 0; - let {onSelectNode} = this.props; - return ( - <div key={node.name} className='tree-block-inside'> - { - <div onDoubleClick={() => this.props.toggleExpanded(path)} className={this.getTreeRowClassName(node.name)}> - { - isFolder && - <div onClick={() => this.props.toggleExpanded(path)} className={classNames('tree-node-expander', {'tree-node-expander-collapsed': !node.expanded})}> - <FontAwesome name='caret-down'/> - </div> - } - { - - <span className='tree-node-icon'> - <FontAwesome name={typeToIcon[node.type]}/> - </span> - } - { - - <span onClick={() => onSelectNode(node.name)} className={this.getTreeTextClassName(node)}> - {node.name} - </span> - } - </div> - } - { - isFolder && - <Collapse in={node.expanded}> - <div className='tree-node-children'> - { - node.children.map((child, ind) => this.renderNode(child, [...path, ind])) - } - </div> - </Collapse> - } + <Tabs id='attachments-tabs' activeKey={this.state.activeTab} onSelect={key => this.handleTabPress(key)}> + <Tab eventKey={tabsMapping.SETUP} title='HEAT Setup'> + <HeatSetupComponent + heatDataExist={heatDataExist} + changeAttachmentsTab={tab => this.setState({activeTab: tab})} + onProcessAndValidate={onProcessAndValidate} + softwareProductId={softwareProductId} + isReadOnlyMode={isReadOnlyMode} + version={version}/> + </Tab> + <Tab eventKey={tabsMapping.VALIDATION} title='Heat Validation' disabled={!isValidationAvailable}> + <HeatValidation {...other}/> + </Tab> + </Tabs> </div> ); } - createErrorList(errorList, node, parent) { - if (node.errors) { - node.errors.forEach(error => errorList.push({ - error, - name: node.name, - parentName: parent.name, - type: node.type - })); + handleTabPress(key) { + let {heatSetup, heatSetupCache, onProcessAndValidate, isReadOnlyMode, version} = this.props; + switch (key) { + case tabsMapping.VALIDATION: + onProcessAndValidate({heatData: heatSetup, heatDataCache: heatSetupCache, isReadOnlyMode, version}).then( + () => this.setState({activeTab: tabsMapping.VALIDATION}) + ); + return; + case tabsMapping.SETUP: + this.setState({activeTab: tabsMapping.SETUP}); + return; } - if (node.children && node.children.length) { - node.children.map((child) => this.createErrorList(errorList, child, node)); - } - } - - renderErrorList(errors) { - let prevError = {}; - let {selectedNode} = this.props; - return errors.map(error => { - let isSameNodeError = error.name === prevError.name && error.parentName === prevError.parentName; - prevError = error; - - return ( - <div - key={error.name + error.errorMessage + error.parentName} - - onClick={() => this.selectNode(error.name)} - className={classNames('error-item', {'clicked': selectedNode === error.name, 'shifted': !isSameNodeError})}> - <span className={classNames('error-item-file-type', {'strong': !isSameNodeError})}> - { - error.hasParent ? - i18n('{type} {name} in {parentName}: ', { - type: nodeTypes[error.type], - name: error.name, - parentName: error.parentName - }) : - i18n('{type} {name}: ', { - type: nodeTypes[error.type], - name: error.name - }) - } - </span> - <span className={`error-item-file-type ${error.errorLevel}`}> {error.errorMessage} </span> - </div> - ); - }); } - selectNode(currentSelectedNode) { - let {onUnselectNode, onSelectNode, selectedNode} = this.props; - if (currentSelectedNode !== selectedNode) { - onSelectNode(currentSelectedNode); - }else{ - onUnselectNode(); - } - - } - - getTreeRowClassName(name) { - let {hoveredNode, selectedNode} = this.props; - return classNames({ - 'tree-node-row': true, - 'tree-node-selected': name === hoveredNode, - 'tree-node-clicked': name === selectedNode - }); + handleImport(evt) { + evt.preventDefault(); + let {version} = this.props; + let formData = new FormData(); + formData.append('upload', this.refs.hiddenImportFileInput.files[0]); + this.refs.hiddenImportFileInput.value = ''; + this.props.onUpload(formData, version); + this.setState({activeTab: tabsMapping.SETUP}); } - getTreeTextClassName(node) { - let {selectedNode} = this.props; - return classNames({ - 'tree-element-text': true, - 'error-status': node.errors, - 'error-status-selected': node.name === selectedNode - }); + save() { + return this.props.onSave(this.props.heatSetup, this.props.version); } - onChangeTreeWidth(e) { - if (e.button === mouseActions.MOUSE_BUTTON_CLICK) { - let onMouseMove = (e) => { - this.setState({treeWidth: e.clientX - leftPanelWidth}); - }; - let onMouseUp = () => { - document.removeEventListener('mousemove', onMouseMove); - document.removeEventListener('mouseup', onMouseUp); - }; - document.addEventListener('mousemove', onMouseMove); - document.addEventListener('mouseup', onMouseUp); - } - } } -export default SoftwareProductAttachmentsView; +export default HeatScreenView; |