From f26db65121cc4f524fb11352e5ad32eda120ad3f Mon Sep 17 00:00:00 2001 From: jlightner Date: Fri, 3 Apr 2026 07:30:25 +0000 Subject: [PATCH] refactor: fold yt-dlp update controls into existing Health card, remove standalone section --- src/frontend/src/components/HealthStatus.tsx | 150 +++++++++++++++---- src/frontend/src/pages/System.tsx | 114 ++------------ 2 files changed, 130 insertions(+), 134 deletions(-) diff --git a/src/frontend/src/components/HealthStatus.tsx b/src/frontend/src/components/HealthStatus.tsx index 50cbc59..d97399d 100644 --- a/src/frontend/src/components/HealthStatus.tsx +++ b/src/frontend/src/components/HealthStatus.tsx @@ -1,6 +1,9 @@ -import { AlertTriangle, CheckCircle2, HardDrive, Play, Square, Terminal } from 'lucide-react'; +import { useState } from 'react'; +import { AlertTriangle, CheckCircle2, HardDrive, Loader2, Play, RefreshCw, Square, Terminal, CheckCircle, AlertCircle } from 'lucide-react'; import type { ComponentHealth } from '@shared/types/api'; import { formatBytes } from '../utils/format'; +import type { YtDlpStatusResponse, YtDlpUpdateResponse } from '@shared/types/api'; +import type { UseMutationResult } from '@tanstack/react-query'; // ── Status → color mapping ── @@ -27,9 +30,12 @@ const COMPONENT_LABELS: Record = { interface HealthStatusProps { components: ComponentHealth[]; overallStatus: 'healthy' | 'degraded' | 'unhealthy'; + ytdlpStatus?: YtDlpStatusResponse | null; + ytdlpLoading?: boolean; + updateYtDlp?: UseMutationResult; } -export function HealthStatus({ components, overallStatus }: HealthStatusProps) { +export function HealthStatus({ components, overallStatus, ytdlpStatus, ytdlpLoading, updateYtDlp }: HealthStatusProps) { const overallColors = STATUS_COLORS[overallStatus] ?? DEFAULT_COLORS; const overallLabel = overallStatus.charAt(0).toUpperCase() + overallStatus.slice(1); @@ -74,7 +80,13 @@ export function HealthStatus({ components, overallStatus }: HealthStatusProps) { }} > {components.map((comp) => ( - + ))} @@ -98,7 +110,12 @@ export function HealthStatus({ components, overallStatus }: HealthStatusProps) { // ── Component Card ── -function ComponentCard({ component }: { component: ComponentHealth }) { +function ComponentCard({ component, ytdlpStatus, ytdlpLoading, updateYtDlp }: { + component: ComponentHealth; + ytdlpStatus?: YtDlpStatusResponse | null; + ytdlpLoading?: boolean; + updateYtDlp?: UseMutationResult; +}) { const colors = STATUS_COLORS[component.status] ?? DEFAULT_COLORS; const label = COMPONENT_LABELS[component.name] ?? component.name; @@ -142,20 +159,24 @@ function ComponentCard({ component }: { component: ComponentHealth }) { - {/* Custom detail rendering per component type */} - + ); } // ── Detail Renderers ── -function ComponentDetail({ component }: { component: ComponentHealth }) { +function ComponentDetail({ component, ytdlpStatus, ytdlpLoading, updateYtDlp }: { + component: ComponentHealth; + ytdlpStatus?: YtDlpStatusResponse | null; + ytdlpLoading?: boolean; + updateYtDlp?: UseMutationResult; +}) { switch (component.name) { case 'diskSpace': return ; case 'ytDlp': - return ; + return ; case 'scheduler': return ; case 'recentErrors': @@ -233,30 +254,101 @@ function DiskSpaceDetail({ component }: { component: ComponentHealth }) { // ── yt-dlp ── -function YtDlpDetail({ component }: { component: ComponentHealth }) { +function YtDlpDetail({ component, ytdlpStatus, ytdlpLoading, updateYtDlp }: { + component: ComponentHealth; + ytdlpStatus?: YtDlpStatusResponse | null; + ytdlpLoading?: boolean; + updateYtDlp?: UseMutationResult; +}) { + const [updateMessage, setUpdateMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); const details = component.details as { version?: string } | undefined; return ( -
-
) : health ? ( - + ) : null} - {/* ── yt-dlp section ── */} -
-
-

- - yt-dlp -

-
- -
- {ytdlpLoading ? ( -

Loading yt-dlp status…

- ) : ytdlpError ? ( -

- Failed to load yt-dlp status: {ytdlpError instanceof Error ? ytdlpError.message : 'Unknown error'} -

- ) : ( - <> -
-
- Version -

- {ytdlpStatus?.version ?? 'Unknown'} -

-
-
- Last Updated -

- {ytdlpStatus?.lastUpdated ? new Date(ytdlpStatus.lastUpdated).toLocaleString() : 'Never'} -

-
-
- -
- - - {updateMessage && ( - - {updateMessage.type === 'success' ? : } - {updateMessage.text} - - )} -
- - )} -
- -

- Auto-refreshes every 60 seconds. -

-
- {/* ── System Status section ── */}