github.com/minio/console@v1.4.1/web-app/src/screens/Console/Dashboard/Prometheus/Widgets/SingleValueWidget.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 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 17 import React, { Fragment, useEffect, useState } from "react"; 18 import { useSelector } from "react-redux"; 19 import { Box, Loader } from "mds"; 20 import styled from "styled-components"; 21 import get from "lodash/get"; 22 import { widgetCommon } from "../../../Common/FormComponents/common/styleLibrary"; 23 import { splitSizeMetric, widgetDetailsToPanel } from "../utils"; 24 import { IDashboardPanel } from "../types"; 25 import { ErrorResponseHandler } from "../../../../../common/types"; 26 import { setErrorSnackMessage } from "../../../../../systemSlice"; 27 import { AppState, useAppDispatch } from "../../../../../store"; 28 import api from "../../../../../common/api"; 29 30 interface ISingleValueWidget { 31 title: string; 32 panelItem: IDashboardPanel; 33 timeStart: any; 34 timeEnd: any; 35 apiPrefix: string; 36 renderFn?: (arg: Record<string, any>) => any; 37 } 38 39 const SingleValueWidgetMain = styled.div(({ theme }) => ({ 40 display: "flex", 41 height: 140, 42 flexDirection: "column", 43 justifyContent: "center", 44 "& .unitText": { 45 color: get(theme, "mutedText", "#87888d"), 46 fontSize: 12, 47 }, 48 "& .loadingAlign": { 49 width: "100%", 50 textAlign: "center", 51 margin: "auto", 52 }, 53 "& .metric": { 54 fontSize: 60, 55 lineHeight: 1, 56 color: get(theme, "signalColors.main", "#07193E"), 57 fontWeight: 700, 58 }, 59 "& .titleElement": { 60 fontSize: 10, 61 color: get(theme, "mutedText", "#87888d"), 62 fontWeight: 700, 63 }, 64 ...widgetCommon(theme), 65 })); 66 67 const SingleValueWidget = ({ 68 title, 69 panelItem, 70 timeStart, 71 timeEnd, 72 apiPrefix, 73 renderFn, 74 }: ISingleValueWidget) => { 75 const dispatch = useAppDispatch(); 76 77 const [loading, setLoading] = useState<boolean>(false); 78 const [data, setData] = useState<string>(""); 79 const widgetVersion = useSelector( 80 (state: AppState) => state.dashboard.widgetLoadVersion, 81 ); 82 83 useEffect(() => { 84 setLoading(true); 85 }, [widgetVersion]); 86 87 useEffect(() => { 88 if (loading) { 89 let stepCalc = 0; 90 if (timeStart !== null && timeEnd !== null) { 91 const secondsInPeriod = 92 timeEnd.toUnixInteger() - timeStart.toUnixInteger(); 93 const periods = Math.floor(secondsInPeriod / 60); 94 95 stepCalc = periods < 1 ? 15 : periods; 96 } 97 98 api 99 .invoke( 100 "GET", 101 `/api/v1/${apiPrefix}/info/widgets/${ 102 panelItem.id 103 }/?step=${stepCalc}&${ 104 timeStart !== null ? `&start=${timeStart.toUnixInteger()}` : "" 105 }${timeStart !== null && timeEnd !== null ? "&" : ""}${ 106 timeEnd !== null ? `end=${timeEnd.toUnixInteger()}` : "" 107 }`, 108 ) 109 .then((res: any) => { 110 const widgetsWithValue = widgetDetailsToPanel(res, panelItem); 111 setData(widgetsWithValue.data); 112 setLoading(false); 113 }) 114 .catch((err: ErrorResponseHandler) => { 115 dispatch(setErrorSnackMessage(err)); 116 setLoading(false); 117 }); 118 } 119 }, [loading, panelItem, timeEnd, timeStart, dispatch, apiPrefix]); 120 121 const valueToRender = splitSizeMetric(data); 122 123 if (renderFn) { 124 return renderFn({ valueToRender, loading, title, id: panelItem.id }); 125 } 126 return ( 127 <SingleValueWidgetMain> 128 {loading && ( 129 <Box className={"loadingAlign"}> 130 <Loader /> 131 </Box> 132 )} 133 {!loading && ( 134 <Fragment> 135 <Box className={"metric"}>{splitSizeMetric(data)}</Box> 136 <Box className={"titleElement"}>{title}</Box> 137 </Fragment> 138 )} 139 </SingleValueWidgetMain> 140 ); 141 }; 142 143 export default SingleValueWidget;