🎉 开始项目
feat: 完成基础界面; 列表展示 todo: uplevel button function todo: download/upload
This commit is contained in:
174
frontend/src/component/connection/list.tsx
Normal file
174
frontend/src/component/connection/list.tsx
Normal 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>
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user