mirror of
https://github.com/prometheus/alertmanager.git
synced 2026-02-05 06:45:45 +01:00
Remove abandoned react-app (#4617)
The experimental react-app has been abandoned. Remove the code to avoid continued maintence. Signed-off-by: SuperQ <superq@gmail.com>
This commit is contained in:
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@@ -18,8 +18,3 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/ui/react-app"
|
||||
open-pull-requests-limit: 20
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
|
||||
13
Makefile
13
Makefile
@@ -27,19 +27,10 @@ STATICCHECK_IGNORE =
|
||||
build-all: assets apiv2 build
|
||||
|
||||
.PHONY: build
|
||||
build: build-react-app assets-compress common-build
|
||||
build: common-build
|
||||
|
||||
.PHONY: lint
|
||||
lint: assets-compress common-lint
|
||||
|
||||
.PHONY: build-react-app
|
||||
build-react-app:
|
||||
cd ui/react-app && npm install && npm run build
|
||||
|
||||
.PHONY: assets-compress
|
||||
assets-compress: build-react-app
|
||||
@echo '>> compressing assets'
|
||||
scripts/compress_assets.sh
|
||||
lint: common-lint
|
||||
|
||||
.PHONY: assets
|
||||
assets: asset/assets_vfsdata.go
|
||||
|
||||
@@ -60,7 +60,6 @@ import (
|
||||
"github.com/prometheus/alertmanager/timeinterval"
|
||||
"github.com/prometheus/alertmanager/types"
|
||||
"github.com/prometheus/alertmanager/ui"
|
||||
reactapp "github.com/prometheus/alertmanager/ui/react-app"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -549,7 +548,6 @@ func run() int {
|
||||
webReload := make(chan chan error)
|
||||
|
||||
ui.Register(router, webReload, logger)
|
||||
reactapp.Register(router, logger)
|
||||
|
||||
mux := api.Register(router, *routePrefix)
|
||||
|
||||
|
||||
1
go.mod
1
go.mod
@@ -36,7 +36,6 @@ require (
|
||||
github.com/oklog/ulid v1.3.1
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/prometheus/common v0.67.1
|
||||
github.com/prometheus/common/assets v0.2.0
|
||||
github.com/prometheus/exporter-toolkit v0.14.1
|
||||
github.com/prometheus/sigv4 v0.2.1
|
||||
github.com/rs/cors v1.11.1
|
||||
|
||||
2
go.sum
2
go.sum
@@ -487,8 +487,6 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8
|
||||
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
|
||||
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
|
||||
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
|
||||
github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM=
|
||||
github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI=
|
||||
github.com/prometheus/exporter-toolkit v0.14.1 h1:uKPE4ewweVRWFainwvAcHs3uw15pjw2dk3I7b+aNo9o=
|
||||
github.com/prometheus/exporter-toolkit v0.14.1/go.mod h1:di7yaAJiaMkcjcz48f/u4yRPwtyuxTU5Jr4EnM2mhtQ=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# compress static assets
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd ui/react-app
|
||||
cp embed.go.tmpl embed.go
|
||||
|
||||
GZIP_OPTS="-fkn"
|
||||
# gzip option '-k' may not always exist in the latest gzip available on different distros.
|
||||
if ! gzip -k -h &>/dev/null; then GZIP_OPTS="-fn"; fi
|
||||
|
||||
dist="dist"
|
||||
|
||||
if ! [[ -d "${dist}" ]]; then
|
||||
mkdir -p ${dist}
|
||||
echo "<!doctype html>
|
||||
<html lang=\"en\">
|
||||
<head>
|
||||
<meta charset=\"utf-8\">
|
||||
<title>Node</title>
|
||||
<base href=\"/\">
|
||||
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">
|
||||
<link rel=\"icon\" type=\"image/x-icon\" href=\"favicon.ico\">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<p> This is the default index, looks like you forget to generate the react app before generating the golang endpoint.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>" > ${dist}/index.html
|
||||
fi
|
||||
|
||||
find dist -type f -name '*.gz' -delete
|
||||
find dist -type f -exec gzip $GZIP_OPTS '{}' \; -print0 | xargs -0 -I % echo %.gz | sort | xargs echo //go:embed >> embed.go
|
||||
echo var embedFS embed.FS >> embed.go
|
||||
@@ -1,83 +0,0 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:jsx-a11y/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
|
||||
plugins: ['import'],
|
||||
|
||||
env: {
|
||||
commonjs: true,
|
||||
es6: true,
|
||||
jest: true,
|
||||
node: true,
|
||||
browser: true,
|
||||
},
|
||||
|
||||
parser: '@typescript-eslint/parser',
|
||||
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
},
|
||||
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
},
|
||||
|
||||
rules: {
|
||||
'prettier/prettier': 'error',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/array-type': [
|
||||
'warn',
|
||||
{
|
||||
default: 'array-simple',
|
||||
},
|
||||
],
|
||||
'import/order': 'warn',
|
||||
// you must disable the base rule as it can report incorrect errors
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': ['error'],
|
||||
|
||||
'react/prop-types': 'off',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
// Not necessary in React 17
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
{
|
||||
patterns: [
|
||||
{
|
||||
/**
|
||||
* This library is gigantic and named imports end up slowing down builds/blowing out bundle sizes,
|
||||
* so this prevents that style of import.
|
||||
*/
|
||||
group: ['mdi-material-ui', '!mdi-material-ui/'],
|
||||
message: `
|
||||
Please use the default import from the icon file directly rather than using a named import.
|
||||
|
||||
Good:
|
||||
import IconName from 'mdi-material-ui/IconName';
|
||||
|
||||
Bad:
|
||||
import { IconName } from 'mdi-material-ui';
|
||||
`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
ignorePatterns: ['**/dist'],
|
||||
};
|
||||
4
ui/react-app/.gitignore
vendored
4
ui/react-app/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
node_modules/
|
||||
|
||||
dist/*
|
||||
!dist/*.gz
|
||||
@@ -1,2 +0,0 @@
|
||||
# Build output
|
||||
dist/
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
BIN
ui/react-app/dist/959.js.gz
vendored
BIN
ui/react-app/dist/959.js.gz
vendored
Binary file not shown.
BIN
ui/react-app/dist/959.js.map.gz
vendored
BIN
ui/react-app/dist/959.js.map.gz
vendored
Binary file not shown.
BIN
ui/react-app/dist/97.js.gz
vendored
BIN
ui/react-app/dist/97.js.gz
vendored
Binary file not shown.
BIN
ui/react-app/dist/97.js.map.gz
vendored
BIN
ui/react-app/dist/97.js.map.gz
vendored
Binary file not shown.
BIN
ui/react-app/dist/index.html.gz
vendored
BIN
ui/react-app/dist/index.html.gz
vendored
Binary file not shown.
BIN
ui/react-app/dist/main.js.gz
vendored
BIN
ui/react-app/dist/main.js.gz
vendored
Binary file not shown.
BIN
ui/react-app/dist/main.js.map.gz
vendored
BIN
ui/react-app/dist/main.js.map.gz
vendored
Binary file not shown.
@@ -1,21 +0,0 @@
|
||||
// Copyright 2023 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// DO NOT EDIT: This file was autogenerated by `scripts/compress_assets.sh`.
|
||||
|
||||
package reactapp
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed dist/959.js.gz dist/959.js.map.gz dist/97.js.gz dist/97.js.map.gz dist/index.html.gz dist/main.js.gz dist/main.js.map.gz
|
||||
var embedFS embed.FS
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2023 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// DO NOT EDIT: This file was autogenerated by `scripts/compress_assets.sh`.
|
||||
|
||||
package reactapp
|
||||
|
||||
import "embed"
|
||||
|
||||
16307
ui/react-app/package-lock.json
generated
16307
ui/react-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"name": "@prometheus-io/alertmanager",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"clean": "rimraf dist/",
|
||||
"start": "webpack serve --config webpack.dev.ts",
|
||||
"build": "webpack --config webpack.prod.ts",
|
||||
"lint": "eslint src --ext .ts,.tsx",
|
||||
"lint:fix": "eslint --fix src --ext .ts,.tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.9.3",
|
||||
"@mui/material": "^5.10.14",
|
||||
"@tanstack/react-query": "^4.7.1",
|
||||
"mdi-material-ui": "^7.9.3",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"use-query-params": "^2.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.51",
|
||||
"@types/react-dom": "^18.2.19",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.7",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"dotenv-defaults": "^5.0.2",
|
||||
"esbuild-loader": "^2.20.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^7.0.0",
|
||||
"eslint-webpack-plugin": "^4.2.0",
|
||||
"fork-ts-checker-webpack-plugin": "^9.0.2",
|
||||
"html-webpack-plugin": "^5.6.4",
|
||||
"style-loader": "^4.0.0",
|
||||
"ts-loader": "^9.5.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.8.2",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-bundle-analyzer": "^4.10.2",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack-dev-server": "^5.2.0",
|
||||
"webpack-merge": "^6.0.1"
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Box, styled } from '@mui/material';
|
||||
import Navbar from './components/navbar';
|
||||
import Router from './Router';
|
||||
|
||||
// Based on the MUI doc: https://mui.com/material-ui/react-app-bar/#fixed-placement
|
||||
const Offset = styled('div')(({ theme }) => theme.mixins.toolbar);
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<Navbar />
|
||||
<Offset />
|
||||
<Box
|
||||
sx={{
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
<Router />
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,17 +0,0 @@
|
||||
// Other routes are lazy-loaded for code-splitting
|
||||
import { Suspense, lazy } from 'react';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
|
||||
const ViewStatus = lazy(() => import('./views/ViewStatus'));
|
||||
|
||||
function Router() {
|
||||
return (
|
||||
<Suspense>
|
||||
<Routes>
|
||||
<Route path="/react-app/status" element={<ViewStatus />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default Router;
|
||||
@@ -1,41 +0,0 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import buildURL from '../utils/url-builder';
|
||||
import { fetchJson } from '../utils/fetch';
|
||||
|
||||
const resource = 'status';
|
||||
|
||||
export interface AMStatusClusterPeersInfo {
|
||||
address: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface AMStatusClusterInfo {
|
||||
name: string;
|
||||
peers: AMStatusClusterPeersInfo[];
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface AMStatusVersionInfo {
|
||||
branch: string;
|
||||
buildDate: string;
|
||||
buildUser: string;
|
||||
goVersion: string;
|
||||
revision: string;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export interface AMStatus {
|
||||
cluster: AMStatusClusterInfo;
|
||||
uptime: string;
|
||||
versionInfo: AMStatusVersionInfo;
|
||||
config: {
|
||||
original: string;
|
||||
};
|
||||
}
|
||||
|
||||
export function useAMStatus() {
|
||||
return useQuery<AMStatus, Error>([], () => {
|
||||
const url = buildURL({ resource: resource });
|
||||
return fetchJson<AMStatus>(url);
|
||||
});
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { AppBar, Box, Button, Stack, Toolbar, Typography } from '@mui/material';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
export default function Navbar(): JSX.Element {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
return (
|
||||
<AppBar position={'fixed'} elevation={1}>
|
||||
<Toolbar
|
||||
sx={{
|
||||
backgroundColor: 'aliceblue',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'row' }} flexGrow={1}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate('/react-app');
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={(theme) => ({
|
||||
marginRight: '1rem',
|
||||
color: theme.palette.common.black,
|
||||
})}
|
||||
>
|
||||
AlertManager
|
||||
</Typography>
|
||||
</Button>
|
||||
<Button variant="text">Alerts</Button>
|
||||
<Button variant="text">Silences</Button>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={() => {
|
||||
navigate('/react-app/status');
|
||||
}}
|
||||
disabled={location.pathname === '/react-app/status'}
|
||||
>
|
||||
Status
|
||||
</Button>
|
||||
<Button variant="text">Settings</Button>
|
||||
<Button variant="text" target="_blank" href="https://prometheus.io/docs/alerting/latest/alertmanager/">
|
||||
Help
|
||||
</Button>
|
||||
</Box>
|
||||
<Stack direction={'row'} alignItems={'center'}>
|
||||
<Button variant="outlined">New Silence</Button>
|
||||
</Stack>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta name="theme-color" content="#000000"/>
|
||||
<meta name="description" content="AlertManager"/>
|
||||
<title>AlertManager</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,39 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { QueryParamProvider } from 'use-query-params';
|
||||
import { ReactRouter6Adapter } from 'use-query-params/adapters/react-router-6';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
|
||||
function renderApp(container: Element | null) {
|
||||
if (container === null) {
|
||||
return;
|
||||
}
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnWindowFocus: false,
|
||||
// react-query uses a default of 3 retries.
|
||||
// This sets the default to 0 retries.
|
||||
// If needed, the number of retries can be overridden in individual useQuery calls.
|
||||
retry: 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const root = ReactDOM.createRoot(container);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<QueryParamProvider adapter={ReactRouter6Adapter}>
|
||||
<App />
|
||||
</QueryParamProvider>
|
||||
</QueryClientProvider>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
|
||||
renderApp(document.getElementById('root'));
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Calls `global.fetch`, but throws a `FetchError` for non-200 responses.
|
||||
*/
|
||||
export async function fetch(...args: Parameters<typeof global.fetch>) {
|
||||
const response = await global.fetch(...args);
|
||||
if (!response.ok) {
|
||||
throw new FetchError(response);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls `global.fetch` and throws a `FetchError` on non-200 responses, but also
|
||||
* decodes the response body as JSON, casting it to type `T`. Returns the
|
||||
* decoded body.
|
||||
*/
|
||||
export async function fetchJson<T>(...args: Parameters<typeof global.fetch>) {
|
||||
const response = await fetch(...args);
|
||||
const json: T = await response.json();
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error thrown when fetch returns a non-200 response.
|
||||
*/
|
||||
export class FetchError extends Error {
|
||||
constructor(readonly response: Response) {
|
||||
super(`${response.status} ${response.statusText}`);
|
||||
Object.setPrototypeOf(this, FetchError.prototype);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
const API_PREFIX = '/api/v2';
|
||||
|
||||
export type URLParams = {
|
||||
resource: string;
|
||||
queryParams?: URLSearchParams;
|
||||
apiPrefix?: string;
|
||||
};
|
||||
|
||||
export default function buildURL({ apiPrefix = API_PREFIX, resource, queryParams }: URLParams): string {
|
||||
let url = `${apiPrefix}/${resource}`;
|
||||
if (queryParams !== undefined) {
|
||||
url = `${url}?${queryParams.toString()}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import {
|
||||
Chip,
|
||||
Container,
|
||||
List,
|
||||
ListItem,
|
||||
SxProps,
|
||||
Table,
|
||||
TableCell,
|
||||
tableCellClasses,
|
||||
TableContainer,
|
||||
TableRow,
|
||||
TextareaAutosize,
|
||||
Theme,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { useAMStatus } from '../client/am-client';
|
||||
|
||||
const tableStyle: SxProps<Theme> = {
|
||||
[`& .${tableCellClasses.root}`]: {
|
||||
borderBottom: 'none',
|
||||
},
|
||||
};
|
||||
|
||||
const tableHeaderStyle: SxProps<Theme> = {
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
|
||||
interface tableCellProperties {
|
||||
header: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
function CustomTableCell(props: tableCellProperties) {
|
||||
const { header, content } = props;
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell variant="head" sx={tableHeaderStyle}>
|
||||
{header}
|
||||
</TableCell>
|
||||
<TableCell>{content}</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ViewStatus() {
|
||||
const { data } = useAMStatus();
|
||||
if (data === undefined || data === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxWidth="md">
|
||||
<Typography variant="h4">Status</Typography>
|
||||
<TableContainer>
|
||||
<Table size="small" sx={tableStyle}>
|
||||
<CustomTableCell header="Uptime" content={data.uptime} />
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Typography variant="h4">Cluster Status</Typography>
|
||||
<Table size="small" sx={tableStyle}>
|
||||
<CustomTableCell header="Name" content={data.cluster.name} />
|
||||
<TableRow>
|
||||
<TableCell variant="head" sx={tableHeaderStyle}>
|
||||
Status
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Chip color={data.cluster.status === 'ready' ? 'success' : 'error'} label={data.cluster.status} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell variant="head" sx={tableHeaderStyle}>
|
||||
Peers
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<List>
|
||||
{data.cluster.peers.map((peer, i) => {
|
||||
return (
|
||||
<ListItem disablePadding sx={{ display: 'list-item' }} key={i}>
|
||||
<p>
|
||||
Name: {peer.name}
|
||||
<br />
|
||||
Address: {peer.address}
|
||||
</p>
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Table>
|
||||
<Typography variant="h4">Version Information</Typography>
|
||||
<TableContainer>
|
||||
<Table size="small" sx={tableStyle}>
|
||||
<CustomTableCell header="Branch" content={data.versionInfo.branch} />
|
||||
<CustomTableCell header="Build Date" content={data.versionInfo.buildDate} />
|
||||
<CustomTableCell header="Build User" content={data.versionInfo.buildUser} />
|
||||
<CustomTableCell header="Go Version" content={data.versionInfo.goVersion} />
|
||||
<CustomTableCell header="Revision" content={data.versionInfo.revision} />
|
||||
<CustomTableCell header="Version" content={data.versionInfo.version} />
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Typography variant="h4">Config</Typography>
|
||||
<TextareaAutosize
|
||||
readOnly
|
||||
aria-multiline
|
||||
value={data.config.original}
|
||||
style={{ width: '100%', backgroundColor: 'lightgrey' }}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Base config for all typescript packages
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2018",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"module": "esnext",
|
||||
"jsx": "react-jsx",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"pretty": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src"],
|
||||
// For builds that use ts-node to compile the configs (e.g. webpack, jest)
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright 2023 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package reactapp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/common/assets"
|
||||
)
|
||||
|
||||
var Assets = http.FS(assets.New(embedFS))
|
||||
@@ -1,63 +0,0 @@
|
||||
// Copyright 2023 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package reactapp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
"github.com/prometheus/common/route"
|
||||
"github.com/prometheus/common/server"
|
||||
)
|
||||
|
||||
var reactRouterPaths = []string{
|
||||
"/",
|
||||
"/status",
|
||||
}
|
||||
|
||||
func Register(r *route.Router, logger *slog.Logger) {
|
||||
serveReactApp := func(w http.ResponseWriter, r *http.Request) {
|
||||
f, err := Assets.Open("/dist/index.html")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "Error opening React index.html: %v", err)
|
||||
return
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
idx, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "Error reading React index.html: %v", err)
|
||||
return
|
||||
}
|
||||
w.Write(idx)
|
||||
}
|
||||
|
||||
// Static files required by the React app.
|
||||
r.Get("/react-app/*filepath", func(w http.ResponseWriter, r *http.Request) {
|
||||
for _, rt := range reactRouterPaths {
|
||||
if r.URL.Path != "/react-app"+rt {
|
||||
continue
|
||||
}
|
||||
serveReactApp(w, r)
|
||||
return
|
||||
}
|
||||
r.URL.Path = path.Join("/dist", route.Param(r.Context(), "filepath"))
|
||||
fs := server.StaticFileServer(Assets)
|
||||
fs.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
// Copyright 2023 The Perses Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import path from 'path';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import { Configuration } from 'webpack';
|
||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
|
||||
import ESLintWebpackPlugin from 'eslint-webpack-plugin';
|
||||
|
||||
export const commonConfig: Configuration = {
|
||||
entry: path.resolve(__dirname, './src/index.tsx'),
|
||||
output: {
|
||||
path: path.resolve(__dirname, './dist'),
|
||||
publicPath: '/',
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', 'jsx', '.json'],
|
||||
},
|
||||
plugins: [
|
||||
// Generates HTML index page with bundle injected
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.resolve(__dirname, './src/index.html'),
|
||||
templateParameters: {},
|
||||
}),
|
||||
// Does TS type-checking in a separate process
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: {
|
||||
configFile: path.resolve(__dirname, './tsconfig.json'),
|
||||
},
|
||||
}),
|
||||
new ESLintWebpackPlugin({
|
||||
threads: true,
|
||||
files: '../*/src/**/*.{ts,tsx,js,jsx}',
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
// Type-checking happens in separate plugin process
|
||||
transpileOnly: true,
|
||||
projectReferences: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ['style-loader', 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|woff|woff2)$/,
|
||||
type: 'asset/resource',
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif)$/,
|
||||
type: 'asset',
|
||||
},
|
||||
// SVG as React components
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
{
|
||||
loader: '@svgr/webpack',
|
||||
options: {
|
||||
// Generated React components will support a 'title' prop to render
|
||||
// a <title> inside the <svg>
|
||||
titleProp: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -1,78 +0,0 @@
|
||||
// Copyright 2023 The Perses Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import fs from 'fs';
|
||||
import { Configuration } from 'webpack';
|
||||
import { Configuration as DevServerConfig, ServerConfiguration } from 'webpack-dev-server';
|
||||
import { merge } from 'webpack-merge';
|
||||
import { commonConfig } from './webpack.common';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('dotenv-defaults').config();
|
||||
|
||||
declare module 'webpack' {
|
||||
interface Configuration {
|
||||
devServer?: DevServerConfig | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Get dev server HTTP options (note: HTTP2 is not currently supported by webpack since we're on Node 16)
|
||||
function getServerConfig(): ServerConfiguration | undefined {
|
||||
// Just use regular HTTP by default
|
||||
if (process.env.HTTPS !== 'true') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Support the same HTTPS options as Creact React App if HTTPS is set
|
||||
if (process.env.SSL_KEY_FILE === undefined || process.env.SSL_CRT_FILE === undefined) {
|
||||
// Use the default self-signed cert
|
||||
return { type: 'https' };
|
||||
}
|
||||
|
||||
// Use a custom cert
|
||||
return {
|
||||
type: 'https',
|
||||
options: {
|
||||
key: fs.readFileSync(process.env.SSL_KEY_FILE),
|
||||
cert: fs.readFileSync(process.env.SSL_CRT_FILE),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Webpack configuration in dev
|
||||
const devConfig: Configuration = {
|
||||
mode: 'development',
|
||||
devtool: 'cheap-module-source-map',
|
||||
|
||||
output: {
|
||||
pathinfo: true,
|
||||
},
|
||||
|
||||
watchOptions: {
|
||||
aggregateTimeout: 300,
|
||||
},
|
||||
|
||||
devServer: {
|
||||
port: parseInt(process.env.PORT ?? '3000'),
|
||||
open: true,
|
||||
server: getServerConfig(),
|
||||
historyApiFallback: true,
|
||||
allowedHosts: 'all',
|
||||
proxy: {
|
||||
'/api': 'http://localhost:9093',
|
||||
},
|
||||
},
|
||||
cache: true,
|
||||
};
|
||||
|
||||
const merged = merge(commonConfig, devConfig);
|
||||
export default merged;
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright 2023 The Perses Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Configuration } from 'webpack';
|
||||
import { merge } from 'webpack-merge';
|
||||
import { ESBuildMinifyPlugin } from 'esbuild-loader';
|
||||
import { commonConfig } from './webpack.common';
|
||||
import path from 'path';
|
||||
|
||||
const prodConfig: Configuration = {
|
||||
output: {
|
||||
path: path.resolve(__dirname, './dist'),
|
||||
publicPath: '/react-app/',
|
||||
},
|
||||
mode: 'production',
|
||||
bail: true,
|
||||
devtool: 'source-map',
|
||||
optimization: {
|
||||
// TODO: Could this also be replaced with swc minifier?
|
||||
minimizer: [new ESBuildMinifyPlugin({ target: 'es2018' })],
|
||||
},
|
||||
};
|
||||
|
||||
const merged = merge(commonConfig, prodConfig);
|
||||
export default merged;
|
||||
Reference in New Issue
Block a user