Add scheduling-remote service to docker-compose and enhance camera error handling

- Introduced a new service for scheduling-remote in docker-compose.yml, allowing for better management of scheduling functionalities.
- Enhanced error handling in CameraMonitor and CameraStreamer classes to improve robustness during camera initialization and streaming processes.
- Updated various components in the management dashboard to support dark mode and improve user experience with consistent styling.
- Implemented feature flags for enabling/disabling modules, including the new scheduling module.
This commit is contained in:
salirezav
2025-11-02 19:33:13 -05:00
parent f6a37ca1ba
commit 868aa3f036
33 changed files with 7471 additions and 136 deletions

View File

@@ -195,11 +195,11 @@ export const CameraCard: React.FC<CameraCardProps> = ({
{isStreaming && (
<button
onClick={() => onStopStreaming(cameraName)}
className="px-3 py-2 text-sm font-medium text-white bg-orange-600 rounded-lg hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 transition-colors"
className="flex items-center justify-center px-3 py-2 text-sm font-medium text-white bg-orange-600 rounded-lg hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-orange-500 focus:ring-offset-2 transition-colors"
title="Stop streaming"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
<svg className="w-4 h-4 text-white" fill="none" stroke="currentColor" strokeWidth={2} viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
)}

View File

@@ -6,6 +6,8 @@ interface CameraPreviewModalProps {
isOpen: boolean
onClose: () => void
onError?: (error: string) => void
onStreamStarted?: () => void
onStreamStopped?: () => void
}
export const CameraPreviewModal: React.FC<CameraPreviewModalProps> = ({
@@ -13,6 +15,8 @@ export const CameraPreviewModal: React.FC<CameraPreviewModalProps> = ({
isOpen,
onClose,
onError,
onStreamStarted,
onStreamStopped,
}) => {
const [loading, setLoading] = useState(false)
const [streaming, setStreaming] = useState(false)
@@ -46,6 +50,9 @@ export const CameraPreviewModal: React.FC<CameraPreviewModalProps> = ({
if (imgRef.current) {
imgRef.current.src = `${streamUrl}?t=${Date.now()}`
}
// Notify parent that streaming started
onStreamStarted?.()
} else {
throw new Error(result.message)
}
@@ -68,6 +75,9 @@ export const CameraPreviewModal: React.FC<CameraPreviewModalProps> = ({
if (imgRef.current) {
imgRef.current.src = ''
}
// Notify parent that streaming stopped
onStreamStopped?.()
}
} catch (err) {
console.error('Error stopping stream:', err)
@@ -82,12 +92,13 @@ export const CameraPreviewModal: React.FC<CameraPreviewModalProps> = ({
if (!isOpen) return null
return (
<div className="fixed inset-0 z-[999999] flex items-center justify-center overflow-y-auto">
<div className="fixed inset-0 z-[999999] flex items-center justify-center overflow-y-auto p-4">
<div
className="fixed inset-0 h-full w-full bg-gray-900/60 backdrop-blur-sm"
className="fixed inset-0 h-full w-full bg-gray-900/70 backdrop-blur-md"
onClick={handleClose}
style={{ backdropFilter: 'blur(8px)', WebkitBackdropFilter: 'blur(8px)' }}
/>
<div className="relative w-11/12 max-w-5xl rounded-xl bg-white shadow-2xl dark:bg-gray-800 p-6" onClick={(e) => e.stopPropagation()}>
<div className="relative w-full max-w-4xl rounded-xl bg-white shadow-2xl dark:bg-gray-800 p-6" onClick={(e) => e.stopPropagation()}>
{/* Close Button */}
<button
onClick={handleClose}
@@ -148,7 +159,7 @@ export const CameraPreviewModal: React.FC<CameraPreviewModalProps> = ({
<img
ref={imgRef}
alt={`Live stream from ${cameraName}`}
className="w-full h-auto max-h-[70vh] object-contain"
className="w-full h-auto max-h-[60vh] object-contain"
onError={() => setError('Failed to load camera stream')}
/>
</div>