diff --git a/admin/src/MonitorPage.ts b/admin/src/MonitorPage.ts index 26906fd3..44af14b0 100644 --- a/admin/src/MonitorPage.ts +++ b/admin/src/MonitorPage.ts @@ -3,7 +3,7 @@ import _ from "lodash" import { createElement as h, useMemo, Fragment, useState } from "react" import { apiCall, useApiEvents, useApiEx, useApiList } from "./api" -import { LinkOff, Lock, FolderZip, Upload, Download, ChevronRight, ChevronLeft, History } from '@mui/icons-material' +import { LinkOff as DisconnectIcon, Lock, FolderZip, Upload, Download, ChevronRight, ChevronLeft, History } from '@mui/icons-material' import { Alert, Box, Chip, ChipProps, Grid } from '@mui/material' import { DataTable } from './DataTable' import { @@ -11,14 +11,14 @@ import { reactJoin, } from "./misc" import { - IconBtn, IconProgress, iconTooltip, usePauseButton, useBreakpoint, Country, hTooltip, useToggleButton, Flex + IconBtn, IconProgress, iconTooltip, usePauseButton, useBreakpoint, Country, hTooltip, useToggleButton, Flex, Btn } from './mui' import { Field, SelectField } from '@hfs/mui-grid-form' import { StandardCSSProperties } from '@mui/system/styleFunctionSx/StandardCssProperties' import { agentIcons, LogFile } from './LogsPage' import { state, useSnapState } from './state' import { useBlockIp } from './useBlockIp' -import { alertDialog, confirmDialog } from './dialog' +import { alertDialog, confirmDialog, toast } from './dialog' import { useInterval } from 'usehooks-ts' import { PageProps } from './App' @@ -129,7 +129,7 @@ function Connections() { const logSize = logAble && wantLog ? 6 : 0 return h(Fragment, {}, h(Flex, {}, - h(Box, { flex: 1 }, + h(Flex, { flex: 1 }, h(SelectField as Field, { fullWidth: false, value: monitorOnlyFiles, @@ -147,7 +147,16 @@ function Connections() { error, rows, noRows: monitorOnlyFiles && "No downloads at the moment", - footerSide: () => pauseButton, + footerSide: () => h(Flex, {}, + pauseButton, + h(Btn, { + size: 'small', + icon: DisconnectIcon, + labelIf: 'xl', + confirm: "Disconnecting all connections but localhost. Continue?", + onClick: () => apiCall('disconnect', { allButLocalhost: true }).then(x => toast(`Disconnected: ${x.result}`)) + }, "Disconnect all") + ), columns: [ { field: 'ip', @@ -249,7 +258,7 @@ function Connections() { actionsProps: { hideUnder: 'sm' }, actions: ({ row }) => [ h(IconBtn, { - icon: LinkOff, + icon: DisconnectIcon, title: "Disconnect", doneMessage: true, onClick: () => apiCall('disconnect', _.pick(row, ['ip', 'port'])).then(x => x.result > 0) diff --git a/admin/src/mui.ts b/admin/src/mui.ts index c9fb5b0d..3a4f8aed 100644 --- a/admin/src/mui.ts +++ b/admin/src/mui.ts @@ -148,6 +148,8 @@ export const Btn = forwardRef(({ icon, title, onClick, disabled, progress, link, if (link) onClick = () => window.open(link) const showLabel = useBreakpoint(_.isString(labelIf) ? labelIf : 'xs') && (_.isBoolean(labelIf) ? labelIf : true) + if (!showLabel) + title = children const ref = useRefPass(forwarded) const common = _.merge(propsForModifiedValues(modified), { ref, diff --git a/src/api.monitor.ts b/src/api.monitor.ts index 49776b5b..f1c0b1b7 100644 --- a/src/api.monitor.ts +++ b/src/api.monitor.ts @@ -2,7 +2,7 @@ import _ from 'lodash' import { Connection, getConnections } from './connections' -import { apiAssertTypes, shortenAgent, try_, wait, wantArray } from './misc' +import { apiAssertTypes, isLocalHost, shortenAgent, try_, wait, wantArray } from './misc' import { ApiHandlers } from './apiMiddleware' import Koa from 'koa' import { totalGot, totalInSpeed, totalOutSpeed, totalSent } from './throttler' @@ -12,8 +12,9 @@ import { storedMap } from './persistence' export default { - async disconnect({ ip, port }) { - const match = _.matches({ ip, port }) + async disconnect({ ip, port, allButLocalhost }) { + const match = allButLocalhost ? ((x: any) => !isLocalHost(x.ip)) + : _.matches({ ip, port }) const found = getConnections().filter(c => match(getConnAddress(c))) for (const c of found) c.socket.destroy()