summaryrefslogtreecommitdiffstats
path: root/openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx')
-rw-r--r--openecomp-ui/src/sdc-app/heatvalidation/attachments/AttachmentsView.jsx190
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;