github.com/minio/console@v1.4.1/web-app/src/screens/Console/Dashboard/BasicDashboard/ServerInfoItem.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 import React from "react"; 17 import styled from "styled-components"; 18 import get from "lodash/get"; 19 import { Box, breakPoints, CircleIcon } from "mds"; 20 import { niceDays } from "../../../../common/utils"; 21 import { 22 getDriveStatusColor, 23 getNetworkStatusColor, 24 serverStatusColor, 25 } from "./Utils"; 26 import { ServerProperties } from "api/consoleApi"; 27 28 interface ICardProps { 29 server: ServerProperties; 30 index: number; 31 } 32 33 const ServerStatItemMain = styled.div(({ theme }) => ({ 34 alignItems: "baseline", 35 padding: "5px", 36 display: "flex", 37 gap: "5px", 38 "& .StatBox": { 39 display: "flex", 40 alignItems: "center", 41 justifyContent: "center", 42 flexFlow: "column", 43 "& .stat-text": { 44 color: get(theme, "mutedText", "#87888d"), 45 fontSize: "12px", 46 }, 47 "& .stat-value": { 48 fontSize: "18px", 49 color: get(theme, "signalColors.main", "#07193E"), 50 display: "flex", 51 fontWeight: 500, 52 overflow: "hidden", 53 textOverflow: "ellipsis", 54 whiteSpace: "nowrap", 55 "& .stat-container": { 56 display: "flex", 57 alignItems: "center", 58 justifyContent: "center", 59 flexFlow: "column", 60 marginLeft: "5px", 61 maxWidth: "40px", 62 "&:first-of-type(svg)": { 63 fill: get(theme, "mutedText", "#87888d"), 64 }, 65 "& .stat-indicator": { 66 marginRight: "0px", 67 justifyContent: "center", 68 alignItems: "center", 69 textAlign: "center", 70 "& svg.min-icon": { 71 width: "10px", 72 height: "10px", 73 }, 74 "&.good": { 75 "& svg.min-icon": { 76 fill: get(theme, "signalColors.good", "#4CCB92"), 77 }, 78 }, 79 "&.warn": { 80 "& svg.min-icon": { 81 fill: get(theme, "signalColors.warning", "#FFBD62"), 82 }, 83 }, 84 "&.bad": { 85 "& svg.min-icon": { 86 fill: get(theme, "signalColors.danger", "#C51B3F"), 87 }, 88 }, 89 }, 90 }, 91 }, 92 }, 93 })); 94 95 const ServerInfoItemMain = styled.div(({ theme }) => ({ 96 display: "flex", 97 alignItems: "flex-start", 98 flexFlow: "column", 99 flex: 1, 100 "& .server-state": { 101 marginLeft: "8px", 102 "& .min-icon": { 103 height: "14px", 104 width: "14px", 105 }, 106 "&.good": { 107 "& svg.min-icon": { 108 fill: get(theme, "signalColors.good", "#4CCB92"), 109 }, 110 }, 111 "&.warn": { 112 "& svg.min-icon": { 113 fill: get(theme, "signalColors.warning", "#FFBD62"), 114 }, 115 }, 116 "&.bad": { 117 "& svg.min-icon": { 118 fill: get(theme, "signalColors.danger", "#C51B3F"), 119 }, 120 }, 121 }, 122 })); 123 124 const ServerStatItem = ({ 125 label = "", 126 value = "", 127 statusColor = "warn", 128 hasStatus = false, 129 }: { 130 label?: string; 131 value?: any; 132 hasStatus?: boolean; 133 statusColor?: "good" | "warn" | "bad"; 134 }) => { 135 return ( 136 <ServerStatItemMain> 137 <Box className={"StatBox"}> 138 <div className="stat-value"> 139 {value}{" "} 140 <Box className={"stat-container"}> 141 {hasStatus ? ( 142 <Box className={`stat-indicator ${statusColor}`}> 143 <CircleIcon /> 144 </Box> 145 ) : ( 146 <Box sx={{ width: "12px", height: "12px" }} /> 147 )} 148 </Box> 149 </div> 150 <div className="stat-text">{label}</div> 151 </Box> 152 </ServerStatItemMain> 153 ); 154 }; 155 156 const ServerInfoItem = ({ server }: ICardProps) => { 157 const networkKeys = Object.keys(get(server, "network", {})); 158 const networkTotal = networkKeys.length; 159 const totalDrives = server.drives ? server.drives.length : 0; 160 const activeNetwork = networkKeys.reduce((acc: number, currValue: string) => { 161 const item = server.network ? server.network[currValue] : ""; 162 if (item === "online") { 163 return acc + 1; 164 } 165 return acc; 166 }, 0); 167 const activeDisks = server.drives 168 ? server.drives.filter((element) => element.state === "ok").length 169 : 0; 170 return ( 171 <ServerInfoItemMain> 172 <Box 173 sx={{ 174 display: "flex", 175 alignItems: "center", 176 padding: "3px", 177 gap: "15px", 178 justifyContent: "space-between", 179 width: "100%", 180 paddingLeft: "20px", 181 flexFlow: "row", 182 [`@media (max-width: ${breakPoints.md}px)`]: { 183 flexFlow: "column", 184 }, 185 }} 186 > 187 <Box 188 sx={{ 189 display: "flex", 190 alignItems: "center", 191 }} 192 > 193 <Box 194 sx={{ 195 fontWeight: 600, 196 textTransform: "none", 197 }} 198 > 199 {server.endpoint || ""} 200 </Box> 201 {server?.state && ( 202 <Box className={`server-state ${serverStatusColor(server.state)}`}> 203 <CircleIcon /> 204 </Box> 205 )} 206 </Box> 207 208 <Box 209 sx={{ 210 display: "flex", 211 alignItems: "center", 212 justifyContent: "center", 213 flex: "1.5", 214 gap: "5%", 215 }} 216 > 217 <ServerStatItem 218 statusColor={getDriveStatusColor(activeDisks, totalDrives)} 219 label={"Drives"} 220 hasStatus={true} 221 value={`${activeDisks}/${totalDrives}`} 222 /> 223 <ServerStatItem 224 statusColor={getNetworkStatusColor(activeNetwork, networkTotal)} 225 label={"Network"} 226 hasStatus={true} 227 value={`${activeNetwork}/${networkTotal}`} 228 /> 229 <ServerStatItem 230 statusColor={"good"} 231 label={"Up time"} 232 value={server?.uptime ? niceDays(`${server.uptime}`) : "N/A"} 233 /> 234 </Box> 235 <ServerStatItem 236 statusColor={"good"} 237 label={""} 238 value={ 239 <Box 240 sx={{ 241 background: "rgb(235, 236, 237)", 242 color: "#000000", 243 paddingLeft: "10px", 244 paddingRight: "10px", 245 borderRadius: "2px", 246 fontSize: "12px", 247 marginTop: "5px", 248 249 "& .label": { 250 fontWeight: 600, 251 marginRight: "3px", 252 }, 253 }} 254 > 255 <span className="label">Version:</span> 256 {server.version ? server.version : "N/A"} 257 </Box> 258 } 259 /> 260 </Box> 261 </ServerInfoItemMain> 262 ); 263 }; 264 export default ServerInfoItem;