diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx')
-rw-r--r-- | openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx b/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx new file mode 100644 index 0000000000..7e2dda8d47 --- /dev/null +++ b/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx @@ -0,0 +1,190 @@ +import React from 'react'; +import FontAwesome from 'react-fontawesome'; +import classNames from 'classnames'; +import Collapse from 'react-bootstrap/lib/Collapse.js'; + +import i18n from 'nfvo-utils/i18n/i18n.js'; +import {nodeTypes, mouseActions} from './AttachmentsConstants'; + +const typeToIcon = Object.freeze({ + heat: 'building-o', + volume: 'database', + network: 'cloud', + artifact: 'gear', + env: 'server', + other: 'cube' +}); + +const leftPanelWidth = 250; + +class SoftwareProductAttachmentsView extends React.Component { + + static propTypes = { + attachmentsTree: React.PropTypes.object.isRequired + }; + state = { + treeWidth: '400', + }; + + render() { + let {attachmentsTree, errorList = []} = this.props; + + let {treeWidth} = this.state; + return ( + <div className='software-product-attachments'> + <div className='software-product-view'> + <div className='software-product-landing-view-right-side'> + <div className='software-product-attachments-main'> + <div className='software-product-attachments-tree' style={{'width' : treeWidth + 'px'}}> + <div className='tree-wrapper'> + { + attachmentsTree && attachmentsTree.children && attachmentsTree.children.map((child, ind) => this.renderNode(child, [ind])) + } + </div> + </div> + <div className='software-product-attachments-separator' onMouseDown={e => this.onChangeTreeWidth(e)} /> + <div className='software-product-attachments-error-list'> + {errorList.length ? this.renderErrorList(errorList) : <div className='no-errors'>{attachmentsTree.children ? + i18n('VALIDATION SUCCESS') : i18n('THERE IS NO HEAT DATA TO PRESENT') }</div>} + </div> + </div> + </div> + </div> + </div> + ); + } + + + + renderNode(node, path) { + let isFolder = node.children && node.children.length > 0; + let {onSelectNode} = this.props; + return ( + <div key={node.name} className='tree-block-inside'> + { + <div onDoubleClick={() => this.props.toggleExpanded(path)} className={this.getTreeRowClassName(node.name)}> + { + isFolder && + <div onClick={() => this.props.toggleExpanded(path)} className={classNames('tree-node-expander', {'tree-node-expander-collapsed': !node.expanded})}> + <FontAwesome name='caret-down'/> + </div> + } + { + + <span className='tree-node-icon'> + <FontAwesome name={typeToIcon[node.type]}/> + </span> + } + { + + <span onClick={() => onSelectNode(node.name)} className={this.getTreeTextClassName(node)}> + {node.name} + </span> + } + </div> + } + { + isFolder && + <Collapse in={node.expanded}> + <div className='tree-node-children'> + { + node.children.map((child, ind) => this.renderNode(child, [...path, ind])) + } + </div> + </Collapse> + } + </div> + ); + } + + createErrorList(errorList, node, parent) { + if (node.errors) { + node.errors.forEach(error => errorList.push({ + error, + name: node.name, + parentName: parent.name, + type: node.type + })); + } + if (node.children && node.children.length) { + node.children.map((child) => this.createErrorList(errorList, child, node)); + } + } + + renderErrorList(errors) { + let prevError = {}; + let {selectedNode} = this.props; + return errors.map(error => { + let isSameNodeError = error.name === prevError.name && error.parentName === prevError.parentName; + prevError = error; + + return ( + <div + key={error.name + error.errorMessage + error.parentName} + + onClick={() => this.selectNode(error.name)} + className={classNames('error-item', {'clicked': selectedNode === error.name, 'shifted': !isSameNodeError})}> + <span className={classNames('error-item-file-type', {'strong': !isSameNodeError})}> + { + error.hasParent ? + i18n('{type} {name} in {parentName}: ', { + type: nodeTypes[error.type], + name: error.name, + parentName: error.parentName + }) : + i18n('{type} {name}: ', { + type: nodeTypes[error.type], + name: error.name + }) + } + </span> + <span className={`error-item-file-type ${error.errorLevel}`}> {error.errorMessage} </span> + </div> + ); + }); + } + + selectNode(currentSelectedNode) { + let {onUnselectNode, onSelectNode, selectedNode} = this.props; + if (currentSelectedNode !== selectedNode) { + onSelectNode(currentSelectedNode); + }else{ + onUnselectNode(); + } + + } + + getTreeRowClassName(name) { + let {hoveredNode, selectedNode} = this.props; + return classNames({ + 'tree-node-row': true, + 'tree-node-selected': name === hoveredNode, + 'tree-node-clicked': name === selectedNode + }); + } + + getTreeTextClassName(node) { + let {selectedNode} = this.props; + return classNames({ + 'tree-element-text': true, + 'error-status': node.errors, + 'error-status-selected': node.name === selectedNode + }); + } + + onChangeTreeWidth(e) { + if (e.button === mouseActions.MOUSE_BUTTON_CLICK) { + let onMouseMove = (e) => { + this.setState({treeWidth: e.clientX - leftPanelWidth}); + }; + let onMouseUp = () => { + document.removeEventListener('mousemove', onMouseMove); + document.removeEventListener('mouseup', onMouseUp); + }; + document.addEventListener('mousemove', onMouseMove); + document.addEventListener('mouseup', onMouseUp); + } + } +} + +export default SoftwareProductAttachmentsView; |