feat: connections page simply support
This commit is contained in:
parent
7074bbc405
commit
5b886fe6be
@ -1,4 +1,20 @@
|
|||||||
|
import dayjs from "dayjs";
|
||||||
|
import { useLockFn } from "ahooks";
|
||||||
|
import { styled, Box, ListItem, IconButton, ListItemText } from "@mui/material";
|
||||||
|
import { CloseRounded } from "@mui/icons-material";
|
||||||
import { ApiType } from "../../services/types";
|
import { ApiType } from "../../services/types";
|
||||||
|
import { deleteConnection } from "../../services/api";
|
||||||
|
|
||||||
|
const Tag = styled(Box)(({ theme }) => ({
|
||||||
|
display: "inline-block",
|
||||||
|
fontSize: "12px",
|
||||||
|
padding: "0 4px",
|
||||||
|
lineHeight: 1.375,
|
||||||
|
border: "1px solid #ccc",
|
||||||
|
borderRadius: 4,
|
||||||
|
marginRight: "0.1em",
|
||||||
|
transform: "scale(0.92)",
|
||||||
|
}));
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
value: ApiType.ConnectionsItem;
|
value: ApiType.ConnectionsItem;
|
||||||
@ -7,7 +23,34 @@ interface Props {
|
|||||||
const ConnectionItem = (props: Props) => {
|
const ConnectionItem = (props: Props) => {
|
||||||
const { value } = props;
|
const { value } = props;
|
||||||
|
|
||||||
return <div>{value.metadata.host || value.metadata.destinationIP}</div>;
|
const onDelete = useLockFn(async () => deleteConnection(value.id));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem
|
||||||
|
dense
|
||||||
|
secondaryAction={
|
||||||
|
<IconButton edge="end" onClick={onDelete}>
|
||||||
|
<CloseRounded />
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ListItemText
|
||||||
|
primary={value.metadata.host || value.metadata.destinationIP}
|
||||||
|
secondary={
|
||||||
|
<Box>
|
||||||
|
<Tag sx={{ textTransform: "uppercase", color: "success" }}>
|
||||||
|
{value.metadata.network}
|
||||||
|
</Tag>
|
||||||
|
<Tag>{value.metadata.type}</Tag>
|
||||||
|
{value.chains.length > 0 && (
|
||||||
|
<Tag>{value.chains[value.chains.length - 1]}</Tag>
|
||||||
|
)}
|
||||||
|
<Tag>{dayjs(value.start).fromNow()}</Tag>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ConnectionItem;
|
export default ConnectionItem;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"Profile URL": "Profile URL",
|
"Profile URL": "Profile URL",
|
||||||
"Import": "Import",
|
"Import": "Import",
|
||||||
"New": "New",
|
"New": "New",
|
||||||
|
"Close All": "Close All",
|
||||||
|
|
||||||
"Settings": "Settings",
|
"Settings": "Settings",
|
||||||
"Clash Setting": "Clash Setting",
|
"Clash Setting": "Clash Setting",
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"Profile URL": "配置文件链接",
|
"Profile URL": "配置文件链接",
|
||||||
"Import": "导入",
|
"Import": "导入",
|
||||||
"New": "新建",
|
"New": "新建",
|
||||||
|
"Close All": "关闭全部",
|
||||||
|
|
||||||
"Settings": "设置",
|
"Settings": "设置",
|
||||||
"Clash Setting": "Clash 设置",
|
"Clash Setting": "Clash 设置",
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Paper } from "@mui/material";
|
import { useLockFn } from "ahooks";
|
||||||
|
import { Button, Paper } from "@mui/material";
|
||||||
import { Virtuoso } from "react-virtuoso";
|
import { Virtuoso } from "react-virtuoso";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ApiType } from "../services/types";
|
import { ApiType } from "../services/types";
|
||||||
import { getInfomation } from "../services/api";
|
import { closeAllConnections, getInfomation } from "../services/api";
|
||||||
import BasePage from "../components/base/base-page";
|
import BasePage from "../components/base/base-page";
|
||||||
import ConnectionItem from "../components/connection/connection-item";
|
import ConnectionItem from "../components/connection/connection-item";
|
||||||
|
|
||||||
@ -29,10 +30,26 @@ const ConnectionsPage = () => {
|
|||||||
return () => ws?.close();
|
return () => ws?.close();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const onCloseAll = useLockFn(closeAllConnections);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BasePage title={t("Connections")} contentStyle={{ height: "100%" }}>
|
<BasePage
|
||||||
|
title={t("Connections")}
|
||||||
|
contentStyle={{ height: "100%" }}
|
||||||
|
header={
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
sx={{ mt: 1 }}
|
||||||
|
variant="contained"
|
||||||
|
onClick={onCloseAll}
|
||||||
|
>
|
||||||
|
{t("Close All")}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Paper sx={{ boxShadow: 2, height: "100%" }}>
|
<Paper sx={{ boxShadow: 2, height: "100%" }}>
|
||||||
<Virtuoso
|
<Virtuoso
|
||||||
|
initialTopMostItemIndex={999}
|
||||||
data={conn.connections}
|
data={conn.connections}
|
||||||
itemContent={(index, item) => <ConnectionItem value={item} />}
|
itemContent={(index, item) => <ConnectionItem value={item} />}
|
||||||
/>
|
/>
|
||||||
|
@ -141,3 +141,15 @@ export async function getProviders() {
|
|||||||
const response = await instance.get<any, any>("/providers/proxies");
|
const response = await instance.get<any, any>("/providers/proxies");
|
||||||
return response.providers as any;
|
return response.providers as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close specific connection
|
||||||
|
export async function deleteConnection(id: string) {
|
||||||
|
const instance = await getAxios();
|
||||||
|
await instance.delete<any, any>(`/connections/${encodeURIComponent(id)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close all connections
|
||||||
|
export async function closeAllConnections() {
|
||||||
|
const instance = await getAxios();
|
||||||
|
await instance.delete<any, any>(`/connections`);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user