mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 12:17:24 +00:00
Allow normal user to upload.
This commit is contained in:
@@ -108,7 +108,7 @@ export default function ManageServerConfigPage() {
|
||||
}}
|
||||
></Input>
|
||||
<fieldset className="fieldset w-full">
|
||||
<legend className="fieldset-legend">Allow register</legend>
|
||||
<legend className="fieldset-legend">Allow registration</legend>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={config.allow_register}
|
||||
@@ -164,6 +164,36 @@ export default function ManageServerConfigPage() {
|
||||
label="Site info (Markdown)"
|
||||
height={180}
|
||||
/>
|
||||
<fieldset className="fieldset w-full">
|
||||
<legend className="fieldset-legend">Allow normal user upload</legend>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={config.allow_normal_user_upload}
|
||||
className="toggle-primary toggle"
|
||||
onChange={(e) => {
|
||||
setConfig({ ...config, allow_normal_user_upload: e.target.checked });
|
||||
}}
|
||||
/>
|
||||
</fieldset>
|
||||
<Input
|
||||
type="number"
|
||||
value={config.max_normal_user_upload_size_in_mb.toString()}
|
||||
label="Max normal user upload size (MB)"
|
||||
onChange={(e) => {
|
||||
setConfig({
|
||||
...config,
|
||||
max_normal_user_upload_size_in_mb: parseInt(e.target.value),
|
||||
});
|
||||
}}
|
||||
></Input>
|
||||
<Input
|
||||
type="text"
|
||||
value={config.upload_prompt}
|
||||
label="Upload prompt"
|
||||
onChange={(e) => {
|
||||
setConfig({ ...config, upload_prompt: e.target.value });
|
||||
}}
|
||||
></Input>
|
||||
<InfoAlert
|
||||
className="my-2"
|
||||
message="If the cloudflare turnstile keys are not empty, the turnstile will be used for register and download."
|
||||
|
@@ -3,10 +3,12 @@ import { Storage } from "../network/models.ts";
|
||||
import { network } from "../network/network.ts";
|
||||
import showToast from "../components/toast.ts";
|
||||
import Loading from "../components/loading.tsx";
|
||||
import { MdAdd, MdDelete } from "react-icons/md";
|
||||
import { MdAdd, MdMoreHoriz } from "react-icons/md";
|
||||
import { ErrorAlert } from "../components/alert.tsx";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { app } from "../app.ts";
|
||||
import showPopup, { PopupMenuItem } from "../components/popup.tsx";
|
||||
import Badge from "../components/badge.tsx";
|
||||
|
||||
export default function StorageView() {
|
||||
const { t } = useTranslation();
|
||||
@@ -84,6 +86,26 @@ export default function StorageView() {
|
||||
setLoadingId(null);
|
||||
};
|
||||
|
||||
const handleSetDefault = async (id: number) => {
|
||||
if (loadingId != null) {
|
||||
return;
|
||||
}
|
||||
setLoadingId(id);
|
||||
const response = await network.setDefaultStorage(id);
|
||||
if (response.success) {
|
||||
showToast({
|
||||
message: t("Storage set as default successfully"),
|
||||
});
|
||||
updateStorages();
|
||||
} else {
|
||||
showToast({
|
||||
message: response.message,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
setLoadingId(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
@@ -121,7 +143,10 @@ export default function StorageView() {
|
||||
{storages.map((s) => {
|
||||
return (
|
||||
<tr key={s.id} className={"hover"}>
|
||||
<td>{s.name}</td>
|
||||
<td>
|
||||
{s.name}
|
||||
{s.isDefault && <Badge className={"ml-1"}>{t("Default")}</Badge>}
|
||||
</td>
|
||||
<td>{new Date(s.createdAt).toLocaleString()}</td>
|
||||
<td>
|
||||
{(s.currentSize / 1024 / 1024).toFixed(2)} /{" "}
|
||||
@@ -129,13 +154,39 @@ export default function StorageView() {
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
id={`set_default_button_${s.id}`}
|
||||
className={"btn btn-square"}
|
||||
type={"button"}
|
||||
onClick={() => {
|
||||
const dialog = document.getElementById(
|
||||
`confirm_delete_dialog_${s.id}`,
|
||||
) as HTMLDialogElement;
|
||||
dialog.showModal();
|
||||
showPopup(
|
||||
<ul className="menu bg-base-100 rounded-box z-1 w-64 p-2 shadow-sm">
|
||||
<h4 className="text-sm font-bold px-3 py-1 text-primary">
|
||||
{t("Actions")}
|
||||
</h4>
|
||||
<PopupMenuItem
|
||||
onClick={() => {
|
||||
const dialog = document.getElementById(
|
||||
`confirm_delete_dialog_${s.id}`,
|
||||
) as HTMLDialogElement;
|
||||
dialog.showModal();
|
||||
}}
|
||||
>
|
||||
<a>{t("Delete")}</a>
|
||||
</PopupMenuItem>
|
||||
{!s.isDefault && <PopupMenuItem
|
||||
onClick={() => {
|
||||
handleSetDefault(s.id);
|
||||
}}
|
||||
>
|
||||
<a>
|
||||
t("Set as Default")
|
||||
</a>
|
||||
</PopupMenuItem>}
|
||||
</ul>,
|
||||
document.getElementById(
|
||||
`set_default_button_${s.id}`,
|
||||
)!,
|
||||
);
|
||||
}}
|
||||
>
|
||||
{loadingId === s.id ? (
|
||||
@@ -143,7 +194,7 @@ export default function StorageView() {
|
||||
className={"loading loading-spinner loading-sm"}
|
||||
></span>
|
||||
) : (
|
||||
<MdDelete size={24} />
|
||||
<MdMoreHoriz size={24} />
|
||||
)}
|
||||
</button>
|
||||
<dialog
|
||||
|
@@ -404,7 +404,6 @@ function Article({ resource }: { resource: ResourceDetails }) {
|
||||
<Markdown
|
||||
components={{
|
||||
p: ({ node, ...props }) => {
|
||||
console.log(props.children);
|
||||
if (
|
||||
typeof props.children === "object" &&
|
||||
(props.children as ReactElement).type === "strong"
|
||||
@@ -722,7 +721,7 @@ function Files({ files, resourceID }: { files: RFile[]; resourceID: number }) {
|
||||
return <FileTile file={file} key={file.id}></FileTile>;
|
||||
})}
|
||||
<div className={"h-2"}></div>
|
||||
{app.canUpload() && (
|
||||
{app.canUpload() || app.allowNormalUserUpload && (
|
||||
<div className={"flex flex-row-reverse"}>
|
||||
<CreateFileDialog resourceId={resourceID}></CreateFileDialog>
|
||||
</div>
|
||||
@@ -876,6 +875,12 @@ function CreateFileDialog({ resourceId }: { resourceId: number }) {
|
||||
showToast({ message: res.message, type: "error" });
|
||||
} else {
|
||||
storages.current = res.data!;
|
||||
let defaultStorage = storages.current.find((s) => s.isDefault);
|
||||
if (!defaultStorage && storages.current.length > 0) {
|
||||
defaultStorage = storages.current[0];
|
||||
}
|
||||
console.log("defaultStorage", defaultStorage);
|
||||
setStorage(defaultStorage || null);
|
||||
setLoading(false);
|
||||
const dialog = document.getElementById(
|
||||
"upload_dialog",
|
||||
@@ -902,6 +907,10 @@ function CreateFileDialog({ resourceId }: { resourceId: number }) {
|
||||
<div className="modal-box">
|
||||
<h3 className="font-bold text-lg mb-2">{t("Create File")}</h3>
|
||||
|
||||
{app.uploadPrompt && (
|
||||
<p className={"text-sm p-2"}>{app.uploadPrompt}</p>
|
||||
)}
|
||||
|
||||
<p className={"text-sm font-bold p-2"}>{t("Type")}</p>
|
||||
<form className="filter mb-2">
|
||||
<input
|
||||
@@ -980,8 +989,9 @@ function CreateFileDialog({ resourceId }: { resourceId: number }) {
|
||||
)}
|
||||
</p>
|
||||
<select
|
||||
disabled={!app.canUpload()} // normal user cannot choose storage
|
||||
className="select select-primary w-full my-2"
|
||||
defaultValue={""}
|
||||
value={storage?.id || ""}
|
||||
onChange={(e) => {
|
||||
const id = parseInt(e.target.value);
|
||||
if (isNaN(id)) {
|
||||
@@ -1027,7 +1037,15 @@ function CreateFileDialog({ resourceId }: { resourceId: number }) {
|
||||
</>
|
||||
)}
|
||||
|
||||
{fileType === FileType.serverTask && (
|
||||
{fileType === FileType.serverTask && !app.canUpload() && (
|
||||
<p className={"text-sm p-2"}>
|
||||
{t(
|
||||
"You do not have permission to upload files, please contact the administrator.",
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{fileType === FileType.serverTask && app.canUpload() && (
|
||||
<>
|
||||
<p className={"text-sm p-2"}>
|
||||
{t(
|
||||
@@ -1035,8 +1053,9 @@ function CreateFileDialog({ resourceId }: { resourceId: number }) {
|
||||
)}
|
||||
</p>
|
||||
<select
|
||||
disabled={!app.canUpload()}
|
||||
className="select select-primary w-full my-2"
|
||||
defaultValue={""}
|
||||
value={storage?.id || ""}
|
||||
onChange={(e) => {
|
||||
const id = parseInt(e.target.value);
|
||||
if (isNaN(id)) {
|
||||
|
Reference in New Issue
Block a user