github.com/replicatedhq/ship@v0.55.0/web/init/src/components/shared/Sidebar.jsx (about) 1 import * as React from "react"; 2 import assign from "object-assign"; 3 import SidebarItem from "./SidebarItem"; 4 5 export default class Sidebar extends React.Component { 6 constructor() { 7 super(); 8 this.state = { 9 activeSub: "", 10 } 11 } 12 13 isActive = (link, pathname = "") => { 14 if (!link) return false; 15 return pathname.indexOf(`${link}`) > -1; 16 } 17 18 buildSubItems = (items) => { 19 const { activeSub } = this.state; 20 const _items = items.filter(Boolean).map((item) => { 21 return assign(item, { 22 isActive: activeSub === item.id, 23 }); 24 }); 25 return _items; 26 } 27 28 getSidebarItems = (configOnly) => { 29 if (configOnly) { 30 const { configRouteId } = this.props; 31 return [{ 32 id: 0, 33 linkTo: `/${configRouteId}`, 34 label: "Application settings", 35 position: "top", 36 subItems: this.buildSubItems(this.props.appSettingsFieldsList) 37 }, 38 ]; 39 } else { 40 return [{ 41 id: 0, 42 linkTo: "/config", 43 label: "Application settings", 44 position: "top", 45 subItems: this.buildSubItems(this.props.appSettingsFieldsList) 46 }, { 47 id: 1, 48 linkTo: `/support`, 49 label: "Support", 50 position: "top", 51 }, { 52 id: 2, 53 linkTo: `/cluster`, 54 label: "Cluster", 55 position: "top", 56 }, { 57 id: 4, 58 linkTo: `/releases`, 59 label: "Releases", 60 position: "top", 61 }, { 62 id: 5, 63 linkTo: `/snapshots`, 64 label: "Snapshots", 65 position: "top", 66 }, { 67 id: 6, 68 linkTo: `/view-license`, 69 label: "View license", 70 position: "top", 71 }, { 72 id: 7, 73 linkTo: `/console-settings`, 74 label: "Console settings", 75 position: "top", 76 subItems: this.buildSubItems(this.props.consoleSettingsFieldsList) 77 }, 78 ]; 79 } 80 } 81 82 scrollToSection = (id) => { 83 const el = document.getElementById(id); 84 if (!el) return; 85 setTimeout(() => { 86 el.scrollIntoView({ behavior: "smooth", block: "start" }); 87 this.setState({ activeSub: id }); 88 }, 50); 89 } 90 91 componentDidUpdate(lastProps) { 92 const { location } = this.props; 93 if (lastProps.location.hash !== location.hash && location.hash) { 94 this.scrollToSection(location.hash.replace("#", "")); 95 } 96 } 97 98 onClick = (item) => { 99 this.setState({ route: item.linkTo }); 100 if (item.subItems) { 101 this.setState({ activeSub: "" }); 102 } 103 return (e, ...rest) => { 104 if (typeof item.onClick === "function") { 105 item.onClick(e, ...rest); 106 return; 107 } 108 }; 109 } 110 111 render() { 112 const { configOnly } = this.props; 113 const items = this.getSidebarItems(configOnly); 114 const sidebarItems = items.map(item => { 115 const active = this.isActive(item.linkTo, window.location.pathname); 116 return assign(item, { 117 isActive: active, 118 }); 119 }); 120 const renderItem = item => { 121 return ( 122 <div key={item.id}> 123 <SidebarItem 124 {...item} 125 onClick={() => this.onClick(item)} 126 /> 127 {item.isActive && item.subItems ? 128 item.subItems.map((item) => ( 129 <SidebarItem 130 key={item.id} 131 className="SubItem" 132 activeSub={this.state.activeSub} 133 subItemLinkTo={`${this.props.location.pathname}#${item.id}`} 134 {...item} 135 onClick={() => this.scrollToSection(item.id)} 136 /> 137 )) 138 : null} 139 </div> 140 ); 141 }; 142 143 return ( 144 <div className="SidebarContent-wrapper flex flex1 u-minHeight--full"> 145 <div className="flex-column u-width--full"> 146 <div className="SidebarElements-wrapper flex-column flex-1-auto u-overflow--auto"> 147 {sidebarItems 148 .filter(i => i.position === "top") 149 .map(renderItem) 150 } 151 </div> 152 </div> 153 </div> 154 ); 155 } 156 }