feat: add log viewer components and fix build issues
Some checks failed
Build and Push Docker Image to Gitea / build-and-push (push) Failing after 53s
Some checks failed
Build and Push Docker Image to Gitea / build-and-push (push) Failing after 53s
- Add LogViewer component with syntax highlighting and auto-scroll - Add LogControls for play/pause, auto-scroll, refresh, download, clear - Add LogSearch component with search highlighting - Add Input UI component - Fix TypeScript type issues in ProcessCard and types.ts - Fix XML-RPC client type issues - Add force-dynamic to layout to prevent SSR issues with client components - Add mounted state to Navbar for theme toggle hydration - Add custom 404 page Components added: - components/logs/LogViewer.tsx - Main log viewer with real-time display - components/logs/LogControls.tsx - Control panel for log viewing - components/logs/LogSearch.tsx - Search input for filtering logs - components/ui/input.tsx - Reusable input component Fixes: - ProcessStateCode type casting in ProcessCard - XML-RPC client options type (use any to avoid library type issues) - canStartProcess/canStopProcess type assertions - Dynamic rendering to prevent SSR hydration issues 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
75
components/logs/LogControls.tsx
Normal file
75
components/logs/LogControls.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
'use client';
|
||||
|
||||
import { Play, Pause, RotateCcw, Download, Trash2 } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { cn } from '@/lib/utils/cn';
|
||||
|
||||
interface LogControlsProps {
|
||||
isPlaying: boolean;
|
||||
onPlayPause: () => void;
|
||||
autoScroll: boolean;
|
||||
onToggleAutoScroll: () => void;
|
||||
onRefresh: () => void;
|
||||
onClear?: () => void;
|
||||
onDownload?: () => void;
|
||||
isClearing?: boolean;
|
||||
}
|
||||
|
||||
export function LogControls({
|
||||
isPlaying,
|
||||
onPlayPause,
|
||||
autoScroll,
|
||||
onToggleAutoScroll,
|
||||
onRefresh,
|
||||
onClear,
|
||||
onDownload,
|
||||
isClearing = false,
|
||||
}: LogControlsProps) {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant={isPlaying ? 'destructive' : 'success'}
|
||||
size="sm"
|
||||
onClick={onPlayPause}
|
||||
title={isPlaying ? 'Pause auto-refresh' : 'Resume auto-refresh'}
|
||||
>
|
||||
{isPlaying ? <Pause className="h-4 w-4" /> : <Play className="h-4 w-4" />}
|
||||
{isPlaying ? 'Pause' : 'Play'}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant={autoScroll ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
onClick={onToggleAutoScroll}
|
||||
title={autoScroll ? 'Disable auto-scroll' : 'Enable auto-scroll'}
|
||||
>
|
||||
Auto-scroll
|
||||
</Button>
|
||||
|
||||
<Button variant="outline" size="sm" onClick={onRefresh} title="Refresh logs now">
|
||||
<RotateCcw className="h-4 w-4" />
|
||||
Refresh
|
||||
</Button>
|
||||
|
||||
{onDownload && (
|
||||
<Button variant="outline" size="sm" onClick={onDownload} title="Download logs">
|
||||
<Download className="h-4 w-4" />
|
||||
Download
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{onClear && (
|
||||
<Button
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
onClick={onClear}
|
||||
disabled={isClearing}
|
||||
title="Clear logs"
|
||||
>
|
||||
<Trash2 className={cn('h-4 w-4', isClearing && 'animate-spin')} />
|
||||
Clear
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user