Polish admin styles

This commit is contained in:
David Stotijn
2020-09-23 18:10:32 +02:00
parent a3c22b7f1f
commit e9367f7186
16 changed files with 178 additions and 97 deletions

View File

@ -12,6 +12,7 @@
"@apollo/client": "^3.2.0", "@apollo/client": "^3.2.0",
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1", "@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.56",
"graphql": "^15.3.0", "graphql": "^15.3.0",
"next": "^9.5.3", "next": "^9.5.3",
"react": "^16.13.1", "react": "^16.13.1",

View File

@ -0,0 +1,25 @@
import { Paper } from "@material-ui/core";
function CenteredPaper({
children,
}: {
children: React.ReactNode;
}): JSX.Element {
return (
<div>
<Paper
elevation={0}
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
padding: 36,
}}
>
{children}
</Paper>
</div>
);
}
export default CenteredPaper;

View File

@ -86,7 +86,7 @@ const useStyles = makeStyles((theme: Theme) =>
}, },
content: { content: {
flexGrow: 1, flexGrow: 1,
padding: theme.spacing(2), padding: theme.spacing(3),
}, },
listItem: { listItem: {
paddingLeft: 16, paddingLeft: 16,
@ -136,7 +136,7 @@ export function Layout(props: { children: React.ReactNode }): JSX.Element {
<MenuIcon /> <MenuIcon />
</IconButton> </IconButton>
<Typography variant="h5" noWrap> <Typography variant="h5" noWrap>
Hetty <span style={{ marginRight: 12 }}>🧑🔧</span>Hetty
</Typography> </Typography>
</Toolbar> </Toolbar>
</AppBar> </AppBar>

View File

@ -1,4 +1,4 @@
import { teal, orange, red } from "@material-ui/core/colors"; import { green, orange, red } from "@material-ui/core/colors";
import FiberManualRecordIcon from "@material-ui/icons/FiberManualRecord"; import FiberManualRecordIcon from "@material-ui/icons/FiberManualRecord";
function HttpStatusIcon({ status }: { status: number }): JSX.Element { function HttpStatusIcon({ status }: { status: number }): JSX.Element {
@ -6,7 +6,7 @@ function HttpStatusIcon({ status }: { status: number }): JSX.Element {
switch (Math.floor(status / 100)) { switch (Math.floor(status / 100)) {
case 2: case 2:
case 3: case 3:
return <FiberManualRecordIcon style={{ ...style, color: teal[400] }} />; return <FiberManualRecordIcon style={{ ...style, color: green[600] }} />;
case 4: case 4:
return <FiberManualRecordIcon style={{ ...style, color: orange[400] }} />; return <FiberManualRecordIcon style={{ ...style, color: orange[400] }} />;
case 5: case 5:

View File

@ -1,8 +1,9 @@
import { gql, useQuery } from "@apollo/client"; import { gql, useQuery } from "@apollo/client";
import { Box, Grid, Paper } from "@material-ui/core"; import { Box, Grid, Paper, CircularProgress } from "@material-ui/core";
import ResponseDetail from "./ResponseDetail"; import ResponseDetail from "./ResponseDetail";
import RequestDetail from "./RequestDetail"; import RequestDetail from "./RequestDetail";
import Alert from "@material-ui/lab/Alert";
const HTTP_REQUEST_LOG = gql` const HTTP_REQUEST_LOG = gql`
query HttpRequestLog($id: ID!) { query HttpRequestLog($id: ID!) {
@ -31,8 +32,16 @@ function LogDetail({ requestId: id }: Props): JSX.Element {
variables: { id }, variables: { id },
}); });
if (loading) return <div>"Loading..."</div>; if (loading) {
if (error) return <div>`Error: ${error.message}`</div>; return <CircularProgress />;
}
if (error) {
return (
<Alert severity="error">
Error fetching logs details: {error.message}
</Alert>
);
}
const { method, url, proto, body, response } = data.httpRequestLog; const { method, url, proto, body, response } = data.httpRequestLog;
@ -40,13 +49,13 @@ function LogDetail({ requestId: id }: Props): JSX.Element {
<div> <div>
<Grid container item spacing={2}> <Grid container item spacing={2}>
<Grid item xs={6}> <Grid item xs={6}>
<Box component={Paper} maxHeight="60vh" overflow="scroll"> <Box component={Paper} maxHeight="62vh" overflow="scroll">
<RequestDetail request={{ method, url, proto, body }} /> <RequestDetail request={{ method, url, proto, body }} />
</Box> </Box>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
{response && ( {response && (
<Box component={Paper} maxHeight="65vh" overflow="scroll"> <Box component={Paper} maxHeight="62vh" overflow="scroll">
<ResponseDetail response={response} /> <ResponseDetail response={response} />
</Box> </Box>
)} )}

View File

@ -1,37 +1,56 @@
import { gql, useQuery } from "@apollo/client";
import { useState } from "react"; import { useState } from "react";
import { Box, Paper, Container, Typography } from "@material-ui/core"; import { Box, Typography, CircularProgress } from "@material-ui/core";
import Alert from "@material-ui/lab/Alert";
import RequestList from "./RequestList"; import RequestList from "./RequestList";
import LogDetail from "./LogDetail"; import LogDetail from "./LogDetail";
import CenteredPaper from "../CenteredPaper";
const HTTP_REQUEST_LOGS = gql`
query HttpRequestLogs {
httpRequestLogs {
id
method
url
timestamp
response {
status
statusCode
}
}
}
`;
function LogsOverview(): JSX.Element { function LogsOverview(): JSX.Element {
const [detailReqLogId, setDetailReqLogId] = useState<string | null>(null); const { loading, error, data } = useQuery(HTTP_REQUEST_LOGS);
const [detailReqLogId, setDetailReqLogId] = useState<string | null>(null);
const handleLogClick = (reqId: string) => setDetailReqLogId(reqId); const handleLogClick = (reqId: string) => setDetailReqLogId(reqId);
if (loading) {
return <CircularProgress />;
}
if (error) {
return <Alert severity="error">Error fetching logs: {error.message}</Alert>;
}
const { httpRequestLogs: logs } = data;
return ( return (
<Box style={{ padding: 8 }}> <div>
<Box mb={2}> <Box mb={2}>
<RequestList onLogClick={handleLogClick} /> <RequestList logs={logs} onLogClick={handleLogClick} />
</Box> </Box>
<Box> <Box>
{detailReqLogId ? ( {detailReqLogId && <LogDetail requestId={detailReqLogId} />}
<LogDetail requestId={detailReqLogId} /> {logs.length !== 0 && !detailReqLogId && (
) : ( <CenteredPaper>
<Paper
elevation={0}
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "60vh",
}}
>
<Typography>Select a log entry</Typography> <Typography>Select a log entry</Typography>
</Paper> </CenteredPaper>
)} )}
</Box> </Box>
</Box> </div>
); );
} }

View File

@ -1,6 +1,6 @@
import { Typography, Box } from "@material-ui/core"; import { Typography, Box } from "@material-ui/core";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { materialLight } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { vscDarkPlus } from "react-syntax-highlighter/dist/cjs/styles/prism";
interface Props { interface Props {
request: { request: {
@ -15,7 +15,6 @@ function RequestDetail({ request }: Props): JSX.Element {
const { method, url, proto, body } = request; const { method, url, proto, body } = request;
const parsedUrl = new URL(url); const parsedUrl = new URL(url);
console.log(parsedUrl);
return ( return (
<div> <div>
@ -24,18 +23,18 @@ function RequestDetail({ request }: Props): JSX.Element {
variant="h6" variant="h6"
style={{ fontSize: "1rem", whiteSpace: "nowrap" }} style={{ fontSize: "1rem", whiteSpace: "nowrap" }}
> >
{request.method}{" "} {method} {decodeURIComponent(parsedUrl.pathname + parsedUrl.search)}{" "}
{decodeURIComponent(parsedUrl.pathname + parsedUrl.search)} {proto} {proto}
</Typography> </Typography>
</Box> </Box>
<Box> <Box>
{request.body && ( {body && (
<SyntaxHighlighter <SyntaxHighlighter
language="markup" language="markup"
showLineNumbers={true} showLineNumbers={true}
style={materialLight} style={vscDarkPlus}
> >
{request.body} {body}
</SyntaxHighlighter> </SyntaxHighlighter>
)} )}
</Box> </Box>

View File

@ -1,4 +1,3 @@
import { gql, useQuery } from "@apollo/client";
import { import {
TableContainer, TableContainer,
Paper, Paper,
@ -7,42 +6,50 @@ import {
TableRow, TableRow,
TableCell, TableCell,
TableBody, TableBody,
CircularProgress,
Typography, Typography,
Box,
} from "@material-ui/core"; } from "@material-ui/core";
import HttpStatusIcon from "./HttpStatusCode"; import HttpStatusIcon from "./HttpStatusCode";
import CenteredPaper from "../CenteredPaper";
const HTTP_REQUEST_LOGS = gql`
query HttpRequestLogs {
httpRequestLogs {
id
method
url
timestamp
response {
status
statusCode
}
}
}
`;
interface Props { interface Props {
logs: Array<any>;
onLogClick(requestId: string): void; onLogClick(requestId: string): void;
} }
function RequestList({ onLogClick }: Props): JSX.Element { function RequestList({ logs, onLogClick }: Props): JSX.Element {
const { loading, error, data } = useQuery(HTTP_REQUEST_LOGS); return (
<div>
<RequestListTable onLogClick={onLogClick} logs={logs} />
{logs.length === 0 && (
<Box my={1}>
<CenteredPaper>
<Typography>No logs found.</Typography>
</CenteredPaper>
</Box>
)}
</div>
);
}
if (loading) return <div>"Loading..."</div>; interface RequestListTableProps {
if (error) return <div>`Error: ${error.message}`</div>; logs?: any;
onLogClick(requestId: string): void;
const { httpRequestLogs: logs } = data; }
function RequestListTable({
logs,
onLogClick,
}: RequestListTableProps): JSX.Element {
return ( return (
<TableContainer <TableContainer
component={Paper} component={Paper}
style={{ minHeight: 200, height: "24vh" }} style={{
minHeight: logs.length ? 200 : 0,
height: logs.length ? "24vh" : "inherit",
}}
> >
<Table stickyHeader size="small"> <Table stickyHeader size="small">
<TableHead> <TableHead>

View File

@ -1,6 +1,6 @@
import { Typography, Box } from "@material-ui/core"; import { Typography, Box } from "@material-ui/core";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { materialLight } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { vscDarkPlus } from "react-syntax-highlighter/dist/cjs/styles/prism";
import HttpStatusIcon from "./HttpStatusCode"; import HttpStatusIcon from "./HttpStatusCode";
@ -26,11 +26,12 @@ function ResponseDetail({ response }: Props): JSX.Element {
</Typography> </Typography>
</Box> </Box>
<Box> <Box>
{response.body && (
<SyntaxHighlighter <SyntaxHighlighter
language="markup" language="markup"
showLineNumbers={true} showLineNumbers={true}
showInlineLineNumbers={true} showInlineLineNumbers={true}
style={materialLight} style={vscDarkPlus}
lineProps={{ lineProps={{
style: { style: {
display: "block", display: "block",
@ -42,6 +43,7 @@ function ResponseDetail({ response }: Props): JSX.Element {
> >
{response.body} {response.body}
</SyntaxHighlighter> </SyntaxHighlighter>
)}
</Box> </Box>
</div> </div>
); );

View File

@ -8,7 +8,7 @@ function createApolloClient() {
return new ApolloClient({ return new ApolloClient({
ssrMode: typeof window === "undefined", ssrMode: typeof window === "undefined",
link: new HttpLink({ link: new HttpLink({
uri: "http://localhost:3000/api/graphql", uri: "/api/graphql",
}), }),
cache: new InMemoryCache({ cache: new InMemoryCache({
typePolicies: { typePolicies: {

View File

@ -1,11 +1,12 @@
import { createMuiTheme } from "@material-ui/core/styles"; import { createMuiTheme } from "@material-ui/core/styles";
import teal from "@material-ui/core/colors/teal"; import grey from "@material-ui/core/colors/grey";
import green from "@material-ui/core/colors/green"; import green from "@material-ui/core/colors/green";
const theme = createMuiTheme({ const theme = createMuiTheme({
palette: { palette: {
type: "dark",
primary: { primary: {
main: teal[500], main: grey[900],
}, },
secondary: { secondary: {
main: green[500], main: green[500],

View File

@ -1,9 +1,7 @@
import RequestList from "../components/reqlog/RequestList";
function Index(): JSX.Element { function Index(): JSX.Element {
return ( return (
<div> <div>
<h1>Hetty</h1> <h1>Hetty123</h1>
</div> </div>
); );
} }

View File

@ -0,0 +1,9 @@
function Index(): JSX.Element {
return (
<div>
<h1>Proxy123</h1>
</div>
);
}
export default Index;

View File

@ -1,17 +0,0 @@
import { useState } from "react";
import { Box } from "@material-ui/core";
import RequestList from "../../components/reqlog/RequestList";
import LogDetail from "../../components/reqlog/LogDetail";
import LogsOverview from "../../components/reqlog/LogsOverview";
import Layout from "../../components/Layout";
function Logs(): JSX.Element {
return (
<Layout>
<LogsOverview />
</Layout>
);
}
export default Logs;

View File

@ -0,0 +1,17 @@
import { Typography, Box } from "@material-ui/core";
import LogsOverview from "../../../components/reqlog/LogsOverview";
import Layout from "../../../components/Layout";
function ProxyLogs(): JSX.Element {
return (
<Layout>
<Box mb={2}>
<Typography variant="h5">Proxy logs</Typography>
</Box>
<LogsOverview />
</Layout>
);
}
export default ProxyLogs;

View File

@ -1085,6 +1085,17 @@
dependencies: dependencies:
"@babel/runtime" "^7.4.4" "@babel/runtime" "^7.4.4"
"@material-ui/lab@^4.0.0-alpha.56":
version "4.0.0-alpha.56"
resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz#ff63080949b55b40625e056bbda05e130d216d34"
integrity sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw==
dependencies:
"@babel/runtime" "^7.4.4"
"@material-ui/utils" "^4.10.2"
clsx "^1.0.4"
prop-types "^15.7.2"
react-is "^16.8.0"
"@material-ui/styles@^4.10.0": "@material-ui/styles@^4.10.0":
version "4.10.0" version "4.10.0"
resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.10.0.tgz#2406dc23aa358217aa8cc772e6237bd7f0544071" resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.10.0.tgz#2406dc23aa358217aa8cc772e6237bd7f0544071"