drawDB/src/pages/BugReport.jsx

302 lines
9.2 KiB
React
Raw Normal View History

import React, { useEffect, useState, useCallback, useRef } from "react";
2023-09-19 20:51:49 +08:00
import logo_light from "../assets/logo_light_46.png";
import logo_dark from "../assets/logo_dark_46.png";
import { Banner, Button, Input, Upload, Toast, Spin } from "@douyinfe/semi-ui";
2023-09-19 20:51:49 +08:00
import {
IconSun,
IconMoon,
IconGithubLogo,
IconPaperclip,
} from "@douyinfe/semi-icons";
import RichEditor from "../components/RichEditor";
2023-09-19 20:52:02 +08:00
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { editorConfig } from "../data/editor_config";
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { $generateHtmlFromNodes } from "@lexical/html";
import { CLEAR_EDITOR_COMMAND } from "lexical";
2023-09-23 01:09:02 +08:00
import axios from "axios";
2023-09-19 20:52:02 +08:00
function Form({ theme }) {
const [editor] = useLexicalComposerContext();
2023-09-23 01:09:02 +08:00
const [data, setData] = useState({
title: "",
attachments: [],
});
const [loading, setLoading] = useState(false);
const uploadRef = useRef();
const resetForm = () => {
setData({
title: "",
attachments: [],
});
setLoading(false);
if (uploadRef.current) {
uploadRef.current.clear();
}
};
2023-09-23 01:09:02 +08:00
const onFileChange = (fileList) => {
const attachments = [];
const processFile = (index) => {
const reader = new FileReader();
reader.onload = (event) => {
const dataUri = event.target.result;
attachments.push({ path: dataUri, filename: fileList[index].name });
};
reader.readAsDataURL(fileList[index].fileInstance);
};
fileList.forEach((_, i) => processFile(i));
setData((prev) => ({
...prev,
attachments: attachments,
}));
};
2023-09-19 20:52:02 +08:00
const onSubmit = useCallback(
(e) => {
setLoading(true);
2023-09-19 20:52:02 +08:00
editor.update(() => {
2023-09-23 01:09:02 +08:00
const sendMail = async () => {
await axios
2023-10-14 22:02:45 +08:00
.post(`${process.env.REACT_APP_BACKEND_URL}/send_email`, {
subject: `[BUG REPORT]: ${data.title}`,
2023-09-23 01:09:02 +08:00
message: $generateHtmlFromNodes(editor),
attachments: data.attachments,
})
.then((res) => {
Toast.success("Bug reported!");
editor.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
resetForm();
})
.catch((err) => {
Toast.error("Oops! Something went wrong.");
setLoading(false);
});
2023-09-23 01:09:02 +08:00
};
sendMail();
2023-09-19 20:52:02 +08:00
});
},
2023-09-23 01:09:02 +08:00
[editor, data]
2023-09-19 20:52:02 +08:00
);
return (
<div className="p-5 mt-6 card-theme rounded-md">
2023-09-23 01:09:02 +08:00
<Input
placeholder="Title"
value={data.title}
onChange={(v) => setData((prev) => ({ ...prev, title: v }))}
/>
2023-10-13 04:17:23 +08:00
<RichEditor theme={theme} placeholder={"Describe the bug"} />
2023-09-19 20:52:02 +08:00
<Upload
action="#"
ref={uploadRef}
2023-09-23 01:09:02 +08:00
onChange={(info) => onFileChange(info.fileList)}
beforeUpload={({ file }) => {
2023-09-23 01:09:02 +08:00
return {
autoRemove: false,
fileInstance: file.fileInstance,
status: "success",
shouldUpload: false,
};
}}
2023-09-19 20:52:02 +08:00
draggable={true}
dragMainText="Click to upload the file or drag and drop the file here"
2023-09-23 01:09:02 +08:00
dragSubText="Upload up to 3 images"
accept="image/*"
limit={3}
2023-09-19 20:52:02 +08:00
></Upload>
2023-09-23 01:09:02 +08:00
<div className="pt-4 flex justify-between items-center">
<div className="text-sm opacity-80">
<i className="fa-brands fa-markdown me-1"></i>Styling with markdown is
supported
</div>
<div className="flex items-center">
<Button
onClick={onSubmit}
style={{ padding: "16px 24px" }}
disabled={loading || data.title === "" || !data.title}
>
Submit
</Button>
<div className={loading ? "ms-2" : "hidden"}>
<Spin />
</div>
</div>
2023-09-23 01:09:02 +08:00
</div>
2023-09-19 20:52:02 +08:00
</div>
);
}
2023-09-19 20:51:49 +08:00
export default function BugReport() {
const [theme, setTheme] = useState("");
useEffect(() => {
const t = localStorage.getItem("theme");
setTheme(t);
if (t === "dark") {
const body = document.body;
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "dark");
}
} else {
const body = document.body;
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "light");
}
}
2023-09-25 00:38:39 +08:00
document.title = "Report a bug | drawDB";
2023-09-19 20:51:49 +08:00
document.body.setAttribute("class", "theme");
}, [setTheme]);
const changeTheme = () => {
const body = document.body;
const t = body.getAttribute("theme-mode");
if (t === "dark") {
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "light");
setTheme("light");
}
} else {
if (body.hasAttribute("theme-mode")) {
body.setAttribute("theme-mode", "dark");
setTheme("dark");
}
}
};
return (
<>
<div className="sm:py-3 py-5 px-6 flex justify-between items-center">
<div className="flex items-center justify-start">
<img
src={theme === "dark" ? logo_dark : logo_light}
alt="logo"
className="me-2 sm:h-[28px] md:h-[46px]"
/>
<div className="ms-4 sm:text-sm xl:text-lg font-semibold">
Report a bug
</div>
</div>
<div className="flex items-center">
<Button
icon={
theme === "dark" ? (
<IconSun size="extra-large" />
) : (
<IconMoon size="extra-large" />
)
}
theme="borderless"
onClick={changeTheme}
></Button>
</div>
</div>
<hr
className={`${
theme === "dark" ? "border-zinc-700" : "border-zinc-300"
} my-1`}
/>
2023-09-23 03:18:34 +08:00
<div className="grid grid-cols-12 gap-8 my-6 mx-8 sm:mx-3">
<div className="col-span-4 md:col-span-12 lg:col-span-4">
2023-09-19 20:51:59 +08:00
<div className="card-theme p-6 rounded-md">
<div className="flex items-center">
<IconPaperclip />
<div className="font-bold ms-1">Describe the bug </div>
</div>
<div className="text-sm mt-1">
Please provide a clear and concise description of what the bug is.
</div>
<div className="flex items-center mt-3">
<IconPaperclip />
<div className="font-bold ms-1">Steps to reproduce the bug </div>
</div>
<div className="text-sm mt-1">
Please provide the steps of how to reproduce the bug.
</div>
<div className="flex items-center mt-3">
<IconPaperclip />
<div className="font-bold ms-1">Expected behaviour</div>
</div>
<div className="text-sm mt-1">
Tell us what you expected to see vs what you saw.
</div>
<div className="flex items-center mt-3">
<IconPaperclip />
<div className="font-bold ms-1">Your browser and device</div>
</div>
<div className="text-sm mt-1">
What web browser and device did you encounter the bug on.
</div>
<div className="flex items-center mt-3">
<IconPaperclip />
<div className="font-bold ms-1">Screenshots</div>
</div>
<div className="text-sm mt-1">
Add any relevant images if possible.
</div>
<div className="flex items-center justify-center my-2">
<hr
className={`${
theme === "dark" ? "border-zinc-700" : "border-zinc-300"
} flex-grow`}
/>
<div className="text-sm font-semibold m-2">Alternatively</div>
<hr
className={`${
theme === "dark" ? "border-zinc-700" : "border-zinc-300"
} flex-grow`}
/>
</div>
<Button
block
icon={<IconGithubLogo />}
style={{ backgroundColor: "#239144", color: "white" }}
onClick={() => {
window.open(
"https://github.com/drawdb-io/drawdb-issues/issues",
"_self"
);
}}
>
Add an issue
</Button>
2023-09-19 20:51:49 +08:00
</div>
</div>
2023-09-23 03:18:34 +08:00
<div className="col-span-8 md:col-span-12 lg:col-span-8">
2023-09-19 20:51:49 +08:00
<Banner
fullMode={false}
type="info"
icon={null}
closeIcon={null}
description={
<div>
We value your feedback! If you've encountered a bug or issue
while using our platform, please help us improve by reporting
it. Your input is invaluable in making our service better.
</div>
}
/>
2023-09-19 20:52:02 +08:00
<LexicalComposer initialConfig={editorConfig}>
<Form theme={theme} />
</LexicalComposer>
2023-09-19 20:51:49 +08:00
</div>
</div>
<hr
className={`${
theme === "dark" ? "border-zinc-700" : "border-zinc-300"
} my-1`}
/>
<div className="text-center text-sm py-3">
&copy; 2024 <strong>drawDB</strong> - All right reserved.
</div>
</>
);
}