Skip to content

Commit

Permalink
Add headers to log details, add Monaco Editor
Browse files Browse the repository at this point in the history
  • Loading branch information
dstotijn committed Sep 23, 2020
1 parent e9367f7 commit 71de41e
Show file tree
Hide file tree
Showing 13 changed files with 944 additions and 74 deletions.
27 changes: 25 additions & 2 deletions admin/next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
module.exports = {
const withCSS = require("@zeit/next-css");
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");

module.exports = withCSS({
async rewrites() {
return [
{
Expand All @@ -7,4 +10,24 @@ module.exports = {
},
];
},
};
webpack: (config) => {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: "url-loader",
options: {
limit: 100000,
},
},
});

config.plugins.push(
new MonacoWebpackPlugin({
languages: ["html", "json", "javascript"],
filename: "static/[name].worker.js",
})
);

return config;
},
});
5 changes: 5 additions & 0 deletions admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.56",
"@zeit/next-css": "^1.0.1",
"graphql": "^15.3.0",
"monaco-editor": "^0.20.0",
"monaco-editor-webpack-plugin": "^1.9.0",
"next": "^9.5.3",
"next-fonts": "^1.0.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-monaco-editor": "^0.34.0",
"react-syntax-highlighter": "^13.5.3"
},
"devDependencies": {
Expand Down
55 changes: 55 additions & 0 deletions admin/src/components/reqlog/Editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import dynamic from "next/dynamic";
const MonacoEditor = dynamic(import("react-monaco-editor"), { ssr: false });

const monacoOptions = {
readOnly: true,
wordWrap: "on",
minimap: {
enabled: false,
},
};

type language = "html" | "typescript" | "json";

function editorDidMount() {
return (window.MonacoEnvironment.getWorkerUrl = (moduleId, label) => {
if (label === "json") return "/_next/static/json.worker.js";
if (label === "html") return "/_next/static/html.worker.js";
if (label === "javascript") return "/_next/static/ts.worker.js";

return "/_next/static/editor.worker.js";
});
}

function languageForContentType(contentType: string): language {
switch (contentType) {
case "text/html":
return "html";
case "application/json":
return "json";
case "application/javascript":
return "typescript";
default:
return;
}
}

interface Props {
content: string;
contentType: string;
}

function Editor({ content, contentType }: Props): JSX.Element {
return (
<MonacoEditor
height={"600px"}
language={languageForContentType(contentType)}
theme="vs-dark"
editorDidMount={editorDidMount}
options={monacoOptions as any}
value={content}
/>
);
}

export default Editor;
58 changes: 58 additions & 0 deletions admin/src/components/reqlog/HttpHeadersTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {
makeStyles,
Theme,
createStyles,
Table,
TableBody,
TableCell,
TableContainer,
TableRow,
} from "@material-ui/core";

const useStyles = makeStyles((theme: Theme) =>
createStyles({
table: {
tableLayout: "fixed",
width: "100%",
},
keyCell: {
verticalAlign: "top",
width: "30%",
fontWeight: "bold",
},
valueCell: {
width: "70%",
verticalAlign: "top",
wordBreak: "break-all",
whiteSpace: "pre-wrap",
},
})
);

interface Props {
headers: Array<{ key: string; value: string }>;
}

function HttpHeadersTable({ headers }: Props): JSX.Element {
const classes = useStyles();
return (
<TableContainer>
<Table className={classes.table} size="small">
<TableBody>
{headers.map(({ key, value }, index) => (
<TableRow key={index}>
<TableCell component="th" scope="row" className={classes.keyCell}>
<code>{key}</code>
</TableCell>
<TableCell className={classes.valueCell}>
<code>{value}</code>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}

export default HttpHeadersTable;
12 changes: 10 additions & 2 deletions admin/src/components/reqlog/LogDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ const HTTP_REQUEST_LOG = gql`
method
url
proto
headers {
key
value
}
body
response {
proto
headers {
key
value
}
status
statusCode
body
Expand Down Expand Up @@ -43,14 +51,14 @@ function LogDetail({ requestId: id }: Props): JSX.Element {
);
}

const { method, url, proto, body, response } = data.httpRequestLog;
const { method, url, proto, headers, body, response } = data.httpRequestLog;

return (
<div>
<Grid container item spacing={2}>
<Grid item xs={6}>
<Box component={Paper} maxHeight="62vh" overflow="scroll">
<RequestDetail request={{ method, url, proto, body }} />
<RequestDetail request={{ method, url, proto, headers, body }} />
</Box>
</Grid>
<Grid item xs={6}>
Expand Down
78 changes: 59 additions & 19 deletions admin/src/components/reqlog/RequestDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,83 @@
import { Typography, Box } from "@material-ui/core";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { vscDarkPlus } from "react-syntax-highlighter/dist/cjs/styles/prism";
import React from "react";
import {
Typography,
Box,
createStyles,
makeStyles,
Theme,
Divider,
} from "@material-ui/core";

import HttpHeadersTable from "./HttpHeadersTable";
import Editor from "./Editor";

const useStyles = makeStyles((theme: Theme) =>
createStyles({
requestTitle: {
width: "calc(100% - 80px)",
fontSize: "1rem",
wordBreak: "break-all",
whiteSpace: "pre-wrap",
},
headersTable: {
tableLayout: "fixed",
width: "100%",
},
headerKeyCell: {
verticalAlign: "top",
width: "30%",
fontWeight: "bold",
},
headerValueCell: {
width: "70%",
verticalAlign: "top",
wordBreak: "break-all",
whiteSpace: "pre-wrap",
},
})
);

interface Props {
request: {
method: string;
url: string;
proto: string;
headers: Array<{ key: string; value: string }>;
body?: string;
};
}

function RequestDetail({ request }: Props): JSX.Element {
const { method, url, proto, body } = request;
const { method, url, proto, headers, body } = request;
const classes = useStyles();

const contentType = headers.find((header) => header.key === "Content-Type")
?.value;
const parsedUrl = new URL(url);

return (
<div>
<Box m={3}>
<Box mx={2} my={2}>
<Typography
variant="h6"
style={{ fontSize: "1rem", whiteSpace: "nowrap" }}
variant="overline"
color="textSecondary"
style={{ float: "right" }}
>
Request
</Typography>
<Typography className={classes.requestTitle} variant="h6">
{method} {decodeURIComponent(parsedUrl.pathname + parsedUrl.search)}{" "}
{proto}
<Typography component="span" color="textSecondary">
{proto}
</Typography>
</Typography>
</Box>
<Box>
{body && (
<SyntaxHighlighter
language="markup"
showLineNumbers={true}
style={vscDarkPlus}
>
{body}
</SyntaxHighlighter>
)}
</Box>

<Divider />

<HttpHeadersTable headers={headers} />

{body && <Editor content={body} contentType={contentType} />}
</div>
);
}
Expand Down
52 changes: 27 additions & 25 deletions admin/src/components/reqlog/ResponseDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,52 @@
import { Typography, Box } from "@material-ui/core";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { vscDarkPlus } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { Typography, Box, Divider } from "@material-ui/core";

import HttpStatusIcon from "./HttpStatusCode";
import Editor from "./Editor";
import HttpHeadersTable from "./HttpHeadersTable";

interface Props {
response: {
proto: string;
statusCode: number;
status: string;
headers: Array<{ key: string; value: string }>;
body?: string;
};
}

function ResponseDetail({ response }: Props): JSX.Element {
const contentType = response.headers.find(
(header) => header.key === "Content-Type"
)?.value;
return (
<div>
<Box m={3}>
<Box mx={2} my={2}>
<Typography
variant="overline"
color="textSecondary"
style={{ float: "right" }}
>
Response
</Typography>
<Typography
variant="h6"
style={{ fontSize: "1rem", whiteSpace: "nowrap" }}
>
<HttpStatusIcon status={response.statusCode} /> {response.proto}{" "}
<HttpStatusIcon status={response.statusCode} />{" "}
<Typography component="span" color="textSecondary">
{response.proto}
</Typography>{" "}
{response.status}
</Typography>
</Box>
<Box>
{response.body && (
<SyntaxHighlighter
language="markup"
showLineNumbers={true}
showInlineLineNumbers={true}
style={vscDarkPlus}
lineProps={{
style: {
display: "block",
wordBreak: "break-all",
whiteSpace: "pre-wrap",
},
}}
wrapLines={true}
>
{response.body}
</SyntaxHighlighter>
)}
</Box>

<Divider />

<HttpHeadersTable headers={response.headers} />

{response.body && (
<Editor content={response.body} contentType={contentType} />
)}
</div>
);
}
Expand Down
Loading

0 comments on commit 71de41e

Please sign in to comment.