github.com/thanos-io/thanos@v0.32.5/pkg/ui/react-app/src/thanos/pages/stores/StorePoolPanel.tsx (about) 1 import React, { FC } from 'react'; 2 import { Container, Collapse, Table, Badge } from 'reactstrap'; 3 import { now } from 'moment'; 4 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; 5 import { faMinus } from '@fortawesome/free-solid-svg-icons'; 6 import { ToggleMoreLess } from '../../../components/ToggleMoreLess'; 7 import { useLocalStorage } from '../../../hooks/useLocalStorage'; 8 import { getColor } from '../../../pages/targets/target'; 9 import { formatRelative, formatTime, parseTime, isValidTime } from '../../../utils'; 10 import { Store } from './store'; 11 import StoreLabels from './StoreLabels'; 12 13 export type StorePoolPanelProps = { title: string; storePool: Store[] }; 14 15 export const columns = [ 16 'Endpoint', 17 'Status', 18 'Announced LabelSets', 19 'Min Time (UTC)', 20 'Max Time (UTC)', 21 'Last Successful Health Check', 22 'Last Message', 23 ]; 24 25 export const storeTimeRangeMsg = (validMin: boolean, validMax: boolean): string => { 26 if (!validMin && !validMax) { 27 return "This store's time range data is not available"; 28 } 29 if (!validMin && validMax) { 30 return 'This store has no minimum time limit'; 31 } 32 if (validMin && !validMax) { 33 return 'This store has no maximum time limit'; 34 } 35 36 return ''; 37 }; 38 39 export const StorePoolPanel: FC<StorePoolPanelProps> = ({ title, storePool }) => { 40 const [{ expanded }, setOptions] = useLocalStorage(`store-pool-${title}-expanded`, { expanded: true }); 41 42 return ( 43 <Container fluid> 44 <ToggleMoreLess event={(): void => setOptions({ expanded: !expanded })} showMore={expanded}> 45 <span style={{ textTransform: 'capitalize' }}>{title}</span> 46 </ToggleMoreLess> 47 <Collapse isOpen={expanded}> 48 <Table size="sm" bordered hover> 49 <thead> 50 <tr key="header"> 51 {columns.map((column) => ( 52 <th key={column}>{column}</th> 53 ))} 54 </tr> 55 </thead> 56 <tbody> 57 {storePool.map((store: Store) => { 58 const { name, minTime, maxTime, labelSets, lastCheck, lastError } = store; 59 const health = lastError ? 'down' : 'up'; 60 const color = getColor(health); 61 const validMinTime = isValidTime(minTime); 62 const validMaxTime = isValidTime(maxTime); 63 64 return ( 65 <tr key={name}> 66 <td data-testid="endpoint" title={storeTimeRangeMsg(validMinTime, validMaxTime)}> 67 {name} 68 </td> 69 <td data-testid="health"> 70 <Badge color={color}>{health.toUpperCase()}</Badge> 71 </td> 72 <td data-testid="storeLabels"> 73 <StoreLabels labelSets={labelSets} /> 74 </td> 75 <td data-testid="minTime" title={storeTimeRangeMsg(validMinTime, validMaxTime)}> 76 {validMinTime ? formatTime(minTime) : <FontAwesomeIcon icon={faMinus} />} 77 </td> 78 <td data-testid="maxTime" title={storeTimeRangeMsg(validMinTime, validMaxTime)}> 79 {validMaxTime ? formatTime(maxTime) : <FontAwesomeIcon icon={faMinus} />} 80 </td> 81 <td data-testid="lastCheck"> 82 {isValidTime(parseTime(lastCheck)) ? ( 83 formatRelative(lastCheck, now()) 84 ) : ( 85 <FontAwesomeIcon icon={faMinus} /> 86 )}{' '} 87 ago 88 </td> 89 <td data-testid="lastError">{lastError ? <Badge color={color}>{lastError}</Badge> : null}</td> 90 </tr> 91 ); 92 })} 93 </tbody> 94 </Table> 95 </Collapse> 96 </Container> 97 ); 98 }; 99 100 export default StorePoolPanel;