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