admin/logs: copy-request button

Massimo Melina committed Mar 14, 2025 at 15:17 UTC 051736549a246eb01760212ff2f64eaabf70be90
1 file changed +12 -4
admin/src/LogsPage.ts
+12 -4
@@ -6,15 +6,17 @@ import { Box, Tab, Tabs } from '@mui/material'
6 import { API_URL, apiCall, useApi, useApiList } from './api'
7 import { DataTable, DataTableColumn, DataTableProps } from './DataTable'
8 import {
9 - CFG, Dict, formatBytes, HTTP_UNAUTHORIZED, newDialog, prefix, shortenAgent, splitAt, tryJson, md,
10 - typedKeys, _dbg, mapFilter, safeDecodeURIComponent, stringAfter, onlyTruthy, formatTimestamp, formatSpeed
9 + CFG, Dict, formatBytes, HTTP_UNAUTHORIZED, newDialog, prefix, shortenAgent, splitAt, tryJson, md, typedKeys,
10 + _dbg, mapFilter, safeDecodeURIComponent, stringAfter, onlyTruthy, formatTimestamp, formatSpeed, copyTextToClipboard
11 } from '@hfs/shared'
12 import {
13 NetmaskField, Flex, IconBtn, useBreakpoint, usePauseButton, useToggleButton, WildcardsSupported, Country,
14 hTooltip, Btn, wikiLink
15 } from './mui';
16 import _ from 'lodash'
17 -import { AutoDelete, LinkOff, ClearAll, Delete, Download, Settings, SmartToy, Terminal } from '@mui/icons-material'
17 +import {
18 + AutoDelete, LinkOff, ClearAll, Delete, Download, Settings, SmartToy, Terminal, ContentCopy
19 +} from '@mui/icons-material'
20 import { ConfigForm } from './ConfigForm'
21 import { BoolField, SelectField } from '@hfs/mui-grid-form'
22 import { toast, useDialogBarColors } from './dialog'
@@ -117,7 +119,8 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
119 const invert = true
120 const [firstSight, setFirstSight] = useState(!hidden)
121 useEffect(() => setFirstSight(x => x || !hidden), [hidden])
120 - useApi(firstSight && LOGS_ON_FILE.includes(file) && 'get_log_file', { file, range: limited || !skipped ? -MAX : `0-${skipped}` }, {
122 + const hasFile = LOGS_ON_FILE.includes(file)
123 + useApi(firstSight && hasFile && 'get_log_file', { file, range: limited || !skipped ? -MAX : `0-${skipped}` }, {
124 skipParse: true, skipLog: true,
125 onResponse(res, body) {
126 const lines = body.split('\n')
@@ -190,6 +193,11 @@ export function LogFile({ file, footerSide, hidden, limit, filter, ...rest }: Lo
193 title: `Delete all records up to ${formatTimestamp(row.ts)}`,
194 onClick: () => apiCall('delete_ips', { ts: row.ts }).then(res => toast(`${res.n} deleted`)).then(reload)
195 }),
196 + hasFile && h(Btn, {
197 + icon: ContentCopy,
198 + title: "Copy request",
199 + onClick() { copyTextToClipboard(JSON.stringify(_.omit(row, 'id'), undefined, 2)) }
200 + })
201 ])),
202 initialState: isIps ? { sorting: { sortModel: [{ field: 'ts', sort: 'desc' }] } } : undefined,
203 ...rest,