diff --git a/locales/en/public.json b/locales/en/public.json index e153c6746..9dc71b300 100644 --- a/locales/en/public.json +++ b/locales/en/public.json @@ -385,6 +385,7 @@ "DIAGNOSTICS_CARD_TITLE": "Diagnostics", "DIAGNOSTICS_GC_BUTTON": "Invoke Garbage Collection", "DIAGNOSTICS_HEAP_DUMP_BUTTON": "Invoke Heap Dump", + "DIAGNOSTICS_HEAP_DUMP_BUTTON_DISABLED": "Heap Dump collection requires the Cryostat Agent", "DIAGNOSTICS_HEAP_REDIRECT_BUTTON": "View collected Heap Dumps", "DIAGNOSTICS_THREAD_DUMP_BUTTON": "Invoke Thread Dump", "DIAGNOSTICS_THREAD_DUMP_TABLE_TOOLTIP": "View captured Thread Dumps", diff --git a/src/app/Dashboard/Diagnostics/DiagnosticsCard.tsx b/src/app/Dashboard/Diagnostics/DiagnosticsCard.tsx index 64e0464ff..aefeaa8b8 100644 --- a/src/app/Dashboard/Diagnostics/DiagnosticsCard.tsx +++ b/src/app/Dashboard/Diagnostics/DiagnosticsCard.tsx @@ -43,6 +43,7 @@ import { Tooltip, Stack, StackItem, + ActionListItem, } from '@patternfly/react-core'; import { ListIcon, WrenchIcon } from '@patternfly/react-icons'; import * as React from 'react'; @@ -56,7 +57,9 @@ export const DiagnosticsCard: DashboardCardFC = (props) => const serviceContext = React.useContext(ServiceContext); const notifications = React.useContext(NotificationsContext); const addSubscription = useSubscriptions(); - const [running, setRunning] = React.useState(false); + const [runningGc, setRunningGc] = React.useState(false); + const [runningThreadDump, setRunningThreadDump] = React.useState(false); + const [runningHeapDump, setRunningHeapDump] = React.useState(false); const [heapDumpReady, setHeapDumpReady] = React.useState(false); const [threadDumpReady, setThreadDumpReady] = React.useState(false); const [controlEnabled, setControlEnabled] = React.useState(false); @@ -126,39 +129,39 @@ export const DiagnosticsCard: DashboardCardFC = (props) => }, [addSubscription, serviceContext.notificationChannel, setThreadDumpReady]); const handleGC = React.useCallback(() => { - setRunning(true); + setRunningGc(true); addSubscription( serviceContext.api.runGC(true).subscribe({ error: (err) => handleError(t('DiagnosticsCard.KINDS.GC'), err), - complete: () => setRunning(false), + complete: () => setRunningGc(false), }), ); - }, [addSubscription, serviceContext.api, handleError, setRunning, t]); + }, [addSubscription, serviceContext.api, handleError, setRunningGc, t]); const handleThreadDump = React.useCallback(() => { - setRunning(true); + setRunningThreadDump(true); addSubscription( serviceContext.api.runThreadDump(true).subscribe({ error: (err) => handleError(t('DiagnosticsCard.KINDS.THREADS'), err), complete: () => { - setRunning(false); + setRunningThreadDump(false); setThreadDumpReady(true); }, }), ); - }, [addSubscription, serviceContext.api, handleError, setRunning, t]); + }, [addSubscription, serviceContext.api, handleError, setRunningThreadDump, t]); const handleHeapDump = React.useCallback(() => { - setRunning(true); + setRunningHeapDump(true); addSubscription( serviceContext.api.runHeapDump(true).subscribe({ error: (err) => handleError(t('DiagnosticsCard.KINDS.HEAP_DUMP'), err), complete: () => { - setRunning(false); + setRunningHeapDump(false); }, }), ); - }, [addSubscription, serviceContext.api, handleError, setRunning, t]); + }, [addSubscription, serviceContext.api, handleError, setRunningHeapDump, t]); const header = React.useMemo(() => { return ( @@ -193,58 +196,73 @@ export const DiagnosticsCard: DashboardCardFC = (props) => - + + + - - + + + + + - - + + + + + + + + - - + + + + + - - + + + + +