Upload files to "frontend/src/components"
parent
9fd149dd15
commit
ac598a5464
|
@ -0,0 +1,49 @@
|
|||
import React from "react";
|
||||
|
||||
interface ButtonProps {
|
||||
children?: JSX.Element | string,
|
||||
iconRight?: JSX.Element,
|
||||
iconLeft?: JSX.Element,
|
||||
text?: string,
|
||||
loading?: boolean,
|
||||
disabled?: boolean,
|
||||
onClick?: React.MouseEventHandler,
|
||||
className: string,
|
||||
textClassName: string
|
||||
}
|
||||
|
||||
const Button = ({ children, iconRight, iconLeft, text, loading, disabled, onClick, className, textClassName }: ButtonProps) => {
|
||||
return (
|
||||
<button disabled={disabled ? disabled : loading} onClick={onClick} className={className + " relative"}>
|
||||
{children ? (
|
||||
<div className={`${loading ? "opacity-0" : ""} ${textClassName}`}>
|
||||
{children}
|
||||
</div>
|
||||
) : (
|
||||
<div className={`flex items-center justify-center ${textClassName} ${loading ? "opacity-0" : ""}`}>
|
||||
{iconLeft}
|
||||
{text}
|
||||
{iconRight}
|
||||
</div>
|
||||
)}
|
||||
{loading && (
|
||||
<div className="justify-center flex absolute">
|
||||
<svg className="animate-spin h-5 w-5 text-white" fill="none" viewBox="0 0 24 24">
|
||||
<circle
|
||||
className="opacity-25" cx="12" cy="12" r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
/>
|
||||
<path
|
||||
className="opacity-75" fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962
|
||||
7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
|
@ -0,0 +1,29 @@
|
|||
import React, { useEffect, useRef } from "react";
|
||||
import hljs from "highlight.js";
|
||||
|
||||
interface CodeBlockProps {
|
||||
code: string,
|
||||
lang?: string
|
||||
}
|
||||
|
||||
const CodeBlock = ({ code, lang }: CodeBlockProps) => {
|
||||
const classes = "bg-black/10 rounded-lg p-2 mt-3 text-sm text-white";
|
||||
const highlightRef = useRef<HTMLPreElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (highlightRef.current) {
|
||||
const nodes = highlightRef.current.querySelectorAll("pre code");
|
||||
|
||||
for (let i = 0; i < nodes.length; i++)
|
||||
hljs.highlightBlock(nodes[i] as HTMLElement);
|
||||
}
|
||||
}, [code, lang]);
|
||||
|
||||
return (
|
||||
<pre ref={highlightRef} className={classes}>
|
||||
<code className={`${lang ? `language-${lang}` : ""} !bg-transparent`}>{code}</code>
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeBlock;
|
|
@ -0,0 +1,27 @@
|
|||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
interface HeaderProps {
|
||||
row?: JSX.Element
|
||||
}
|
||||
|
||||
const Header = (props: HeaderProps) => {
|
||||
const { row } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Link to="/">
|
||||
<h1 className="text-4xl font-mono text-white font-bold transition duration-500 hover:text-pink-500">
|
||||
RequestBin
|
||||
</h1>
|
||||
</Link>
|
||||
<h5 className="font-mono italic text-neutral-400 font-bold">
|
||||
A platform to inspect HTTP requests quickly and easily.
|
||||
</h5>
|
||||
|
||||
{row ? <div className="mt-4">{row}</div> : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
|
@ -0,0 +1,76 @@
|
|||
import React from "react";
|
||||
import { StoredRequest } from "../types";
|
||||
import dayjs from "dayjs";
|
||||
import RelativeTime from "dayjs/plugin/relativeTime";
|
||||
import { RequestBody } from "./index";
|
||||
|
||||
interface RequestProps {
|
||||
request: StoredRequest
|
||||
}
|
||||
|
||||
dayjs.extend(RelativeTime);
|
||||
|
||||
const Request = ({ request }: RequestProps) => {
|
||||
const url = new URL(request.url);
|
||||
|
||||
const methodColours: {[key: string]: string} = {
|
||||
GET: "bg-purple-500",
|
||||
POST: "bg-blue-500",
|
||||
DELETE: "bg-red-500",
|
||||
fallback: "bg-yellow-600"
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-3 rounded-lg bg-black/10 border-2 border-white/25 w-full flex gap-y-4 flex-col">
|
||||
<div className="flex gap-2 items-center justify-between">
|
||||
<div className="flex gap-2 items-center">
|
||||
<span className={`px-2 font-bold rounded-md uppercase text-white ${methodColours[request.method] ?? methodColours.fallback}`}>
|
||||
{request.method}
|
||||
</span>
|
||||
<span className="font-bold font-mono text-white">
|
||||
{request.ip}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-white">
|
||||
<span className="font-bold">{dayjs(request.timestamp).format("MMM DDD YYYY, HH:mm:ss.SSS")}</span>{" "}
|
||||
({dayjs(request.timestamp).fromNow()})
|
||||
</p>
|
||||
</div>
|
||||
{request.body && request.body.length > 0 && <RequestBody body={request.body} type={request.headers["content-type"]} />}
|
||||
<div>
|
||||
<h4 className="text-white text-xl font-bold">URL</h4>
|
||||
<p className="text-white text-sm font-bold">Host: <span className="text-pink-500 font-mono">{url.host}</span></p>
|
||||
<p className="text-white text-sm font-bold">Path: <span className="text-pink-500 font-mono">{url.pathname}</span></p>
|
||||
{url.search && (
|
||||
<div className="ml-2">
|
||||
<>
|
||||
<h5 className="text-white text-lg font-bold">Query String</h5>
|
||||
{Object.keys(Object.fromEntries(url.searchParams)).map(key => <>
|
||||
<p className="text-white text-sm font-bold">{key}:{" "}
|
||||
<span className="text-pink-500 font-mono">
|
||||
{url.searchParams.get(key)}
|
||||
</span>
|
||||
</p>
|
||||
</>)}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="text-white text-xl font-bold">Headers</h4>
|
||||
<table className="w-full">
|
||||
<tbody>
|
||||
{Object.keys(request.headers).map(key =>
|
||||
<tr key={key} className="border-b last:border-0 border-white/25">
|
||||
<td className="w-96 p-1 align-top text-white font-bold text-sm" key={key}>{key}</td>
|
||||
<td className="p-1 align-top text-pink-500 text-sm font-mono">{request.headers[key]}</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Request;
|
|
@ -0,0 +1,15 @@
|
|||
import Header from "./Header";
|
||||
import Spinner from "./Spinner";
|
||||
import Button from "./Button";
|
||||
import Request from "./Request";
|
||||
import RequestBody from "./RequestBody";
|
||||
import CodeBlock from "./CodeBlock";
|
||||
|
||||
export {
|
||||
Header,
|
||||
Spinner,
|
||||
Button,
|
||||
Request,
|
||||
RequestBody,
|
||||
CodeBlock
|
||||
};
|
Loading…
Reference in New Issue