Create wt-odlux directory
[ccsdk/features.git] / sdnr / wt-odlux / odlux / apps / inventoryApp / src / views / treeview.tsx
1 /**
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt odlux
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 import React from 'react';
19
20 import Breadcrumbs from '@mui/material/Breadcrumbs';
21 import Link from '@mui/material/Link';
22 import { Theme } from '@mui/material/styles';
23 import { WithStyles } from '@mui/styles';
24 import createStyles from '@mui/styles/createStyles';
25 import withStyles from '@mui/styles/withStyles';
26 import { RouteComponentProps } from 'react-router-dom';
27 import { SearchMode, TreeView, TreeViewCtorType } from '../../../../framework/src/components/material-ui/treeView';
28 import { renderObject } from '../../../../framework/src/components/objectDump';
29 import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
30 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
31
32 import { selectInventoryNodeAsyncAction, setSearchTermAction, UpdateExpandedNodesAction, updateInventoryTreeAsyncAction, UpdateSelectedNodeAction } from '../actions/inventoryTreeActions';
33 import { TreeDemoItem } from '../models/inventory';
34
35 const styles = (theme: Theme) => createStyles({
36   root: {
37     flex: '1 0 0%',
38     display: 'flex',
39     flexDirection: 'row',
40   },
41   tree: {
42     wordWrap: 'break-word',
43     minWidth: '250px',
44     padding: `0px ${theme.spacing(1)}`,
45   },
46   details: {
47     flex: '5 0 0%',
48     padding: `0px ${theme.spacing(1)}`,
49   },
50 });
51
52 const mapProps = (state: IApplicationStoreState) => ({
53   isBusy: state.inventory.inventoryTree.isBusy,
54   rootNodes: state.inventory.inventoryTree.rootNodes,
55   searchTerm: state.inventory.inventoryTree.searchTerm,
56   selectedNode: state.inventory.inventoryTree.selectedNode,
57   expendedItems: state.inventory.inventoryTree.expandedItems,
58 });
59
60 const mapDispatch = (dispatcher: IDispatcher) => ({
61   updateExpendedNodes: (expendedNodes: TreeDemoItem[]) => dispatcher.dispatch(new UpdateExpandedNodesAction(expendedNodes)),
62   updateInventoryTree: (mountId: string, searchTerm?: string) => dispatcher.dispatch(updateInventoryTreeAsyncAction(mountId, searchTerm)),
63   selectTreeNode: (nodeId?: string) => nodeId ? dispatcher.dispatch(selectInventoryNodeAsyncAction(nodeId)) : dispatcher.dispatch(new UpdateSelectedNodeAction(undefined)),
64   setSearchTerm: (searchTerm: string) => dispatcher.dispatch(setSearchTermAction(searchTerm)),
65 });
66
67 const propsChache = Symbol('PropsCache');
68 const InventoryTree = TreeView as any as TreeViewCtorType<string>;
69
70
71
72 type TreeviewComponentProps = RouteComponentProps<{ mountId: string }> & WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>;
73
74 type TreeviewComponentState = {
75   [propsChache]: {
76     rootNodes?: TreeDemoItem[];
77   };
78   rootNodes: TreeDemoItem[];
79 };
80
81
82 class DashboardComponent extends React.Component<TreeviewComponentProps, TreeviewComponentState> {
83
84   constructor(props: TreeviewComponentProps) {
85     super(props);
86
87     this.state = {
88       [propsChache]: {},
89       rootNodes: [],
90     };
91   }
92
93   static getDerivedStateFromProps(props: TreeviewComponentProps, state: TreeviewComponentState) {
94     if (state[propsChache].rootNodes != props.rootNodes) {
95       // eslint-disable-next-line no-param-reassign
96       state = { ...state, rootNodes: props.rootNodes };
97     }
98     return state;
99   }
100
101   render() {
102     const { classes, updateInventoryTree, updateExpendedNodes, expendedItems, selectedNode, selectTreeNode, searchTerm, match: { params: { mountId } } } = this.props;
103     const scrollbar = { overflow: 'auto', paddingRight: '20px' };
104
105     let filteredDashboardPath = `/inventory/dashboard/${this.props.match.params.mountId}`;
106     let basePath = `/inventory/${this.props.match.params.mountId}`;
107
108     return (
109       <div style={scrollbar} >
110         <div >
111           <Breadcrumbs aria-label="breadcrumbs">
112             <Link underline="hover" color="inherit" href="#" aria-label="back-breadcrumb"
113               onClick={(event: React.MouseEvent<HTMLElement>) => {
114                 event.preventDefault();
115                 this.props.history.push(filteredDashboardPath);
116               }}>Back</Link>
117             <Link underline="hover" color="inherit" href="#"
118               aria-label={this.props.match.params.mountId + '-breadcrumb'}
119               onClick={(event: React.MouseEvent<HTMLElement>) => {
120                 event.preventDefault();
121                 this.props.history.push(basePath);
122               }}><span>{this.props.match.params.mountId}</span></Link>
123           </Breadcrumbs>
124         </div>
125         <br />
126         <div style={scrollbar} className={classes.root}>
127           <InventoryTree className={classes.tree} items={this.state.rootNodes} enableSearchBar initialSearchTerm={searchTerm} searchMode={SearchMode.OnEnter} searchTerm={searchTerm}
128             // eslint-disable-next-line @typescript-eslint/no-shadow
129             onSearch={(searchTerm) => updateInventoryTree(mountId, searchTerm)} expandedItems={expendedItems} onFolderClick={(item) => {
130               const indexOfItemToToggle = expendedItems.indexOf(item);
131               if (indexOfItemToToggle === -1) {
132                 updateExpendedNodes([...expendedItems, item]);
133               } else {
134                 updateExpendedNodes([
135                   ...expendedItems.slice(0, indexOfItemToToggle),
136                   ...expendedItems.slice(indexOfItemToToggle + 1),
137                 ]);
138               }
139             }}
140             onItemClick={(elm) => selectTreeNode(elm.value)} />
141           <div className={classes.details}>{
142             selectedNode && renderObject(selectedNode, 'tree-view') || null
143           }</div>
144         </div>
145       </div>
146     );
147   }
148
149   componentWillUnmount() {
150     this.props.setSearchTerm('*');
151   }
152 }
153
154 export const InventoryTreeView = connect(mapProps, mapDispatch)(withStyles(styles)(DashboardComponent));
155 export default InventoryTreeView;