Merge pull request #164 from community-scripts/fix/show_modal_during_operation

fix: add loading modal for container operations
This commit is contained in:
Michel Roegl-Brunner
2025-10-16 15:52:06 +02:00
committed by GitHub
2 changed files with 58 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ import { Button } from './ui/button';
import { ScriptInstallationCard } from './ScriptInstallationCard';
import { ConfirmationModal } from './ConfirmationModal';
import { ErrorModal } from './ErrorModal';
import { LoadingModal } from './LoadingModal';
import { getContrastColor } from '../../lib/colorUtils';
import {
DropdownMenu,
@@ -84,6 +85,12 @@ export function InstalledScriptsTab() {
type?: 'error' | 'success';
} | null>(null);
// Loading modal state
const [loadingModal, setLoadingModal] = useState<{
isOpen: boolean;
action: string;
} | null>(null);
// Fetch installed scripts
const { data: scriptsData, refetch: refetchScripts, isLoading } = api.installedScripts.getAllInstalledScripts.useQuery();
const { data: statsData } = api.installedScripts.getInstallationStats.useQuery();
@@ -247,6 +254,7 @@ export function InstalledScriptsTab() {
const controlContainerMutation = api.installedScripts.controlContainer.useMutation({
onSuccess: (data, variables) => {
setLoadingModal(null);
setControllingScriptId(null);
if (data.success) {
@@ -287,6 +295,7 @@ export function InstalledScriptsTab() {
},
onError: (error) => {
console.error('Container control error:', error);
setLoadingModal(null);
setControllingScriptId(null);
// Show detailed error message
@@ -302,6 +311,7 @@ export function InstalledScriptsTab() {
const destroyContainerMutation = api.installedScripts.destroyContainer.useMutation({
onSuccess: (data) => {
setLoadingModal(null);
setControllingScriptId(null);
if (data.success) {
@@ -326,6 +336,7 @@ export function InstalledScriptsTab() {
},
onError: (error) => {
console.error('Container destroy error:', error);
setLoadingModal(null);
setControllingScriptId(null);
// Show detailed error message
@@ -515,6 +526,7 @@ export function InstalledScriptsTab() {
message: `Are you sure you want to ${action} container ${script.container_id} (${script.script_name})?`,
onConfirm: () => {
setControllingScriptId(script.id);
setLoadingModal({ isOpen: true, action: `${action === 'start' ? 'Starting' : 'Stopping'} container ${script.container_id}...` });
void controlContainerMutation.mutate({ id: script.id, action });
setConfirmationModal(null);
}
@@ -535,6 +547,7 @@ export function InstalledScriptsTab() {
confirmText: script.container_id,
onConfirm: () => {
setControllingScriptId(script.id);
setLoadingModal({ isOpen: true, action: `Destroying container ${script.container_id}...` });
void destroyContainerMutation.mutate({ id: script.id });
setConfirmationModal(null);
}
@@ -1566,6 +1579,14 @@ export function InstalledScriptsTab() {
type={errorModal.type ?? 'error'}
/>
)}
{/* Loading Modal */}
{loadingModal && (
<LoadingModal
isOpen={loadingModal.isOpen}
action={loadingModal.action}
/>
)}
</div>
);
}

View File

@@ -0,0 +1,37 @@
'use client';
import { Loader2 } from 'lucide-react';
interface LoadingModalProps {
isOpen: boolean;
action: string;
}
export function LoadingModal({ isOpen, action }: LoadingModalProps) {
if (!isOpen) return null;
return (
<div className="fixed inset-0 backdrop-blur-sm bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-card rounded-lg shadow-xl max-w-md w-full border border-border p-8">
<div className="flex flex-col items-center space-y-4">
<div className="relative">
<Loader2 className="h-12 w-12 animate-spin text-primary" />
<div className="absolute inset-0 rounded-full border-2 border-primary/20 animate-pulse"></div>
</div>
<div className="text-center">
<h3 className="text-lg font-semibold text-card-foreground mb-2">
Processing
</h3>
<p className="text-sm text-muted-foreground">
{action}
</p>
<p className="text-xs text-muted-foreground mt-2">
Please wait...
</p>
</div>
</div>
</div>
</div>
);
}