@samitouri / QOSami-HFS / commits / 0602853c

admin/monitoring: disconnect-all button #797

Massimo Melina committed Nov 5, 2024 at 16:38 UTC 0602853caa5053bf4e02f0093deaef85d045fb35
3 files changed +21 -9
admin/src/MonitorPage.ts
+15 -6
@@ -3,7 +3,7 @@
3 import _ from "lodash"
4 import { createElement as h, useMemo, Fragment, useState } from "react"
5 import { apiCall, useApiEvents, useApiEx, useApiList } from "./api"
6 -import { LinkOff, Lock, FolderZip, Upload, Download, ChevronRight, ChevronLeft, History } from '@mui/icons-material'
6 +import { LinkOff as DisconnectIcon, Lock, FolderZip, Upload, Download, ChevronRight, ChevronLeft, History } from '@mui/icons-material'
7 import { Alert, Box, Chip, ChipProps, Grid } from '@mui/material'
8 import { DataTable } from './DataTable'
9 import {
@@ -11,14 +11,14 @@ import {
11 reactJoin,
12 } from "./misc"
13 import {
14 - IconBtn, IconProgress, iconTooltip, usePauseButton, useBreakpoint, Country, hTooltip, useToggleButton, Flex
14 + IconBtn, IconProgress, iconTooltip, usePauseButton, useBreakpoint, Country, hTooltip, useToggleButton, Flex, Btn
15 } from './mui'
16 import { Field, SelectField } from '@hfs/mui-grid-form'
17 import { StandardCSSProperties } from '@mui/system/styleFunctionSx/StandardCssProperties'
18 import { agentIcons, LogFile } from './LogsPage'
19 import { state, useSnapState } from './state'
20 import { useBlockIp } from './useBlockIp'
21 -import { alertDialog, confirmDialog } from './dialog'
21 +import { alertDialog, confirmDialog, toast } from './dialog'
22 import { useInterval } from 'usehooks-ts'
23 import { PageProps } from './App'
24
@@ -129,7 +129,7 @@ function Connections() {
129 const logSize = logAble && wantLog ? 6 : 0
130 return h(Fragment, {},
131 h(Flex, {},
132 - h(Box, { flex: 1 },
132 + h(Flex, { flex: 1 },
133 h(SelectField as Field<boolean>, {
134 fullWidth: false,
135 value: monitorOnlyFiles,
@@ -147,7 +147,16 @@ function Connections() {
147 error,
148 rows,
149 noRows: monitorOnlyFiles && "No downloads at the moment",
150 - footerSide: () => pauseButton,
150 + footerSide: () => h(Flex, {},
151 + pauseButton,
152 + h(Btn, {
153 + size: 'small',
154 + icon: DisconnectIcon,
155 + labelIf: 'xl',
156 + confirm: "Disconnecting all connections but localhost. Continue?",
157 + onClick: () => apiCall('disconnect', { allButLocalhost: true }).then(x => toast(`Disconnected: ${x.result}`))
158 + }, "Disconnect all")
159 + ),
160 columns: [
161 {
162 field: 'ip',
@@ -249,7 +258,7 @@ function Connections() {
258 actionsProps: { hideUnder: 'sm' },
259 actions: ({ row }) => [
260 h(IconBtn, {
252 - icon: LinkOff,
261 + icon: DisconnectIcon,
262 title: "Disconnect",
263 doneMessage: true,
264 onClick: () => apiCall('disconnect', _.pick(row, ['ip', 'port'])).then(x => x.result > 0)
admin/src/mui.ts
+2
@@ -148,6 +148,8 @@ export const Btn = forwardRef(({ icon, title, onClick, disabled, progress, link,
148 if (link)
149 onClick = () => window.open(link)
150 const showLabel = useBreakpoint(_.isString(labelIf) ? labelIf : 'xs') && (_.isBoolean(labelIf) ? labelIf : true)
151 + if (!showLabel)
152 + title = children
153 const ref = useRefPass<HTMLButtonElement>(forwarded)
154 const common = _.merge(propsForModifiedValues(modified), {
155 ref,
src/api.monitor.ts
+4 -3
@@ -2,7 +2,7 @@
2
3 import _ from 'lodash'
4 import { Connection, getConnections } from './connections'
5 -import { apiAssertTypes, shortenAgent, try_, wait, wantArray } from './misc'
5 +import { apiAssertTypes, isLocalHost, shortenAgent, try_, wait, wantArray } from './misc'
6 import { ApiHandlers } from './apiMiddleware'
7 import Koa from 'koa'
8 import { totalGot, totalInSpeed, totalOutSpeed, totalSent } from './throttler'
@@ -12,8 +12,9 @@ import { storedMap } from './persistence'
12
13 export default {
14
15 - async disconnect({ ip, port }) {
16 - const match = _.matches({ ip, port })
15 + async disconnect({ ip, port, allButLocalhost }) {
16 + const match = allButLocalhost ? ((x: any) => !isLocalHost(x.ip))
17 + : _.matches({ ip, port })
18 const found = getConnections().filter(c => match(getConnAddress(c)))
19 for (const c of found)
20 c.socket.destroy()