This commit includes comprehensive codebase cleanup and refactoring: ## Code Cleanup - Remove dead TypeScript code (types/monitoring.ts - 194 lines duplicate) - Remove unused Go functions (GetClusterNodes, MigratePassword, GetClusterHealthInfo) - Clean up commented-out code blocks across multiple files - Remove unused TypeScript exports (helpTextClass, private tag color helpers) - Delete obsolete test files and components ## localStorage Consolidation - Centralize all storage keys into STORAGE_KEYS constant - Update 5 files to use centralized keys: * utils/apiClient.ts (AUTH, LEGACY_TOKEN) * components/Dashboard/Dashboard.tsx (GUEST_METADATA) * components/Docker/DockerHosts.tsx (DOCKER_METADATA) * App.tsx (PLATFORMS_SEEN) * stores/updates.ts (UPDATES) - Benefits: Single source of truth, prevents typos, better maintainability ## Previous Work Committed - Docker monitoring improvements and disk metrics - Security enhancements and setup fixes - API refactoring and cleanup - Documentation updates - Build system improvements ## Testing - All frontend tests pass (29 tests) - All Go tests pass (15 packages) - Production build successful - Zero breaking changes Total: 186 files changed, 5825 insertions(+), 11602 deletions(-)
144 lines
4.6 KiB
TypeScript
144 lines
4.6 KiB
TypeScript
import { Component, JSX, createSignal, ErrorBoundary as SolidErrorBoundary } from 'solid-js';
|
|
import { logError } from '@/utils/logger';
|
|
import { SectionHeader } from '@/components/shared/SectionHeader';
|
|
|
|
interface ErrorBoundaryProps {
|
|
children: JSX.Element;
|
|
fallback?: (error: Error, reset: () => void) => JSX.Element;
|
|
onError?: (error: Error) => void;
|
|
}
|
|
|
|
const DefaultErrorFallback: Component<{ error: Error; reset: () => void }> = (props) => {
|
|
const [details, setDetails] = createSignal(false);
|
|
|
|
return (
|
|
<div class="min-h-screen flex items-center justify-center bg-gray-100 dark:bg-gray-900 p-4">
|
|
<div class="max-w-md w-full bg-white dark:bg-gray-800 rounded-lg shadow-lg p-6">
|
|
<div class="flex items-center mb-4">
|
|
<svg
|
|
class="w-12 h-12 text-red-500 mr-3"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
/>
|
|
</svg>
|
|
<div>
|
|
<SectionHeader
|
|
title="Something went wrong"
|
|
description="An unexpected error occurred"
|
|
size="md"
|
|
titleClass="text-gray-900 dark:text-gray-100"
|
|
descriptionClass="text-sm text-gray-600 dark:text-gray-400"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded p-3 mb-4">
|
|
<p class="text-sm text-red-800 dark:text-red-200">
|
|
Please try again or reload the page. If the problem persists, contact your administrator.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="flex gap-2">
|
|
<button
|
|
type="button"
|
|
onClick={props.reset}
|
|
class="flex-1 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
|
|
>
|
|
Try Again
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => window.location.reload()}
|
|
class="flex-1 px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
|
|
>
|
|
Reload Page
|
|
</button>
|
|
</div>
|
|
|
|
<div class="mt-4 text-xs text-gray-500 dark:text-gray-400 leading-relaxed">
|
|
Technical details are suppressed in this view. Check server logs for full context.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export const ErrorBoundary: Component<ErrorBoundaryProps> = (props) => {
|
|
return (
|
|
<SolidErrorBoundary
|
|
fallback={(error, reset) => {
|
|
// Log the error
|
|
logError('Error boundary caught error', error);
|
|
|
|
// Call custom error handler if provided
|
|
if (props.onError) {
|
|
props.onError(error);
|
|
}
|
|
|
|
// Render custom or default fallback
|
|
if (props.fallback) {
|
|
return props.fallback(error, reset);
|
|
}
|
|
|
|
return <DefaultErrorFallback error={error} reset={reset} />;
|
|
}}
|
|
>
|
|
{props.children}
|
|
</SolidErrorBoundary>
|
|
);
|
|
};
|
|
|
|
// Component-specific error boundary with more context
|
|
export const ComponentErrorBoundary: Component<{
|
|
name: string;
|
|
children: JSX.Element;
|
|
}> = (props) => {
|
|
return (
|
|
<ErrorBoundary
|
|
fallback={(error, reset) => (
|
|
<div class="p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded">
|
|
<div class="flex items-center mb-2">
|
|
<svg
|
|
class="w-5 h-5 text-red-500 mr-2"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
/>
|
|
</svg>
|
|
<SectionHeader
|
|
title={`Error in ${props.name}`}
|
|
size="sm"
|
|
titleClass="text-red-800 dark:text-red-200"
|
|
/>
|
|
</div>
|
|
<p class="text-xs text-red-700 dark:text-red-300 mb-2">{error.message}</p>
|
|
<button
|
|
type="button"
|
|
onClick={reset}
|
|
class="text-xs px-2 py-1 bg-red-600 text-white rounded hover:bg-red-700 transition-colors"
|
|
>
|
|
Retry
|
|
</button>
|
|
</div>
|
|
)}
|
|
onError={(error) => {
|
|
logError(`Error in component ${props.name}`, error);
|
|
}}
|
|
>
|
|
{props.children}
|
|
</ErrorBoundary>
|
|
);
|
|
};
|