1
import React, { Fragment, FC, useState, useEffect } from 'react';
2
import { Table } from 'reactstrap';
3
import { withStatusIndicator } from '../../components/withStatusIndicator';
4
import { useFetch } from '../../hooks/useFetch';
5
import { usePathPrefix } from '../../contexts/PathPrefixContext';
6
import { API_PATH } from '../../constants/constants';
8
interface StatusPageProps {
9
data: Record<string, string>;
13
export const statusConfig: Record<
15
// eslint-disable-next-line @typescript-eslint/no-explicit-any
16
{ title?: string; customizeValue?: (v: any, key: string) => any; customRow?: boolean; skip?: boolean }
18
startTime: { title: 'Start time', customizeValue: (v: string) => new Date(v).toUTCString() },
19
CWD: { title: 'Working directory' },
20
reloadConfigSuccess: {
21
title: 'Configuration reload',
22
customizeValue: (v: boolean) => (v ? 'Successful' : 'Unsuccessful'),
24
lastConfigTime: { title: 'Last successful configuration reload' },
25
corruptionCount: { title: 'WAL corruptions' },
26
goroutineCount: { title: 'Goroutines' },
27
storageRetention: { title: 'Storage retention' },
28
activeAlertmanagers: {
30
customizeValue: (alertMgrs: { url: string }[], key) => {
36
{alertMgrs.map(({ url }) => {
37
const { origin, pathname } = new URL(url);
41
<a href={url}>{origin}</a>
51
droppedAlertmanagers: { skip: true },
54
export const StatusContent: FC<StatusPageProps> = ({ data, title }) => {
58
<Table className="h-auto" size="sm" bordered striped>
60
{Object.entries(data).map(([k, v]) => {
61
const { title = k, customizeValue = (val: string) => val, customRow, skip } = statusConfig[k] || {};
66
return customizeValue(v, k);
70
<th className="capitalize-title" style={{ width: '35%' }}>
73
<td className="text-break">{customizeValue(v, title)}</td>
82
const StatusWithStatusIndicator = withStatusIndicator(StatusContent);
84
StatusContent.displayName = 'Status';
86
const StatusResult: FC<{ fetchPath: string; title: string }> = ({ fetchPath, title }) => {
87
const { response, isLoading, error } = useFetch(fetchPath);
89
<StatusWithStatusIndicator
95
componentTitle={title}
100
interface StatusProps {
101
agentMode?: boolean | false;
102
setAnimateLogo?: (animateLogo: boolean) => void;
105
const Status: FC<StatusProps> = ({ agentMode, setAnimateLogo }) => {
111
const [inputText, setInputText] = useState('');
114
const handleKeyPress = (event: KeyboardEvent) => {
115
const keyPressed = event.key.toUpperCase();
116
setInputText((prevInputText) => {
117
const newInputText = prevInputText.slice(-3) + String.fromCharCode(((keyPressed.charCodeAt(0) - 64) % 26) + 65);
122
document.addEventListener('keypress', handleKeyPress);
125
document.removeEventListener('keypress', handleKeyPress);
130
if (setAnimateLogo && inputText != '') {
131
setAnimateLogo(inputText.toUpperCase() === 'QSPN');
140
const pathPrefix = usePathPrefix();
141
const path = `${pathPrefix}/${API_PATH}`;
146
{ fetchPath: `${path}/status/runtimeinfo`, title: 'Runtime Information' },
147
{ fetchPath: `${path}/status/buildinfo`, title: 'Build Information' },
148
{ fetchPath: `${path}/alertmanagers`, title: 'Alertmanagers' },
149
].map(({ fetchPath, title }) => {
150
if (agentMode && title === 'Alertmanagers') {
153
return <StatusResult fetchPath={fetchPath} title={title} />;
159
export default Status;