Add new code new version
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / softwareProduct / attachments / SoftwareProductAttachmentsView.jsx
1 import React from 'react';
2 import FontAwesome from 'react-fontawesome';
3 import classNames from 'classnames';
4 import Collapse from 'react-bootstrap/lib/Collapse.js';
5
6 import i18n from 'nfvo-utils/i18n/i18n.js';
7 import {nodeTypes, mouseActions} from './SoftwareProductAttachmentsConstants';
8
9 const typeToIcon = Object.freeze({
10         heat: 'building-o',
11         volume: 'database',
12         network: 'cloud',
13         artifact: 'gear',
14         env: 'server',
15         other: 'cube'
16 });
17
18 const leftPanelWidth = 250;
19
20 class SoftwareProductAttachmentsView extends React.Component {
21
22         static propTypes = {
23                 attachmentsTree: React.PropTypes.object.isRequired
24         };
25         state = {
26                 treeWidth: '400'
27         };
28
29         render() {
30                 let {attachmentsTree, errorList} = this.props;
31                 let {treeWidth} = this.state;
32                 return (
33                         <div className='software-product-attachments'>
34                                 <div className='software-product-attachments-tree' style={{'width' : treeWidth + 'px'}}>
35                                         <div className='tree-wrapper'>
36                                                 {
37                                                         attachmentsTree && attachmentsTree.children && attachmentsTree.children.map((child, ind) => this.renderNode(child, [ind]))
38                                                 }
39                                         </div>
40                                 </div>
41                                 <div onMouseDown={(e) => this.onChangeTreeWidth(e)} className='software-product-attachments-separator'/>
42
43                                 <div className='software-product-attachments-error-list'>
44                                         {errorList.length ? this.renderErrorList(errorList) : <div className='no-errors'>{attachmentsTree.children ?
45                                                 i18n('VALIDATION SUCCESS') : i18n('THERE IS NO HEAT DATA TO PRESENT') }</div>}
46                                 </div>
47                         </div>
48                 );
49         }
50
51         renderNode(node, path) {
52                 let isFolder = node.children && node.children.length > 0;
53                 let {onSelectNode} = this.props;
54                 return (
55                         <div key={node.name} className='tree-block-inside'>
56                                 {
57                                         <div onDoubleClick={() => this.props.toggleExpanded(path)} className={this.getTreeRowClassName(node.name)}>
58                                                 {
59                                                         isFolder &&
60                                                         <div onClick={() => this.props.toggleExpanded(path)} className={classNames('tree-node-expander', {'tree-node-expander-collapsed': !node.expanded})}>
61                                                                 <FontAwesome name='caret-down'/>
62                                                         </div>
63                                                 }
64                                                 {
65
66                                                         <span className='tree-node-icon'>
67                                                                 <FontAwesome name={typeToIcon[node.type]}/>
68                                                         </span>
69                                                 }
70                                                 {
71
72                                                         <span onClick={() => onSelectNode(node.name)} className={this.getTreeTextClassName(node)}>
73                                                         {node.name}
74                                                         </span>
75                                                 }
76                                         </div>
77                                 }
78                                 {
79                                         isFolder &&
80                                         <Collapse in={node.expanded}>
81                                                 <div className='tree-node-children'>
82                                                         {
83                                                                 node.children.map((child, ind) => this.renderNode(child, [...path, ind]))
84                                                         }
85                                                 </div>
86                                         </Collapse>
87                                 }
88                         </div>
89                 );
90         }
91
92         createErrorList(errorList, node, parent) {
93                 if (node.errors) {
94                         node.errors.forEach(error => errorList.push({
95                                 error,
96                                 name: node.name,
97                                 parentName: parent.name,
98                                 type: node.type
99                         }));
100                 }
101                 if (node.children && node.children.length) {
102                         node.children.map((child) => this.createErrorList(errorList, child, node));
103                 }
104         }
105
106         renderErrorList(errors) {
107                 let prevError = {};
108                 let {selectedNode} = this.props;
109                 return errors.map(error => {
110                         let isSameNodeError = error.name === prevError.name && error.parentName === prevError.parentName;
111                         prevError = error;
112
113                         return (
114                                 <div
115                                         key={error.name + error.errorMessage + error.parentName}
116
117                                         onClick={() => this.selectNode(error.name)}
118                                         className={classNames('error-item', {'clicked': selectedNode === error.name, 'shifted': !isSameNodeError})}>
119                                         <span className={classNames('error-item-file-type', {'strong': !isSameNodeError})}>
120                                         {
121                                                 error.hasParent ?
122                                                         i18n('{type}  {name} in {parentName}: ', {
123                                                                 type: nodeTypes[error.type],
124                                                                 name: error.name,
125                                                                 parentName: error.parentName
126                                                         }) :
127                                                         i18n('{type}  {name}: ', {
128                                                                 type: nodeTypes[error.type],
129                                                                 name: error.name
130                                                         })
131                                         }
132                                         </span>
133                                         <span className={`error-item-file-type ${error.errorLevel}`}> {error.errorMessage} </span>
134                                 </div>
135                         );
136                 });
137         }
138
139         selectNode(currentSelectedNode) {
140                 let {onUnselectNode, onSelectNode, selectedNode} = this.props;
141                 if (currentSelectedNode !== selectedNode) {
142                         onSelectNode(currentSelectedNode);
143                 }else{
144                         onUnselectNode();
145                 }
146
147         }
148
149         getTreeRowClassName(name) {
150                 let {hoveredNode, selectedNode} = this.props;
151                 return classNames({
152                         'tree-node-row': true,
153                         'tree-node-selected': name === hoveredNode,
154                         'tree-node-clicked': name === selectedNode
155                 });
156         }
157
158         getTreeTextClassName(node) {
159                 let {selectedNode} = this.props;
160                 return classNames({
161                         'tree-element-text': true,
162                         'error-status': node.errors,
163                         'error-status-selected': node.name === selectedNode
164                 });
165         }
166
167         onChangeTreeWidth(e) {
168                 if (e.button === mouseActions.MOUSE_BUTTON_CLICK) {
169                         let onMouseMove = (e) => {
170                                 this.setState({treeWidth: e.clientX - leftPanelWidth});
171                         };
172                         let onMouseUp = () => {
173                                 document.removeEventListener('mousemove', onMouseMove);
174                                 document.removeEventListener('mouseup', onMouseUp);
175                         };
176                         document.addEventListener('mousemove', onMouseMove);
177                         document.addEventListener('mouseup', onMouseUp);
178                 }
179         }
180 }
181
182 export default SoftwareProductAttachmentsView;