mirror of
https://github.com/dstotijn/hetty.git
synced 2025-07-01 18:47:29 -04:00
Add Sender module
This commit is contained in:
@ -1,46 +0,0 @@
|
||||
import MonacoEditor from "@monaco-editor/react";
|
||||
import monaco from "monaco-editor/esm/vs/editor/editor.api";
|
||||
|
||||
const monacoOptions: monaco.editor.IEditorOptions = {
|
||||
readOnly: true,
|
||||
wordWrap: "on",
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
};
|
||||
|
||||
type language = "html" | "typescript" | "json";
|
||||
|
||||
function languageForContentType(contentType?: string): language | undefined {
|
||||
switch (contentType) {
|
||||
case "text/html":
|
||||
return "html";
|
||||
case "application/json":
|
||||
case "application/json; charset=utf-8":
|
||||
return "json";
|
||||
case "application/javascript":
|
||||
case "application/javascript; charset=utf-8":
|
||||
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"
|
||||
options={monacoOptions}
|
||||
value={content}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default Editor;
|
@ -1,25 +0,0 @@
|
||||
import { SvgIconTypeMap } from "@mui/material";
|
||||
import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord";
|
||||
|
||||
interface Props {
|
||||
status: number;
|
||||
}
|
||||
|
||||
export default function HttpStatusIcon({ status }: Props): JSX.Element {
|
||||
let color: SvgIconTypeMap["props"]["color"] = "inherit";
|
||||
|
||||
switch (Math.floor(status / 100)) {
|
||||
case 2:
|
||||
case 3:
|
||||
color = "primary";
|
||||
break;
|
||||
case 4:
|
||||
color = "warning";
|
||||
break;
|
||||
case 5:
|
||||
color = "error";
|
||||
break;
|
||||
}
|
||||
|
||||
return <FiberManualRecordIcon sx={{ marginTop: "-.25rem", verticalAlign: "middle" }} color={color} />;
|
||||
}
|
@ -5,7 +5,7 @@ import Alert from "@mui/lab/Alert";
|
||||
|
||||
import RequestList from "./RequestList";
|
||||
import LogDetail from "./LogDetail";
|
||||
import CenteredPaper from "../CenteredPaper";
|
||||
import CenteredPaper from "../common/CenteredPaper";
|
||||
import { useHttpRequestLogs } from "./hooks/useHttpRequestLogs";
|
||||
|
||||
function LogsOverview(): JSX.Element {
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Typography, Box, Divider } from "@mui/material";
|
||||
|
||||
import HttpHeadersTable from "./HttpHeadersTable";
|
||||
import Editor from "./Editor";
|
||||
import Editor from "../common/Editor";
|
||||
|
||||
interface Props {
|
||||
request: {
|
||||
|
@ -9,11 +9,18 @@ import {
|
||||
Typography,
|
||||
Box,
|
||||
useTheme,
|
||||
MenuItem,
|
||||
Snackbar,
|
||||
Alert,
|
||||
Link,
|
||||
} from "@mui/material";
|
||||
|
||||
import HttpStatusIcon from "./HttpStatusCode";
|
||||
import CenteredPaper from "../CenteredPaper";
|
||||
import HttpStatusIcon from "../common/HttpStatusIcon";
|
||||
import CenteredPaper from "../common/CenteredPaper";
|
||||
import { RequestLog } from "../../lib/requestLogs";
|
||||
import useContextMenu from "../common/useContextMenu";
|
||||
import React, { useState } from "react";
|
||||
import { useCreateSenderRequestFromHttpRequestLogMutation } from "../../generated/graphql";
|
||||
|
||||
interface Props {
|
||||
logs: RequestLog[];
|
||||
@ -45,69 +52,117 @@ interface RequestListTableProps {
|
||||
function RequestListTable({ logs, selectedReqLogId, onLogClick }: RequestListTableProps): JSX.Element {
|
||||
const theme = useTheme();
|
||||
|
||||
const [createSenderReqFromLog] = useCreateSenderRequestFromHttpRequestLogMutation({});
|
||||
|
||||
const [copyToSenderId, setCopyToSenderId] = useState("");
|
||||
const [Menu, handleContextMenu, handleContextMenuClose] = useContextMenu();
|
||||
|
||||
const handleCopyToSenderClick = () => {
|
||||
createSenderReqFromLog({
|
||||
variables: {
|
||||
id: copyToSenderId,
|
||||
},
|
||||
onCompleted({ createSenderRequestFromHttpRequestLog }) {
|
||||
const { id } = createSenderRequestFromHttpRequestLog;
|
||||
setNewSenderReqId(id);
|
||||
setCopiedReqNotifOpen(true);
|
||||
},
|
||||
});
|
||||
handleContextMenuClose();
|
||||
};
|
||||
|
||||
const [newSenderReqId, setNewSenderReqId] = React.useState("");
|
||||
const [copiedReqNotifOpen, setCopiedReqNotifOpen] = React.useState(false);
|
||||
const handleCloseCopiedNotif = (_: Event | React.SyntheticEvent, reason?: string) => {
|
||||
if (reason === "clickaway") {
|
||||
return;
|
||||
}
|
||||
setCopiedReqNotifOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<TableContainer
|
||||
component={Paper}
|
||||
style={{
|
||||
minHeight: logs.length ? 200 : 0,
|
||||
height: logs.length ? "24vh" : "inherit",
|
||||
}}
|
||||
>
|
||||
<Table stickyHeader size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Method</TableCell>
|
||||
<TableCell>Origin</TableCell>
|
||||
<TableCell>Path</TableCell>
|
||||
<TableCell>Status</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{logs.map(({ id, method, url, response }) => {
|
||||
const { origin, pathname, search, hash } = new URL(url);
|
||||
<div>
|
||||
<Menu>
|
||||
<MenuItem onClick={handleCopyToSenderClick}>Copy request to Sender</MenuItem>
|
||||
</Menu>
|
||||
<Snackbar
|
||||
open={copiedReqNotifOpen}
|
||||
autoHideDuration={3000}
|
||||
onClose={handleCloseCopiedNotif}
|
||||
anchorOrigin={{ horizontal: "center", vertical: "bottom" }}
|
||||
>
|
||||
<Alert onClose={handleCloseCopiedNotif} severity="info">
|
||||
Request was copied. <Link href={`/sender?id=${newSenderReqId}`}>Edit in Sender.</Link>
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
|
||||
const cellStyle = {
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
} as any;
|
||||
<TableContainer
|
||||
component={Paper}
|
||||
style={{
|
||||
minHeight: logs.length ? 200 : 0,
|
||||
height: logs.length ? "24vh" : "inherit",
|
||||
}}
|
||||
>
|
||||
<Table stickyHeader size="small">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Method</TableCell>
|
||||
<TableCell>Origin</TableCell>
|
||||
<TableCell>Path</TableCell>
|
||||
<TableCell>Status</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{logs.map(({ id, method, url, response }) => {
|
||||
const { origin, pathname, search, hash } = new URL(url);
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
key={id}
|
||||
sx={{
|
||||
"&:hover": {
|
||||
cursor: "pointer",
|
||||
},
|
||||
...(id === selectedReqLogId && {
|
||||
bgcolor: theme.palette.action.selected,
|
||||
}),
|
||||
}}
|
||||
hover
|
||||
onClick={() => onLogClick(id)}
|
||||
>
|
||||
<TableCell style={{ ...cellStyle, width: "100px" }}>
|
||||
<code>{method}</code>
|
||||
</TableCell>
|
||||
<TableCell sx={{ ...cellStyle, maxWidth: "100px" }}>{origin}</TableCell>
|
||||
<TableCell sx={{ ...cellStyle, maxWidth: "200px" }}>
|
||||
{decodeURIComponent(pathname + search + hash)}
|
||||
</TableCell>
|
||||
<TableCell style={{ maxWidth: "100px" }}>
|
||||
{response && (
|
||||
<div>
|
||||
<HttpStatusIcon status={response.statusCode} />{" "}
|
||||
<code>
|
||||
{response.statusCode} {response.statusReason}
|
||||
</code>
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
const cellStyle = {
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
} as any;
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
key={id}
|
||||
sx={{
|
||||
"&:hover": {
|
||||
cursor: "pointer",
|
||||
},
|
||||
...(id === selectedReqLogId && {
|
||||
bgcolor: theme.palette.action.selected,
|
||||
}),
|
||||
}}
|
||||
hover
|
||||
onClick={() => onLogClick(id)}
|
||||
onContextMenu={(e) => {
|
||||
setCopyToSenderId(id);
|
||||
handleContextMenu(e);
|
||||
}}
|
||||
>
|
||||
<TableCell style={{ ...cellStyle, width: "100px" }}>
|
||||
<code>{method}</code>
|
||||
</TableCell>
|
||||
<TableCell sx={{ ...cellStyle, maxWidth: "100px" }}>{origin}</TableCell>
|
||||
<TableCell sx={{ ...cellStyle, maxWidth: "200px" }}>
|
||||
{decodeURIComponent(pathname + search + hash)}
|
||||
</TableCell>
|
||||
<TableCell style={{ maxWidth: "100px" }}>
|
||||
{response && (
|
||||
<div>
|
||||
<HttpStatusIcon status={response.statusCode} />{" "}
|
||||
<code>
|
||||
{response.statusCode} {response.statusReason}
|
||||
</code>
|
||||
</div>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Typography, Box, Divider } from "@mui/material";
|
||||
|
||||
import HttpStatusIcon from "./HttpStatusCode";
|
||||
import Editor from "./Editor";
|
||||
import HttpStatusIcon from "../common/HttpStatusIcon";
|
||||
import Editor from "../common/Editor";
|
||||
import HttpHeadersTable from "./HttpHeadersTable";
|
||||
|
||||
interface Props {
|
||||
|
13
admin/src/components/reqlog/hooks/useCreateSenderRequest.ts
Normal file
13
admin/src/components/reqlog/hooks/useCreateSenderRequest.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { gql, useMutation } from "@apollo/client";
|
||||
|
||||
const CREATE_SENDER_REQUEST = gql`
|
||||
mutation CreateSenderRequest($request: SenderRequestInput!) {
|
||||
createSenderRequest(request: $request) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function useCreateSenderRequest() {
|
||||
return useMutation(CREATE_SENDER_REQUEST);
|
||||
}
|
Reference in New Issue
Block a user