Merge pull request #164 from community-scripts/fix/show_modal_during_operation
fix: add loading modal for container operations
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
37
src/app/_components/LoadingModal.tsx
Normal file
37
src/app/_components/LoadingModal.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user