Upload files to "frontend/src/pages"
parent
b1ded0e922
commit
98485dc078
|
@ -0,0 +1,96 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { Header, Spinner, Request, Button } from "../components";
|
||||||
|
import { Error } from "../pages";
|
||||||
|
import { DreadBin, DreadBinResponse } from "../types";
|
||||||
|
import { QuestionMarkCircleIcon } from "@heroicons/react/solid";
|
||||||
|
|
||||||
|
const Bin = () => {
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [refresh, setRefresh] = useState(0);
|
||||||
|
const [error, setError] = useState<number | null>(null);
|
||||||
|
const [bin, setBin] = useState<DreadBin | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setRefresh(Math.random());
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const response = await fetch(`${process.env.REACT_APP_BASE_API_URL}/${id}`);
|
||||||
|
const body = await response.json() as DreadBinResponse;
|
||||||
|
|
||||||
|
if (response.ok)
|
||||||
|
setBin(body.bin);
|
||||||
|
else
|
||||||
|
setError(response.status);
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
} catch (_) {
|
||||||
|
setError(500);
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [id, refresh]);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (error === 404) {
|
||||||
|
return (
|
||||||
|
<Error code={404} message="A request bin could not be found with the ID provided"/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Error code={error} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-8">
|
||||||
|
<Header row={loading ? <Spinner /> : (
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<p className="font-mono text-pink-500 font-bold select-none">
|
||||||
|
Your DreadBin endpoint:{" "}
|
||||||
|
<span className="font-mono select-all rounded-lg p-1 px-2 bg-black/25 text-neutral-300">
|
||||||
|
{process.env.REACT_APP_BASE_API_URL}/-/{id}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
className={
|
||||||
|
"flex items-center justify-center disabled:cursor-not-allowed shadow-lg tracking-tight " +
|
||||||
|
"rounded-md bg-cyan-600 hover:bg-cyan-700 text-white font-semibold text-lg px-4 py-1"}
|
||||||
|
text="Refresh"
|
||||||
|
textClassName="font-mono"
|
||||||
|
onClick={() => setRefresh(Math.random())}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)} />
|
||||||
|
{!loading && bin && (
|
||||||
|
Object.keys(bin.requests).length === 0 ? (
|
||||||
|
<div className="flex mt-8 gap-2">
|
||||||
|
<QuestionMarkCircleIcon className="h-6 w-6 text-white" />
|
||||||
|
<p className="font-bold text-white">No Requests Found</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex gap-4 mt-8 flex-col">
|
||||||
|
{Object
|
||||||
|
.keys(bin.requests)
|
||||||
|
.sort((a, b) => bin.requests[a].timestamp > bin.requests[b].timestamp ? -1 : 1)
|
||||||
|
.map(requestId => <Request key={requestId} request={bin.requests[requestId]} />)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Bin;
|
|
@ -0,0 +1,58 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { Header } from "../components";
|
||||||
|
|
||||||
|
interface ErrorProps {
|
||||||
|
code: number,
|
||||||
|
message?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const Error = (props: ErrorProps) => {
|
||||||
|
const { code, message } = props;
|
||||||
|
|
||||||
|
let defaultMessage: string;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case 404:
|
||||||
|
defaultMessage = "The requested resource could not be found";
|
||||||
|
break;
|
||||||
|
case 401 || 403:
|
||||||
|
defaultMessage = "You don't have permission to access this resource";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
defaultMessage = "An unknown error occurred";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-8 select-none">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<pre className="font-mono text-red-500 font-bold">
|
||||||
|
Code: {code}
|
||||||
|
</pre>
|
||||||
|
<pre className="font-mono text-red-500 font-bold">
|
||||||
|
Message: {message ? message : defaultMessage}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 flex gap-4">
|
||||||
|
<Link
|
||||||
|
className="font-mono font-bold text-cyan-600 underline cursor-pointer"
|
||||||
|
to="/"
|
||||||
|
>
|
||||||
|
Go to Homepage.
|
||||||
|
</Link>
|
||||||
|
<a
|
||||||
|
className="font-mono font-bold text-cyan-600 underline cursor-pointer"
|
||||||
|
href="mailto:klez@cocaine.ninja"
|
||||||
|
>
|
||||||
|
Report an Issue.
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Error;
|
|
@ -0,0 +1,107 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { Header, Button } from "../components";
|
||||||
|
import { ExclamationCircleIcon } from "@heroicons/react/solid";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { DreadBinResponse, ErrorResponse } from "../types";
|
||||||
|
|
||||||
|
const Landing = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleCreateBin = async () => {
|
||||||
|
setError(null);
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${process.env.REACT_APP_BASE_API_URL}/create`, {
|
||||||
|
method: "POST"
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const body = await response.json() as DreadBinResponse;
|
||||||
|
navigate(`/${body.bin.id}`);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = await response.json() as ErrorResponse;
|
||||||
|
|
||||||
|
setError(body.message);
|
||||||
|
} catch (_) {
|
||||||
|
setError("An unknown error occurred");
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="m-8 select-none">
|
||||||
|
<Header row={<>
|
||||||
|
<Button
|
||||||
|
loading={loading}
|
||||||
|
className={
|
||||||
|
"flex items-center justify-center disabled:cursor-not-allowed shadow-lg tracking-tight " +
|
||||||
|
"rounded-md bg-cyan-600 hover:bg-cyan-700 text-white font-semibold text-lg px-4 py-1"}
|
||||||
|
onClick={handleCreateBin}
|
||||||
|
text="Create a Bin"
|
||||||
|
textClassName="font-mono"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<p className="mt-3 font-bold font-mono text-red-600 text-sm flex gap-2 items-center">
|
||||||
|
<ExclamationCircleIcon className="w-5 h-5 inline-block" />
|
||||||
|
{error}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>} />
|
||||||
|
|
||||||
|
<div className="mt-16">
|
||||||
|
<h5 className="font-mono font-bold text-pink-600 mb-1">
|
||||||
|
# What can I do with this?
|
||||||
|
</h5>
|
||||||
|
<p className="ml-2 font-mono text-neutral-400 font-bold text-sm">
|
||||||
|
Anything you want really. Each request you make to the endpoint provided can be inspected, including:
|
||||||
|
</p>
|
||||||
|
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Request Method</p>
|
||||||
|
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Timestamp</p>
|
||||||
|
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Headers</p>
|
||||||
|
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Body (including formatting for common types)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<h5 className="font-mono font-bold text-pink-600 mb-1">
|
||||||
|
# Is it open-source?
|
||||||
|
</h5>
|
||||||
|
<p className="ml-2 font-mono text-neutral-400 font-bold text-sm">
|
||||||
|
Yes.{" "}
|
||||||
|
<a
|
||||||
|
className="font-mono text-cyan-600 underline cursor-pointer"
|
||||||
|
target="_blank" rel="noreferrer noopener"
|
||||||
|
href="https://fsdfsd.net/Klez/DreadBin.git"
|
||||||
|
>
|
||||||
|
https://fsdfsd.net/Klez/DreadBin.git
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8">
|
||||||
|
<h5 className="font-mono font-bold text-pink-600 mb-1">
|
||||||
|
# Who made this <span className="font-mono font-extrabold">*amazing*</span> tool?
|
||||||
|
</h5>
|
||||||
|
<p className="ml-2 font-mono text-neutral-400 font-bold text-sm">
|
||||||
|
Me.{" "}
|
||||||
|
<a
|
||||||
|
className="font-mono text-cyan-600 underline cursor-pointer"
|
||||||
|
target="_blank" rel="noreferrer noopener"
|
||||||
|
href="https://dreadfulservices.xyz"
|
||||||
|
>
|
||||||
|
https://dreadfulservices.xyz
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Landing;
|
|
@ -0,0 +1,9 @@
|
||||||
|
import Landing from "./Landing";
|
||||||
|
import Error from "./Error";
|
||||||
|
import Bin from "./Bin";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Landing,
|
||||||
|
Error,
|
||||||
|
Bin
|
||||||
|
};
|
Loading…
Reference in New Issue