mirror of
https://github.com/community-scripts/ProxmoxVE-Local.git
synced 2026-08-01 01:48:52 -04:00
* Fix server column alignment in installed scripts table
- Add text-left class to server column td element
- Add inline-block class to server name span element
- Ensures server column content aligns with header like other columns
* Fix UpdateableBadge overflow on smaller screens
- Add flex-wrap and gap classes to badge containers in ScriptCard and ScriptCardList
- Prevents badges from overflowing card boundaries on narrow screens
- Maintains proper spacing with gap-1/gap-2 for wrapped elements
- Improves responsive design for mobile and laptop screens
* Enhance action buttons with blueish theme and hover animations
- Update Edit, Update, Delete, Save, and Cancel buttons with color-coded themes
- Edit: Blue theme (bg-blue-50, text-blue-700)
- Update: Cyan theme (bg-cyan-50, text-cyan-700)
- Delete: Red theme (bg-red-50, text-red-700)
- Save: Green theme (bg-green-50, text-green-700)
- Cancel: Gray theme (bg-gray-50, text-gray-700)
- Add hover effects: scale-105, shadow-md, color transitions
- Apply consistent styling to both table and mobile card views
- Disabled buttons prevent scale animation and show proper cursor states
* Tone down button colors for better dark theme compatibility
- Replace bright flashbang colors with subtle dark theme variants
- Use 900-level colors with 20% opacity for backgrounds
- Use 300-level colors for text with 200-level on hover
- Use 700-level colors with 50% opacity for borders
- Maintain color coding but with much more subtle appearance
- Better contrast and readability against dark backgrounds
- No more flashbang effect! 😅
* Refactor button styling with semantic variants for uniform appearance
- Add semantic button variants: edit, update, delete, save, cancel
- Each variant has consistent dark theme colors and hover effects
- Remove custom className overrides from all button instances
- Centralize styling in Button component for maintainability
- All action buttons now use semantic variants instead of custom classes
- Much cleaner code and consistent styling across the application
* Remove rounded bottom border from active tab
- Add rounded-t-md rounded-b-none classes to active tab styling
- Creates flat bottom edge that connects seamlessly with content below
- Applied to all three tabs: Available Scripts, Downloaded Scripts, Installed Scripts
- Maintains rounded top corners for visual appeal while removing bottom rounding
* Apply flat bottom edge to tab hover states
- Add hover:rounded-t-md hover:rounded-b-none to inactive tab hover states
- Ensures consistent flat bottom edge on both active and hover states
- Creates uniform visual behavior across all tab interactions
- Maintains rounded top corners while removing bottom rounding on hover
187 lines
5.6 KiB
TypeScript
187 lines
5.6 KiB
TypeScript
'use client';
|
|
|
|
import { Button } from './ui/button';
|
|
import { StatusBadge } from './Badge';
|
|
import { getContrastColor } from '../../lib/colorUtils';
|
|
|
|
interface InstalledScript {
|
|
id: number;
|
|
script_name: string;
|
|
script_path: string;
|
|
container_id: string | null;
|
|
server_id: number | null;
|
|
server_name: string | null;
|
|
server_ip: string | null;
|
|
server_user: string | null;
|
|
server_password: string | null;
|
|
server_color: string | null;
|
|
installation_date: string;
|
|
status: 'in_progress' | 'success' | 'failed';
|
|
output_log: string | null;
|
|
}
|
|
|
|
interface ScriptInstallationCardProps {
|
|
script: InstalledScript;
|
|
isEditing: boolean;
|
|
editFormData: { script_name: string; container_id: string };
|
|
onInputChange: (field: 'script_name' | 'container_id', value: string) => void;
|
|
onEdit: () => void;
|
|
onSave: () => void;
|
|
onCancel: () => void;
|
|
onUpdate: () => void;
|
|
onDelete: () => void;
|
|
isUpdating: boolean;
|
|
isDeleting: boolean;
|
|
}
|
|
|
|
export function ScriptInstallationCard({
|
|
script,
|
|
isEditing,
|
|
editFormData,
|
|
onInputChange,
|
|
onEdit,
|
|
onSave,
|
|
onCancel,
|
|
onUpdate,
|
|
onDelete,
|
|
isUpdating,
|
|
isDeleting
|
|
}: ScriptInstallationCardProps) {
|
|
const formatDate = (dateString: string) => {
|
|
return new Date(dateString).toLocaleString();
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className="bg-card border border-border rounded-lg p-4 shadow-sm hover:shadow-md transition-shadow"
|
|
style={{ borderLeft: `4px solid ${script.server_color ?? 'transparent'}` }}
|
|
>
|
|
{/* Header with Script Name and Status */}
|
|
<div className="flex items-start justify-between mb-3">
|
|
<div className="flex-1 min-w-0">
|
|
{isEditing ? (
|
|
<div className="space-y-2">
|
|
<input
|
|
type="text"
|
|
value={editFormData.script_name}
|
|
onChange={(e) => onInputChange('script_name', e.target.value)}
|
|
className="w-full px-2 py-1 text-sm border border-border rounded bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary"
|
|
placeholder="Script name"
|
|
/>
|
|
<div className="text-xs text-muted-foreground">{script.script_path}</div>
|
|
</div>
|
|
) : (
|
|
<div>
|
|
<div className="text-sm font-medium text-foreground truncate">{script.script_name}</div>
|
|
<div className="text-xs text-muted-foreground truncate">{script.script_path}</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="ml-2 flex-shrink-0">
|
|
<StatusBadge status={script.status}>
|
|
{script.status.replace('_', ' ').toUpperCase()}
|
|
</StatusBadge>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Details Grid */}
|
|
<div className="grid grid-cols-1 gap-3 mb-4">
|
|
{/* Container ID */}
|
|
<div>
|
|
<div className="text-xs font-medium text-muted-foreground mb-1">Container ID</div>
|
|
{isEditing ? (
|
|
<input
|
|
type="text"
|
|
value={editFormData.container_id}
|
|
onChange={(e) => onInputChange('container_id', e.target.value)}
|
|
className="w-full px-2 py-1 text-sm font-mono border border-border rounded bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary"
|
|
placeholder="Container ID"
|
|
/>
|
|
) : (
|
|
<div className="text-sm font-mono text-foreground break-all">
|
|
{script.container_id ?? '-'}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Server */}
|
|
<div>
|
|
<div className="text-xs font-medium text-muted-foreground mb-1">Server</div>
|
|
<span
|
|
className="text-sm px-3 py-1 rounded inline-block"
|
|
style={{
|
|
backgroundColor: script.server_color ?? 'transparent',
|
|
color: script.server_color ? getContrastColor(script.server_color) : 'inherit'
|
|
}}
|
|
>
|
|
{script.server_name ?? '-'}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Installation Date */}
|
|
<div>
|
|
<div className="text-xs font-medium text-muted-foreground mb-1">Installation Date</div>
|
|
<div className="text-sm text-muted-foreground">
|
|
{formatDate(String(script.installation_date))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Action Buttons */}
|
|
<div className="flex flex-wrap gap-2">
|
|
{isEditing ? (
|
|
<>
|
|
<Button
|
|
onClick={onSave}
|
|
disabled={isUpdating}
|
|
variant="save"
|
|
size="sm"
|
|
className="flex-1 min-w-0"
|
|
>
|
|
{isUpdating ? 'Saving...' : 'Save'}
|
|
</Button>
|
|
<Button
|
|
onClick={onCancel}
|
|
variant="cancel"
|
|
size="sm"
|
|
className="flex-1 min-w-0"
|
|
>
|
|
Cancel
|
|
</Button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<Button
|
|
onClick={onEdit}
|
|
variant="edit"
|
|
size="sm"
|
|
className="flex-1 min-w-0"
|
|
>
|
|
Edit
|
|
</Button>
|
|
{script.container_id && (
|
|
<Button
|
|
onClick={onUpdate}
|
|
variant="update"
|
|
size="sm"
|
|
className="flex-1 min-w-0"
|
|
>
|
|
Update
|
|
</Button>
|
|
)}
|
|
<Button
|
|
onClick={onDelete}
|
|
variant="delete"
|
|
size="sm"
|
|
disabled={isDeleting}
|
|
className="flex-1 min-w-0"
|
|
>
|
|
{isDeleting ? 'Deleting...' : 'Delete'}
|
|
</Button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|