feat: data management
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
// import React from 'react'
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useGetSystemCommonQuery, useUpdateSystemCommonMutation } from "@/app/services/server";
|
||||
import { useAppSelector } from "@/app/store";
|
||||
import { MessageExpireMode } from "@/types/server";
|
||||
import Modal from "@/components/Modal";
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import Button from "@/components/styled/Button";
|
||||
import StyledModal from "@/components/styled/Modal";
|
||||
import StyledRadio from "@/components/styled/Radio";
|
||||
|
||||
// type Props = {
|
||||
// updateConfirmModal: (context: VisibleModalType | null) => void;
|
||||
// };
|
||||
|
||||
const AutoDeleteFiles = () => {
|
||||
const currStatus = useAppSelector((store) => store.server.max_file_expiry_mode ?? "Off");
|
||||
const { t } = useTranslation("setting", { keyPrefix: "data.auto_delete_file" });
|
||||
const { t: ct } = useTranslation();
|
||||
const { refetch } = useGetSystemCommonQuery();
|
||||
const [selected, setSelected] = useState(currStatus);
|
||||
const [updateSetting, { isSuccess, isLoading }] = useUpdateSystemCommonMutation();
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
refetch();
|
||||
toast.success(ct("tip.update"));
|
||||
}
|
||||
}, [isSuccess]);
|
||||
const handleChange = (newVal: MessageExpireMode) => {
|
||||
// updateConfirmModal("auto_delete_file");
|
||||
setSelected(newVal);
|
||||
};
|
||||
const handleClose = () => {
|
||||
setSelected(currStatus);
|
||||
};
|
||||
const handleUpdate = () => {
|
||||
// todo
|
||||
updateSetting({ max_file_expiry_mode: selected });
|
||||
};
|
||||
// if (!loadSuccess) return null;
|
||||
return (
|
||||
<>
|
||||
<SettingBlock title={t("title")} desc={t("desc")}>
|
||||
<StyledRadio
|
||||
options={[t("off"), t("day1"), t("day7"), t("day30"), t("day90"), t("day180")]}
|
||||
values={["Off", "Day1", "Day7", "Day30", "Day90", "Day180"]}
|
||||
value={currStatus}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</SettingBlock>
|
||||
{selected !== currStatus && (
|
||||
<Modal id="modal-modal">
|
||||
<StyledModal
|
||||
title={"Are you sure?"}
|
||||
description={selected == "Off" ? "" : t("confirm_desc")}
|
||||
buttons={
|
||||
<>
|
||||
<Button className="cancel" onClick={handleClose}>
|
||||
{ct("action.cancel")}
|
||||
</Button>
|
||||
<Button onClick={handleUpdate} className="danger">
|
||||
{isLoading ? "Updating" : ct("action.yes")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
></StyledModal>
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AutoDeleteFiles;
|
||||
@@ -0,0 +1,66 @@
|
||||
import { FC, useEffect } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useLazyClearAllFilesQuery, useLazyClearAllMessagesQuery } from "@/app/services/server";
|
||||
import Modal from "@/components/Modal";
|
||||
import Button from "@/components/styled/Button";
|
||||
import StyledModal from "@/components/styled/Modal";
|
||||
import { VisibleModalType } from "./index";
|
||||
|
||||
interface Props {
|
||||
context: VisibleModalType;
|
||||
title: string;
|
||||
desc: string;
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
const ClearConfirmModal: FC<Props> = ({ context, title, desc, closeModal }) => {
|
||||
// const { t } = useTranslation("auth");
|
||||
const { t: ct } = useTranslation();
|
||||
const [clearFiles, { isLoading: filesClearing, isSuccess: clearFilesSuccess }] =
|
||||
useLazyClearAllFilesQuery();
|
||||
const [clearMessages, { isLoading: msgClearing, isSuccess: clearMsgSuccess }] =
|
||||
useLazyClearAllMessagesQuery();
|
||||
const handleClear = () => {
|
||||
//todo
|
||||
switch (context) {
|
||||
case "chat":
|
||||
clearMessages();
|
||||
break;
|
||||
case "files":
|
||||
clearFiles();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
const clearSuccess = clearFilesSuccess || clearMsgSuccess;
|
||||
useEffect(() => {
|
||||
if (clearSuccess) {
|
||||
toast.success("Clear success");
|
||||
closeModal();
|
||||
}
|
||||
}, [clearSuccess]);
|
||||
const clearing = msgClearing || filesClearing;
|
||||
return (
|
||||
<Modal id="modal-modal">
|
||||
<StyledModal
|
||||
title={title}
|
||||
description={desc}
|
||||
buttons={
|
||||
<>
|
||||
<Button className="cancel" onClick={closeModal}>
|
||||
{ct("action.cancel")}
|
||||
</Button>
|
||||
<Button onClick={handleClear} className="danger">
|
||||
{clearing ? "Clearing" : ct("action.remove")}
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
></StyledModal>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClearConfirmModal;
|
||||
@@ -0,0 +1,49 @@
|
||||
// import { useState, useEffect, ChangeEvent } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
// import { useAppSelector } from "@/app/store";
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledButton from "@/components/styled/Button";
|
||||
import AutoDeleteFiles from "./AutoDeleteFiles";
|
||||
import ClearConfirmModal from "./ClearConfirmModal";
|
||||
|
||||
export type VisibleModalType = "chat" | "files";
|
||||
export default function DataManagement() {
|
||||
const [visibleModal, setVisibleModal] = useState<VisibleModalType | null>(null);
|
||||
const { t } = useTranslation("setting");
|
||||
const handleModalVisible = (visible: VisibleModalType | null) => {
|
||||
setVisibleModal(visible);
|
||||
};
|
||||
const clearConfirmDesc = {
|
||||
chat: t("data.clear_msgs.desc"),
|
||||
files: t("data.clear_files.desc")
|
||||
};
|
||||
return (
|
||||
<div className="relative w-full md:w-[512px] flex flex-col gap-6">
|
||||
{/* 清除服务器聊天消息 */}
|
||||
<SettingBlock title={t("data.clear_msgs.title")} desc={t("data.clear_msgs.desc")}>
|
||||
<StyledButton onClick={handleModalVisible.bind(null, "chat")} className="danger">
|
||||
{t("data.clear_msgs.btn")}
|
||||
</StyledButton>
|
||||
</SettingBlock>
|
||||
|
||||
{/* 清除服务器文件 */}
|
||||
<SettingBlock title={t("data.clear_files.title")} desc={t("data.clear_files.desc")}>
|
||||
<StyledButton onClick={handleModalVisible.bind(null, "files")} className="danger">
|
||||
{t("data.clear_files.btn")}
|
||||
</StyledButton>
|
||||
</SettingBlock>
|
||||
{/* 自动清除清除服务器数据 */}
|
||||
<AutoDeleteFiles />
|
||||
{visibleModal && (
|
||||
<ClearConfirmModal
|
||||
closeModal={handleModalVisible.bind(null, null)}
|
||||
context={visibleModal}
|
||||
title="Are you sure?"
|
||||
desc={clearConfirmDesc[visibleModal]}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { useEffect } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledRadio from "@/components/styled/Radio";
|
||||
import {
|
||||
useGetSystemCommonQuery,
|
||||
@@ -10,7 +11,6 @@ import {
|
||||
} from "../../../app/services/server";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import { ChatLayout } from "../../../types/server";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
// type Props = {}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ import { useEffect } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledRadio from "@/components/styled/Radio";
|
||||
import {
|
||||
useGetSystemCommonQuery,
|
||||
useUpdateSystemCommonMutation
|
||||
} from "../../../app/services/server";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
// type Props = {}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import Radio from "../../../components/styled/Radio";
|
||||
import { Theme } from "../../../types/common";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
// type Props = {}
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import { ChangeEvent, useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledButton from "@/components/styled/Button";
|
||||
import StyledInput from "@/components/styled/Input";
|
||||
import { useGetFrontendUrlQuery, useUpdateFrontendUrlMutation } from "../../../app/services/server";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
// type Props = {}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// import React from 'react'
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledRadio from "@/components/styled/Radio";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
// type Props = {}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ import { useEffect } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledRadio from "@/components/styled/Radio";
|
||||
import {
|
||||
useGetSystemCommonQuery,
|
||||
useUpdateSystemCommonMutation
|
||||
} from "../../../app/services/server";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
// type Props = {}
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
desc: string;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const SettingBlock = ({ title, desc, children }: Props) => {
|
||||
return (
|
||||
<div className="text-sm">
|
||||
<p className="text-gray-600 dark:text-gray-100 font-semibold">{title}</p>
|
||||
<p className="flex justify-between w-full text-gray-400 mb-2 text-xs">{desc}</p>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingBlock;
|
||||
@@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
|
||||
|
||||
import { useAppSelector } from "@/app/store";
|
||||
import { LoginConfig, WhoCanSignUp } from "@/types/server";
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledRadio from "@/components/styled/Radio";
|
||||
import useConfig from "@/hooks/useConfig";
|
||||
import ChatLayout from "./ChatLayout";
|
||||
@@ -12,7 +13,6 @@ import FrontendURL from "./FrontendURL";
|
||||
import Language from "./Language";
|
||||
import OnlineStatus from "./OnlineStatus";
|
||||
import Server from "./Server";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
export default function Overview() {
|
||||
const { t } = useTranslation("setting");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// import React from 'react'
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import SettingBlock from "@/components/SettingBlock";
|
||||
import StyledRadio from "@/components/styled/Radio";
|
||||
import SettingBlock from "./SettingBlock";
|
||||
|
||||
// type Props = {}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import ConfigAgora from "./config/Agora";
|
||||
import ConfigFirebase from "./config/Firebase";
|
||||
import Logins from "./config/Logins";
|
||||
import ConfigSMTP from "./config/SMTP";
|
||||
import DataManagement from "./DataManagement";
|
||||
import License from "./License";
|
||||
import MyAccount from "./MyAccount";
|
||||
import Overview from "./Overview";
|
||||
@@ -31,6 +32,11 @@ const navs = [
|
||||
name: "members",
|
||||
component: <ManageMembers />,
|
||||
admin: true
|
||||
},
|
||||
{
|
||||
name: "data_management",
|
||||
component: <DataManagement />,
|
||||
admin: true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user