github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/cluster/containers/nodesOverview/tableSection.tsx (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import * as React from "react"; 12 import { connect } from "react-redux"; 13 import cn from "classnames"; 14 import { Icon } from "antd"; 15 import { Action, Dispatch } from "redux"; 16 17 import { LocalSetting, setLocalSetting } from "src/redux/localsettings"; 18 import { AdminUIState } from "src/redux/state"; 19 import { Text, TextTypes } from "src/components"; 20 21 import "./tableSection.styl"; 22 23 interface MapStateToProps { 24 isCollapsed: boolean; 25 } 26 27 interface MapDispatchToProps { 28 saveExpandedState: (isCollapsed: boolean) => void; 29 } 30 31 interface TableSectionProps { 32 // Uniq ID which is used to create LocalSettings key for storing user state in session. 33 id: string; 34 // Title of the section 35 title: string; 36 // Bottom part of the section, can be string or RectNode. 37 footer?: React.ReactNode; 38 // If true, allows collapse content of the section and only title remains visible. 39 isCollapsible?: boolean; 40 // Class which is applied on root element of the section. 41 className?: string; 42 children?: React.ReactNode; 43 } 44 45 interface TableSectionState { 46 isCollapsed: boolean; 47 } 48 49 class TableSection extends React.Component<TableSectionProps & MapStateToProps & MapDispatchToProps, TableSectionState> { 50 static defaultProps: Partial<TableSectionProps> = { 51 isCollapsible: false, 52 footer: null, 53 className: "", 54 }; 55 56 state = { 57 isCollapsed: false, 58 }; 59 60 componentWillUnmount() { 61 this.props.saveExpandedState(this.state.isCollapsed); 62 } 63 64 onExpandSectionToggle = () => { 65 this.setState({ 66 isCollapsed: !this.state.isCollapsed, 67 }); 68 this.props.saveExpandedState(!this.state.isCollapsed); 69 } 70 71 getCollapseSectionToggle = () => { 72 const { isCollapsible } = this.props; 73 if (!isCollapsible) { 74 return null; 75 } 76 77 const { isCollapsed } = this.state; 78 79 return ( 80 <div className="collapse-toggle" onClick={this.onExpandSectionToggle}> 81 <span>{isCollapsed ? "Show" : "Hide"}</span> 82 <Icon 83 className="collapse-toggle__icon" 84 type={isCollapsed ? "caret-left" : "caret-down"} /> 85 </div> 86 ); 87 } 88 89 render() { 90 const { children, title, footer, className } = this.props; 91 const { isCollapsed } = this.state; 92 const rootClass = cn("table-section", className); 93 const contentClass = cn( 94 "table-section__content", 95 { 96 "table-section__content--collapsed": isCollapsed, 97 }, 98 ); 99 const collapseToggleButton = this.getCollapseSectionToggle(); 100 101 return ( 102 <div className={rootClass}> 103 <section 104 className="table-section__heading table-section__heading--justify-end"> 105 <Text textType={TextTypes.Heading3}>{title}</Text> 106 {collapseToggleButton} 107 </section> 108 <div className={contentClass}> 109 {children} 110 { 111 footer && ( 112 <div className="table-section__footer"> 113 {footer} 114 </div> 115 ) 116 } 117 </div> 118 </div> 119 ); 120 } 121 } 122 123 const getTableSectionKey = (id: string) => `cluster_overview/table_section/${id}/is_expanded`; 124 125 const mapStateToProps = (state: AdminUIState, props: TableSectionProps) => { 126 const tableSectionState = new LocalSetting<AdminUIState, boolean>( 127 getTableSectionKey(props.id), (s) => s.localSettings, 128 ); 129 130 return { 131 isCollapsed: tableSectionState.selector(state), 132 }; 133 }; 134 135 const mapDispatchToProps = (dispatch: Dispatch<Action, AdminUIState>, props: TableSectionProps) => ({ 136 saveExpandedState: (isCollapsed: boolean) => { 137 const tableSectionKey = getTableSectionKey(props.id); 138 dispatch(setLocalSetting(tableSectionKey, isCollapsed)); 139 }, 140 }); 141 142 export default connect(mapStateToProps, mapDispatchToProps)(TableSection);