admin/monitor: added path column
Massimo Melina committed
Mar 9, 2022 at 22:18 UTC
fd1b751e92803df897e41705318e1db8e6cbcd53
5 files changed
+43
-27
admin/src/MonitorPage.ts
+29
-19
@@ -3,8 +3,8 @@
3
import _ from "lodash"
4
import { isValidElement, createElement as h, useMemo, Fragment } from "react"
5
import { apiCall, useApiComp, useApiList } from "./api"
6
-import { Delete, Lock, Refresh } from '@mui/icons-material'
7
-import { Box, Grid, Typography } from '@mui/material'
6
+import { Delete, Lock } from '@mui/icons-material'
7
+import { Box, Chip, Typography } from '@mui/material'
8
import { DataGrid } from "@mui/x-data-grid"
9
import { Alert } from '@mui/material'
10
import { formatBytes, IconBtn, iconTooltip } from "./misc"
@@ -12,14 +12,10 @@ import { alertDialog } from "./dialog"
12
import { prefix } from './misc'
13
14
export default function MonitorPage() {
15
- return h(Box, { flex: 1, display: 'flex', flexDirection: 'column' },
16
- h(Grid, { container: true, flex: 1 },
17
- h(Grid, { item: true, md: 3, lg: 4, xl: 6 },
18
- h(MoreInfo) ),
19
- h(Grid, { item: true, md: 9, lg: 8, xl: 6, width: '100%', display: 'flex', flexDirection: 'column' },
20
- h(SectionTitle, {}, "Active connections"),
21
- h(Connections))
22
- )
15
+ return h(Fragment, {},
16
+ h(MoreInfo),
17
+ h(SectionTitle, {}, "Active connections"),
18
+ h(Connections),
19
)
20
}
21
@@ -30,11 +26,10 @@ function SectionTitle(props: object) {
26
}
27
28
function MoreInfo() {
33
- const [res, reload] = useApiComp('get_status')
34
- return h(Box, {},
35
- h(SectionTitle, {}, "Status", h(IconBtn, { sx: { ml: 2 }, icon: Refresh, onClick: reload })),
29
+ const [res] = useApiComp('get_status')
30
+ return h(Fragment, {},
31
isValidElement(res) ? res :
37
- h('ul', {},
32
+ h(Box, { display: 'flex', flexWrap: 'wrap', gap: '1em', mb: 1 },
33
pair('started'),
34
pair('version'),
35
pair('build'),
@@ -53,7 +48,10 @@ function MoreInfo() {
48
v = render(v)
49
if (!label)
50
label = _.capitalize(k.replaceAll('_', ' '))
56
- return h('li', {}, label + ': ' + v)
51
+ return h(Chip, {
52
+ variant: 'filled',
53
+ label: h(Fragment, {}, h('b',{},label), ': ', v),
54
+ })
55
}
56
}
57
@@ -64,6 +62,7 @@ function Connections() {
62
return h(Alert, { severity: 'error' }, error)
63
return h(DataGrid, {
64
pageSize: 25,
65
+ rows,
66
columns: [
67
{
68
field: 'ip',
@@ -75,15 +74,16 @@ function Connections() {
74
field: 'v',
75
headerName: 'Protocol',
76
align: 'center',
77
+ hide: true,
78
renderCell: ({ value, row }) => h(Fragment, {},
79
'IPv' + value,
80
- row.secure && iconTooltip(Lock, "HTTPS", { opacity:.5 })
80
+ row.secure && iconTooltip(Lock, "HTTPS", { opacity: .5 })
81
)
82
},
83
{
84
field: 'outSpeed',
85
headerName: 'Speed',
86
- valueGetter: ({ value }) => formatBytes(value*1000, 'B/s', 1000)
86
+ valueGetter: ({ value }) => formatBytes(value * 1000, 'B/s', 1000)
87
},
88
{
89
field: 'sent',
@@ -95,6 +95,17 @@ function Connections() {
95
headerName: 'Started',
96
valueGetter: ({ value }) => new Date(value).toLocaleTimeString()
97
},
98
+ {
99
+ field: 'path',
100
+ headerName: 'Path',
101
+ flex: 1,
102
+ renderCell: ({ value }) => {
103
+ if (!value) return
104
+ const i = value?.lastIndexOf('/')
105
+ return h(Fragment, {}, value.slice(i + 1),
106
+ i > 0 && h(Box, { ml: 2, color: 'text.secondary' }, value.slice(0, i)))
107
+ }
108
+ },
109
{
110
field: 'Actions ',
111
width: 80,
@@ -109,7 +120,6 @@ function Connections() {
120
})
121
}
122
}
112
- ],
113
- rows,
123
+ ]
124
})
125
}
server/src/adminApis.ts
+8
-6
@@ -74,16 +74,18 @@ export const adminApis: ApiHandlers = {
74
) )
75
76
function serializeConnection(conn: Connection, minimal?:true) {
77
- const { socket, started, secure, got } = conn
77
+ const { socket, started, secure, got, path } = conn
78
return {
79
- v: minimal ? undefined : (socket.remoteFamily?.endsWith('6') ? 6 : 4),
79
port: socket.remotePort,
80
ip: socket.remoteAddress,
82
- got: minimal ? undefined : got,
83
- started: minimal ? undefined : started,
84
- secure: minimal ? undefined : (secure || undefined), // undefined will save some space once json-ed
81
+ ...!minimal && {
82
+ v: (socket.remoteFamily?.endsWith('6') ? 6 : 4),
83
+ got,
84
+ started,
85
+ path,
86
+ secure: (secure || undefined), // undefined will save some space once json-ed
87
+ }
88
}
86
-
89
}
90
}
91
server/src/connections.ts
+2
-1
@@ -10,7 +10,8 @@ export interface Connection {
10
got: number
11
sent: number
12
outSpeed?: number
13
- [rest:symbol]: any, // let other modules add extra data, but using symbols to avoid name collision
13
+ path?: string
14
+ [rest:symbol]: any // let other modules add extra data, but using symbols to avoid name collision
15
}
16
17
const all: Connection[] = []
server/src/serveFile.ts
+4
@@ -11,6 +11,7 @@ import mm, { isMatch } from 'micromatch'
11
import _ from 'lodash'
12
import path from 'path'
13
import { promisify } from 'util'
14
+import { socket2connection, updateConnection } from './connections'
15
16
export function serveFileNode(node: VfsNode) : Koa.Middleware {
17
const { source, mime } = node
@@ -52,6 +53,9 @@ export function serveFile(source:string, mime?:string, modifier?:(s:string)=>str
53
if (ctx.fresh)
54
return ctx.status = 304
55
56
+ const conn = socket2connection(ctx.socket)
57
+ if (conn)
58
+ updateConnection(conn, { path: ctx.path })
59
if (modifier)
60
return ctx.body = modifier(String(await fs.readFile(source)))
61
if (!range) {
todo.md
-1
@@ -5,7 +5,6 @@
5
- merge accounts in config
6
- frontend: ok button to inputDialogs
7
- admin: in a group, show linked accounts
8
-- admin/monitor: show file currently downloaded
8
- admin/config: use filepicker for https files
9
- admin: warn in case of items with same name
10
- allowed referer