Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
silvareal committed Nov 5, 2022
1 parent 93d1194 commit 3d5724e
Show file tree
Hide file tree
Showing 11 changed files with 362 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"cSpell.words": [
"Uninstantiated"
]
}
1 change: 1 addition & 0 deletions web/src/assets/svg/server-outlined.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions web/src/assets/svg/server.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions web/src/common/ErrorContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from "react";
import { Typography } from "@mui/material";
import clsx from "clsx";
import SentimentVeryDissatisfiedIcon from "@mui/icons-material/SentimentVeryDissatisfied";

interface ErrorContentType {
title: string;
description: string;
className?: string;
onTryAgain?: () => void;
}

/**
*
* @param {ErrorContentProps} props
*/

function ErrorContent(props: ErrorContentType): JSX.Element {
const { title, description, className, onTryAgain, ...rest } = props;

return (
<div
className={clsx(
"p-1 d-flex text-danger justify-content-center align-items-center flex-column w-100",
className
)}
{...rest}
>
<Typography variant="h5" className="font-bold text-center">
{title}
</Typography>
<div>
<SentimentVeryDissatisfiedIcon fontSize="large" />
</div>
<Typography variant="body2" className="text-center mb-4 font-bold w-100">
{description}
</Typography>
</div>
);
}

ErrorContent.defaultProps = {
title: "Something went wrong",
description: "We're quite sorry about this!",
};

export default ErrorContent;

/**
* @typedef {{
* onTryAgain: Function
* } & import("@mui/material").PaperProps} ErrorContentProps
*/
54 changes: 54 additions & 0 deletions web/src/common/ErrorDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from "react";
import {
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
DialogActions,
Button,
} from "@mui/material";

interface ErrorDialogProps {
title?: string;
description?: string;
onRetry?: () => void;
retryText?: string;
}
/**
*
* @param {ErrorDialogProps} props
*/
export function ErrorDialog(props: ErrorDialogProps) {
const { title, description, onRetry, retryText, ...rest } = props;
function handleRetry(e: any) {
e.stopPropagation();
if (onRetry) {
onRetry();
}
}

return (
<Dialog open={true} fullWidth {...rest}>
<DialogTitle>{title}</DialogTitle>
<DialogContent>
<DialogContentText>{description}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleRetry}>{retryText}</Button>
</DialogActions>
</Dialog>
);
}

ErrorDialog.defaultProps = {
title: "Something went wrong",
description:
"Sorry, something went wrong, Please try again later or contact our support.",
retryText: "Try Again",
};

export default ErrorDialog;

/**
* @typedef {import("./ErrorDialogContext").ErrorOptions & import("@material-ui/core").DialogProps} ErrorDialogProps
*/
98 changes: 98 additions & 0 deletions web/src/common/LoadingContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { FC, ReactNode, useEffect } from "react";
import useDataRef from "hooks/useDataRef";
import LoadingIndicator from "./LoadingIndicator";
import ErrorContent from "common/ErrorContent";
import { Box } from "@mui/material";

interface LoadingContentType {
size: number;
error: boolean;
loading: boolean;
children: JSX.Element | (() => JSX.Element);
onReload: () => void;
onMount: () => void;
loadingContent: JSX.Element | ((x: JSX.Element) => ReactNode);
errorContent: JSX.Element | ((x: JSX.Element) => ReactNode);
className: string;
}
/**
*
* @param {LoadingContentProps} props
*/
function LoadingContent(props: Partial<LoadingContentType>): JSX.Element {
const {
size,
error,
loading,
children,
onReload,
onMount,
loadingContent,
errorContent,
className,
...rest
} = props;

const dataRef = useDataRef({ onReload, onMount });

useEffect(() => {
dataRef.current.onMount?.();
}, [dataRef]);

if (!loading && !error) {
if (children !== undefined) {
return typeof children === "function" ? children() : children;
}
}

const defaultLoadingContent = <LoadingIndicator size={size} />;

const defaultErrorContent = <ErrorContent onTryAgain={() => onReload?.()} />;

return (
<Box
display={"flex"}
justifyContent={"center"}
alignItems={"center"}
p={2}
{...rest}
>
{error ? (
<>
{errorContent
? typeof errorContent === "function"
? errorContent(defaultErrorContent)
: errorContent
: defaultErrorContent}
</>
) : loadingContent ? (
typeof loadingContent === "function" ? (
loadingContent(defaultLoadingContent)
) : (
loadingContent
)
) : (
defaultLoadingContent
)}
</Box>
);
}

LoadingContent.defaultProps = {
size: 40,
children: null,
};

export default LoadingContent;

/**
* @typedef {{
* size: string | number,
* onMount: Function,
* onReload: Function,
* error: boolean,
* loading: boolean,
* errorContent: React.ReactNode,
* loadingContent: React.ReactNode,
* } & React.ComponentPropsWithoutRef<'div'>} LoadingContentProps
*/
12 changes: 12 additions & 0 deletions web/src/common/LoadingIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { CircularProgress } from "@mui/material";
import React from "react";

/**
*
* @param {import("@mui/material").CircularProgressProps} props
*/
function LoadingIndicator(props: { [rest: string]: any }) {
return <CircularProgress {...props}></CircularProgress>;
}

export default LoadingIndicator;
13 changes: 13 additions & 0 deletions web/src/hooks/useDataRef.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useRef } from "react";

/**
* @template T
* @param {T} data
*/
function useDataRef(data: any) {
const ref = useRef(data);
ref.current = data;
return ref;
}

export default useDataRef;
61 changes: 56 additions & 5 deletions web/src/server/ServerList.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,78 @@
import React from "react";
import { Card, CardActionArea, Grid, Typography } from "@mui/material";
import { Box, Container } from "@mui/system";
import React, { useState } from "react";
import useWebSocket, { ReadyState } from "react-use-websocket";
import { ReactComponent as ServerIcon } from "../assets/svg/server.svg";
import LoadingContent from "../common/LoadingContent";
import ThemeConfig from "../ThemeConfig";
import { ServerResponse } from "./ServerType";

export default function ServerList() {
const [servers, setServers] = useState<ServerResponse[]>([]);
const { sendJsonMessage, getWebSocket, readyState } = useWebSocket(
`ws://localhost:3000/metrics`,
{
onOpen: () => console.log("WebSocket connection opened."),
onClose: () => console.log("WebSocket connection closed."),
shouldReconnect: (closeEvent) => true,
onMessage: (event: WebSocketEventMap["message"]) =>
console.log("new Data", event.data),
onMessage: (event: WebSocketEventMap["message"]) => {
const newMessage: ServerResponse = JSON.parse(event.data);
setServers((prev: ServerResponse[]) => {
if (!newMessage.Error) {
return prev.concat(newMessage);
}
});
},
}
);
getWebSocket();

const connectionStatus = {
const connectionStatus: string = {
[ReadyState.CONNECTING]: "Connecting",
[ReadyState.OPEN]: "Open",
[ReadyState.CLOSING]: "Closing",
[ReadyState.CLOSED]: "Closed",
[ReadyState.UNINSTANTIATED]: "Uninstantiated",
}[readyState];

console.log(servers);
// console.log("getWebsocket", getWebSocket()?.OPEN);
return <div>ServerList</div>;
return (
<Container>
<LoadingContent
loading={connectionStatus === "Connecting"}
error={connectionStatus === "Closed"}
>
<Grid container spacing={2} my={10}>
{servers.map((server: any, index: number) => (
<Grid item xs={6} md={4}>
<Card key={index}>
<CardActionArea>
<Box
display={"flex"}
justifyContent="center"
alignItems="center"
flexDirection="column"
>
<ServerIcon width={"100px"} />
<Typography
textTransform={"capitalize"}
mb={2}
noWrap
fontWeight={600}
>
localhost -{" "}
<span style={{ color: ThemeConfig.palette.success.dark }}>
linux
</span>
</Typography>
</Box>
</CardActionArea>
</Card>
</Grid>
))}
</Grid>
</LoadingContent>
</Container>
);
}
16 changes: 16 additions & 0 deletions web/src/server/ServerType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface ServerResponse {
Error: boolean;
Message: {
Host: string;
Name:
| "disk"
| "docker"
| "uptime"
| "memory"
| "process"
| "loadavg"
| "tcp";
Platform: string;
Data: Object;
};
}
Loading

0 comments on commit 3d5724e

Please sign in to comment.