mirror of
https://github.com/lordmathis/llamactl.git
synced 2025-11-07 09:34:22 +00:00
Improve InstanceCard layout
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import type { Instance } from "@/types/instance";
|
import type { Instance } from "@/types/instance";
|
||||||
import { Edit, FileText, Play, Square, Trash2 } from "lucide-react";
|
import { Edit, FileText, Play, Square, Trash2, MoreHorizontal } from "lucide-react";
|
||||||
import LogsDialog from "@/components/LogDialog";
|
import LogsDialog from "@/components/LogDialog";
|
||||||
import HealthBadge from "@/components/HealthBadge";
|
import HealthBadge from "@/components/HealthBadge";
|
||||||
import BackendBadge from "@/components/BackendBadge";
|
import BackendBadge from "@/components/BackendBadge";
|
||||||
@@ -25,6 +25,7 @@ function InstanceCard({
|
|||||||
editInstance,
|
editInstance,
|
||||||
}: InstanceCardProps) {
|
}: InstanceCardProps) {
|
||||||
const [isLogsOpen, setIsLogsOpen] = useState(false);
|
const [isLogsOpen, setIsLogsOpen] = useState(false);
|
||||||
|
const [showAllActions, setShowAllActions] = useState(false);
|
||||||
const health = useInstanceHealth(instance.name, instance.status);
|
const health = useInstanceHealth(instance.name, instance.status);
|
||||||
|
|
||||||
const handleStart = () => {
|
const handleStart = () => {
|
||||||
@@ -55,39 +56,44 @@ function InstanceCard({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card>
|
<Card className="hover:shadow-md transition-shadow">
|
||||||
<CardHeader className="pb-3">
|
<CardHeader className="pb-4">
|
||||||
<div className="flex items-center justify-between">
|
{/* Header with instance name and status badges */}
|
||||||
<CardTitle className="text-lg">{instance.name}</CardTitle>
|
<div className="space-y-3">
|
||||||
<div className="flex flex-col items-end gap-2">
|
<CardTitle className="text-lg font-semibold leading-tight break-words">
|
||||||
{running && <HealthBadge health={health} />}
|
{instance.name}
|
||||||
|
</CardTitle>
|
||||||
|
|
||||||
|
{/* Badges row */}
|
||||||
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<BackendBadge backend={instance.options?.backend_type} />
|
<BackendBadge backend={instance.options?.backend_type} />
|
||||||
|
{running && <HealthBadge health={health} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent>
|
<CardContent className="pt-0">
|
||||||
<div className="flex gap-1">
|
{/* Primary actions - always visible */}
|
||||||
|
<div className="flex items-center gap-2 mb-3">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="outline"
|
variant={running ? "outline" : "default"}
|
||||||
onClick={handleStart}
|
onClick={running ? handleStop : handleStart}
|
||||||
disabled={running}
|
className="flex-1"
|
||||||
title="Start instance"
|
title={running ? "Stop instance" : "Start instance"}
|
||||||
data-testid="start-instance-button"
|
data-testid={running ? "stop-instance-button" : "start-instance-button"}
|
||||||
>
|
>
|
||||||
<Play className="h-4 w-4" />
|
{running ? (
|
||||||
</Button>
|
<>
|
||||||
|
<Square className="h-4 w-4 mr-1" />
|
||||||
<Button
|
Stop
|
||||||
size="sm"
|
</>
|
||||||
variant="outline"
|
) : (
|
||||||
onClick={handleStop}
|
<>
|
||||||
disabled={!running}
|
<Play className="h-4 w-4 mr-1" />
|
||||||
title="Stop instance"
|
Start
|
||||||
data-testid="stop-instance-button"
|
</>
|
||||||
>
|
)}
|
||||||
<Square className="h-4 w-4" />
|
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -100,14 +106,29 @@ function InstanceCard({
|
|||||||
<Edit className="h-4 w-4" />
|
<Edit className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
onClick={() => setShowAllActions(!showAllActions)}
|
||||||
|
title="More actions"
|
||||||
|
>
|
||||||
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Secondary actions - collapsible */}
|
||||||
|
{showAllActions && (
|
||||||
|
<div className="flex items-center gap-2 pt-2 border-t border-border">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={handleLogs}
|
onClick={handleLogs}
|
||||||
title="View logs"
|
title="View logs"
|
||||||
data-testid="view-logs-button"
|
data-testid="view-logs-button"
|
||||||
|
className="flex-1"
|
||||||
>
|
>
|
||||||
<FileText className="h-4 w-4" />
|
<FileText className="h-4 w-4 mr-1" />
|
||||||
|
Logs
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
@@ -121,6 +142,7 @@ function InstanceCard({
|
|||||||
<Trash2 className="h-4 w-4" />
|
<Trash2 className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user