🎉 开始项目

feat: 完成基础界面; 列表展示
todo: uplevel button function
todo: download/upload
This commit is contained in:
loveuer
2024-10-11 22:24:14 +08:00
commit 1c818daf16
76 changed files with 12517 additions and 0 deletions

View File

@ -0,0 +1,174 @@
import {
Button,
Input,
makeStyles,
Menu,
MenuItem,
MenuList, MenuPopover, MenuProps,
mergeClasses, PositioningImperativeRef,
tokens,
Tooltip
} from "@fluentui/react-components"
import {DatabaseLinkRegular, DismissRegular} from "@fluentui/react-icons";
import React, {useState} from "react";
import {Bucket, Connection} from "../../interfaces/connection";
import {useToast} from "../../message";
import {Dial} from "../../api";
import {useStoreConnection} from "../../store/connection";
import {useStoreBucket} from "../../store/bucket";
const useStyles = makeStyles({
list: {
display: "flex",
flexDirection: "row",
height: "100%",
},
content: {
height: "100%",
width: "25rem",
display: "flex",
flexDirection: "column",
},
filter: {
height: "4rem",
width: "100%",
display: "flex",
alignItems: "center",
},
filter_input: {
width: "100%",
marginLeft: "0.5rem",
marginRight: "0.5rem",
},
items: {
height: "100%",
width: "100%",
},
items_one: {
marginLeft: "0.5rem",
marginRight: "0.5rem",
"&:hover": {
color: tokens.colorNeutralForeground2BrandPressed,
},
"&.active": {
color: tokens.colorNeutralForeground2BrandPressed,
fontWeight: "bold",
},
"& > span": {
display: "flex",
},
},
items_disconn: {
marginLeft: "auto",
},
slider: {
height: '100%', width: '1px',
// todo: resize
// cursor: 'ew-resize',
'& > div': {
height: '100%', width: '1px',
backgroundColor: 'lightgray',
},
},
})
export function ConnectionList() {
const styles = useStyles()
const {dispatchMessage} = useToast();
const {conn_list, conn_update} = useStoreConnection();
const [conn_filter, set_conn_filter] = useState<string>('');
const {bucket_get, bucket_set} = useStoreBucket()
async function handleSelect(item: Connection) {
conn_list.map((one: Connection) => {
if (item.id === one.id && one.active) {
conn_update(one)
bucket_get(one, false)
bucket_set(null)
}
})
}
async function handleConnect(item: Connection) {
let res = await Dial('/api/connection/connect', {id: item.id});
if (res.status !== 200) {
dispatchMessage(res.msg, "error")
return
}
conn_update({...item, active: true})
bucket_get(item, true)
bucket_set(null)
}
async function handleDisconnect(item: Connection) {
let res = await Dial('/api/connection/disconnect', {id: item.id})
if (res.status !== 200) {
dispatchMessage(res.msg, "error")
return
}
conn_update({...item, active: false})
}
async function handleRightClick(e: React.MouseEvent<HTMLDivElement>, item: Connection) {
e.preventDefault()
console.log('[DEBUG] right click connection =', item, 'event =', e)
console.log(`[DEBUG] click position: [${e.pageX}, ${e.pageY}]`)
}
return (
<div className={styles.list}>
<div className={styles.content}>
<div className={styles.filter}>
<Input
value={conn_filter}
className={styles.filter_input}
contentAfter={
<Button appearance={'transparent'} onClick={async () => {
set_conn_filter('')
}} size="small" icon={<DismissRegular/>}/>
}
placeholder="搜索连接"
onChange={(e) => set_conn_filter(e.target.value)}
/>
</div>
<div className={styles.items}>
<MenuList>
{conn_list.filter(item => item.name.includes(conn_filter)).map(item => {
return <MenuItem
className={item.active ? mergeClasses(styles.items_one, "active") : styles.items_one}
onClick={async () => {
await handleSelect(item)
}}
onDoubleClick={async () => {
await handleConnect(item)
}}
onContextMenu={async (e) => {
await handleRightClick(e, item)
}}
icon={<DatabaseLinkRegular/>}
key={item.id}>
{item.name}
<Tooltip
content="断开连接"
relationship="label">
<Button
appearance={'transparent'}
size="small"
icon={<DismissRegular/>}
className={styles.items_disconn}
onClick={async () => {
await handleDisconnect(item)
}}/>
</Tooltip>
</MenuItem>
})}
</MenuList>
</div>
</div>
<div className={styles.slider}>
<div></div>
</div>
</div>
)
}