import * as React from 'react' ; import styles from './TreeView.module.scss' ; import uniqBy from 'lodash/uniqBy' ; import { ITreeViewProps , SelectChildrenMode , TreeViewSelectionMode } from './ITreeViewProps' ; import { ITreeViewState } from './ITreeViewState' ; import { ITreeItem } from './ITreeItem' ; import TreeItem from './TreeItem' ; import * as telemetry from '../../common/telemetry' ; /**
 * Renders the controls for TreeItem component
 */ export class TreeView extends React . Component < ITreeViewProps , ITreeViewState > { private nodesToExpand : string [ ] = [ ] ; param props constructor ( props ) { super ( props ) ; telemetry . track ( 'TreeView' ) ; this . state = { loaded : true , defaultExpanded : props . defaultExpanded , activeItems : [ ] } ; this . handleTreeExpandCollapse = this . handleTreeExpandCollapse . bind ( this ) ; this . handleOnSelect = this . handleOnSelect . bind ( this ) ; if ( props . expandToSelected && props . defaultSelectedKeys ) { props . defaultSelectedKeys . forEach ( element => { this . pathTo ( props . items , element ) ; } ) ; } } private pathTo = ( array , target ) : string => { let result ; if ( array ) { array . some ( ( { key , children = [ ] } ) => { if ( key === target ) { this . nodesToExpand . push ( key ) ; result = key ; return true ; } let temp = this . pathTo ( children , target ) ; if ( temp ) { this . nodesToExpand . push ( key ) ; result = key + '.' + temp ; return true ; } } ) ; } return result ; } ; private getSelectedItems ( treeItems , selectedKeys , selectedChildren ) { let selectedItems = [ ] ; treeItems . forEach ( item => { if ( selectedKeys . indexOf ( item . key ) !== - 1 && item . selectable !== false && ! item . disabled ) { selectedItems . push ( item ) ; if ( selectedChildren ) { this . selectAllChildren ( item , selectedItems ) ; } else { if ( item . children ) { selectedItems . push ( ... this . getSelectedItems ( item . children , selectedKeys , selectedChildren ) ) ; } } } else { if ( item . children ) { selectedItems . push ( ... this . getSelectedItems ( item . children , selectedKeys , selectedChildren ) ) ; } } } ) ; return selectedItems ; } argument item argument isExpanded private handleTreeExpandCollapse ( item , isExpanded ) { if ( typeof this . props . onExpandCollapse === "function" ) { this . props . onExpandCollapse ( item , isExpanded ) ; } } param item private selectAllChildren ( item , selectedItems ) { if ( item . children ) { item . children . forEach ( element => { if ( ! element . disabled && element . selectable !== false ) { selectedItems . push ( element ) ; } if ( element . children ) { this . selectAllChildren ( element , selectedItems ) ; } } ) ; } } /**
     * Unselects all child nodes of selected parent.
     */ private unSelectChildren ( item , unselectArray ) { const tempItem = item ; if ( tempItem . children ) { tempItem . children . forEach ( element => { unselectArray . push ( element . key ) ; if ( element . children ) { this . unSelectChildren ( element , unselectArray ) ; } } ) ; } } argument item argument isSelected private handleOnSelect ( item , isSelected ) { let selectedItems = this . state . activeItems ; if ( isSelected ) { if ( this . props . selectionMode == TreeViewSelectionMode . Multiple ) { selectedItems . push ( item ) ; if ( this . checkIfChildrenShouldBeSelected ( SelectChildrenMode . Select ) ) { this . selectAllChildren ( item , selectedItems ) ; } selectedItems = uniqBy ( selectedItems , 'key' ) ; this . setState ( { activeItems : selectedItems } ) ; } else { this . setState ( { activeItems : [ item ] } ) ; selectedItems = [ item ] ; } } else { let unselectArray = [ ] ; unselectArray . push ( item . key ) ; if ( this . checkIfChildrenShouldBeSelected ( SelectChildrenMode . Unselect ) ) { this . unSelectChildren ( item , unselectArray ) ; } unselectArray . forEach ( element => { selectedItems = selectedItems . filter ( i => i . key != element ) ; } ) ; this . setState ( { activeItems : selectedItems } ) ; } if ( typeof this . props . onSelect === "function" ) { this . props . onSelect ( selectedItems ) ; } } private checkIfChildrenShouldBeSelected ( testMode ) { let selectChildrenMode = SelectChildrenMode . None ; if ( this . props . selectChildrenMode ) { selectChildrenMode = this . props . selectChildrenMode ; } else { if ( this . props . selectChildrenIfParentSelected ) { selectChildrenMode = SelectChildrenMode . All ; } } if ( ( selectChildrenMode & testMode ) === testMode ) { return true ; } return false ; } public componentDidMount ( ) { const { items , defaultSelectedKeys } = this . props ; if ( defaultSelectedKeys ) { const selectedItems = this . getSelectedItems ( items , defaultSelectedKeys , this . checkIfChildrenShouldBeSelected ( SelectChildrenMode . Mount ) ) ; this . setState ( { activeItems : selectedItems } ) ; } } public componentWillReceiveProps ( nextProps ) { const { items , defaultSelectedKeys } = nextProps ; if ( defaultSelectedKeys ) { const selectedItems = this . getSelectedItems ( items , defaultSelectedKeys , this . checkIfChildrenShouldBeSelected ( SelectChildrenMode . Update ) ) ; this . setState ( { activeItems : selectedItems } ) ; } } /**
     * Default React render method
     */ public render ( ) { const { items , selectionMode , onRenderItem , showCheckboxes , treeItemActionsDisplayMode , defaultExpanded , defaultExpandedChildren } = this . props ; return ( < div className = { styles . treeView } > { items . map ( ( treeNodeItem , index ) => ( < TreeItem treeItem = { treeNodeItem } leftOffset = { 20 } isFirstRender = { true } defaultExpanded = { defaultExpanded } defaultExpandedChildren = { defaultExpandedChildren !== undefined ? defaultExpandedChildren : true } selectionMode = { selectionMode } activeItems = { this . state . activeItems } parentCallbackExpandCollapse = { this . handleTreeExpandCollapse } parentCallbackOnSelect = { this . handleOnSelect } onRenderItem = { onRenderItem } showCheckboxes = { showCheckboxes } treeItemActionsDisplayMode = { treeItemActionsDisplayMode } nodesToExpand = { this . nodesToExpand } / > ) ) } < /div>); } }