authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-17 20:19:16-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-17 20:19:16-07:00
log6088c8104cfda0c11eafd1e1f636d47106fee136
tree293f7a31f5e53fc3b00da30fe4fcf469c3e0ed15
parenta1390ac655927cda10cfab3e4678d456db7b54b8
signature Signed by PGP key B5690EEEBB952194

refactor(web): share diagnostic process actions (#12358)


3 files changed, 53 insertions(+), 66 deletions(-)

apps/web/src/components/settings/DiagnosticsSettings.tsx+3-48
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1import { ProcessSignalActions } from "./ProcessSignalActions";
1import { RefreshIcon } from "~/components/ui/refresh-icon";2import { RefreshIcon } from "~/components/ui/refresh-icon";
2import {3import {
3 AlertTriangleIcon,4 AlertTriangleIcon,
...@@ -309,51 +310,6 @@ function ProcessNameCell({...@@ -309,51 +310,6 @@ function ProcessNameCell({
309 );310 );
310}311}
311312
312function ProcessSignalActions({
313 process,
314 isSignaling,
315 onSignal,
316}: {
317 process: ServerProcessDiagnosticsEntry;
318 isSignaling: boolean;
319 onSignal: (pid: number, signal: ServerProcessSignal) => void;
320}) {
321 return (
322 <div className="flex items-center justify-end gap-1.5">
323 <Tooltip>
324 <TooltipTrigger
325 render={
326 <button
327 type="button"
328 disabled={isSignaling}
329 className="cursor-pointer text-[11px] font-medium text-muted-foreground underline-offset-2 hover:text-foreground hover:underline disabled:pointer-events-none disabled:opacity-50"
330 onClick={() => onSignal(process.pid, "SIGINT")}
331 >
332 INT
333 </button>
334 }
335 />
336 <TooltipPopup side="top">Send SIGINT</TooltipPopup>
337 </Tooltip>
338 <Tooltip>
339 <TooltipTrigger
340 render={
341 <button
342 type="button"
343 disabled={isSignaling}
344 className="cursor-pointer text-[11px] font-medium text-destructive underline-offset-2 hover:underline disabled:pointer-events-none disabled:opacity-50"
345 onClick={() => onSignal(process.pid, "SIGKILL")}
346 >
347 KILL
348 </button>
349 }
350 />
351 <TooltipPopup side="top">Send SIGKILL</TooltipPopup>
352 </Tooltip>
353 </div>
354 );
355}
356
357function ProcessDiagnosticsTable({313function ProcessDiagnosticsTable({
358 processes,314 processes,
359 signalingPid,315 signalingPid,
...@@ -469,9 +425,8 @@ function ProcessDiagnosticsTable({...@@ -469,9 +425,8 @@ function ProcessDiagnosticsTable({
469 </td>425 </td>
470 <td className="p-2 align-middle sm:pr-4">426 <td className="p-2 align-middle sm:pr-4">
471 <ProcessSignalActions427 <ProcessSignalActions
472 process={process}428 disabled={signalingPid === process.pid}
473 isSignaling={signalingPid === process.pid}429 onSignal={(signal) => onSignal(process.pid, signal)}
474 onSignal={onSignal}
475 />430 />
476 </td>431 </td>
477 </tr>432 </tr>
apps/web/src/components/settings/ProcessSignalActions.tsx created+48
...@@ -0,0 +1,48 @@
1import type { ServerProcessSignal } from "@t3tools/contracts";
2
3import { InlineButton } from "../ui/button";
4import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
5
6/** Process ownership and confirmation stay with the diagnostics view. */
7export function ProcessSignalActions({
8 disabled,
9 onSignal,
10}: {
11 disabled: boolean;
12 onSignal: (signal: ServerProcessSignal) => void;
13}) {
14 return (
15 <div className="flex items-center justify-end gap-1.5">
16 <Tooltip>
17 <TooltipTrigger
18 render={
19 <InlineButton
20 disabled={disabled}
21 aria-label="Send SIGINT"
22 className="text-[11px] font-medium text-muted-foreground underline-offset-2 hover:text-foreground hover:underline"
23 onClick={() => onSignal("SIGINT")}
24 >
25 INT
26 </InlineButton>
27 }
28 />
29 <TooltipPopup side="top">Send SIGINT</TooltipPopup>
30 </Tooltip>
31 <Tooltip>
32 <TooltipTrigger
33 render={
34 <InlineButton
35 disabled={disabled}
36 aria-label="Send SIGKILL"
37 className="text-[11px] font-medium text-destructive underline-offset-2 hover:underline"
38 onClick={() => onSignal("SIGKILL")}
39 >
40 KILL
41 </InlineButton>
42 }
43 />
44 <TooltipPopup side="top">Send SIGKILL</TooltipPopup>
45 </Tooltip>
46 </div>
47 );
48}
apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx+2-18
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1import { ProcessSignalActions } from "./ProcessSignalActions";
1import { RefreshIcon } from "~/components/ui/refresh-icon";2import { RefreshIcon } from "~/components/ui/refresh-icon";
2import {3import {
3 ActivityIcon,4 ActivityIcon,
...@@ -535,24 +536,7 @@ function ProcessActions({...@@ -535,24 +536,7 @@ function ProcessActions({
535 }536 }
536 const isSignaling = signalingKeys.has(processIdentityKey(process));537 const isSignaling = signalingKeys.has(processIdentityKey(process));
537 return (538 return (
538 <div className="flex items-center justify-end gap-1.5">539 <ProcessSignalActions disabled={isSignaling} onSignal={(signal) => onSignal(process, signal)} />
539 <button
540 type="button"
541 disabled={isSignaling}
542 className="cursor-pointer text-[10px] font-semibold text-muted-foreground hover:text-foreground disabled:opacity-50"
543 onClick={() => onSignal(process, "SIGINT")}
544 >
545 INT
546 </button>
547 <button
548 type="button"
549 disabled={isSignaling}
550 className="cursor-pointer text-[10px] font-semibold text-destructive hover:underline disabled:opacity-50"
551 onClick={() => onSignal(process, "SIGKILL")}
552 >
553 KILL
554 </button>
555 </div>
556 );540 );
557}541}
558542