2024-05-17 19:13:33 +08:00

134 lines
3.5 KiB
TypeScript

import { useMemo, useState } from "react";
import { useRecoilState } from "recoil";
import {
Box,
Button,
IconButton,
MenuItem,
Select,
SelectProps,
styled,
} from "@mui/material";
import { Virtuoso } from "react-virtuoso";
import { useTranslation } from "react-i18next";
import {
PlayCircleOutlineRounded,
PauseCircleOutlineRounded,
} from "@mui/icons-material";
import { atomEnableLog, atomLogData } from "@/services/states";
import { BaseEmpty, BasePage } from "@/components/base";
import LogItem from "@/components/log/log-item";
import { useCustomTheme } from "@/components/layout/use-custom-theme";
import { BaseSearchBox } from "@/components/base/base-search-box";
const StyledSelect = styled((props: SelectProps<string>) => {
return (
<Select
size="small"
autoComplete="off"
sx={{
width: 120,
height: 33.375,
mr: 1,
'[role="button"]': { py: 0.65 },
}}
{...props}
/>
);
})(({ theme }) => ({
background: theme.palette.mode === "light" ? "#fff" : undefined,
}));
const LogPage = () => {
const { t } = useTranslation();
const [logData, setLogData] = useRecoilState(atomLogData);
const [enableLog, setEnableLog] = useRecoilState(atomEnableLog);
const { theme } = useCustomTheme();
const isDark = theme.palette.mode === "dark";
const [logState, setLogState] = useState("all");
const [match, setMatch] = useState(() => (_: string) => true);
const filterLogs = useMemo(() => {
return logData
.filter((data) =>
logState === "all" ? true : data.type.includes(logState)
)
.filter((data) => match(data.payload));
}, [logData, logState, match]);
return (
<BasePage
full
title={t("Logs")}
contentStyle={{ height: "100%" }}
header={
<Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
<IconButton
size="small"
color="inherit"
onClick={() => setEnableLog((e) => !e)}
>
{enableLog ? (
<PauseCircleOutlineRounded />
) : (
<PlayCircleOutlineRounded />
)}
</IconButton>
<Button
size="small"
variant="contained"
onClick={() => setLogData([])}
>
{t("Clear")}
</Button>
</Box>
}
>
<Box
sx={{
pt: 1,
mb: 0.5,
mx: "10px",
height: "36px",
display: "flex",
alignItems: "center",
}}
>
<StyledSelect
value={logState}
onChange={(e) => setLogState(e.target.value)}
>
<MenuItem value="all">ALL</MenuItem>
<MenuItem value="inf">INFO</MenuItem>
<MenuItem value="warn">WARN</MenuItem>
<MenuItem value="err">ERROR</MenuItem>
</StyledSelect>
<BaseSearchBox onSearch={(match) => setMatch(() => match)} />
</Box>
<Box
height="calc(100% - 65px)"
sx={{
margin: "10px",
borderRadius: "8px",
bgcolor: isDark ? "#282a36" : "#ffffff",
}}
>
{filterLogs.length > 0 ? (
<Virtuoso
initialTopMostItemIndex={999}
data={filterLogs}
itemContent={(index, item) => <LogItem value={item} />}
followOutput={"smooth"}
/>
) : (
<BaseEmpty text="No Logs" />
)}
</Box>
</BasePage>
);
};
export default LogPage;