feat: Enhance frontend loading experience and service status handling
Some checks failed
Integration Tests / integration-tests (push) Failing after 20s
Integration Tests / performance-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.11) (push) Failing after 23s
Frontend (React) / test (20) (push) Failing after 1m3s
Frontend (React) / build (push) Has been skipped
Frontend (React) / lighthouse (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.12) (push) Failing after 23s
Service Adapters (Python FastAPI) / test (3.13) (push) Failing after 20s
Service Adapters (Python FastAPI) / build (push) Has been skipped

### Summary of Changes
- Removed proxy configuration in `rsbuild.config.js` as the API Gateway is not running.
- Added smooth transitions and gentle loading overlays in CSS for improved user experience during data loading.
- Updated `Dashboard` component to conditionally display loading spinner and gentle loading overlay based on data fetching state.
- Enhanced `useOfflineAwareServiceStatus` and `useOfflineAwareSystemData` hooks to manage loading states and service status more effectively.
- Increased refresh intervals for service status and system data to reduce API call frequency.

### Expected Results
- Improved user experience with smoother loading transitions and better feedback during data refreshes.
- Enhanced handling of service status checks, providing clearer information when services are unavailable.
- Streamlined code for managing loading states, making it easier to maintain and extend in the future.
This commit is contained in:
GSRN
2025-09-18 11:09:51 +02:00
parent 48c755dff3
commit 7373ccfa1d
30 changed files with 2402 additions and 89 deletions

View File

@@ -1,9 +1,14 @@
import logging
from datetime import datetime
from fastapi import APIRouter
from models.schemas import HealthResponse, RootResponse, ServiceStatus
from services.config import SERVICES
from services.status_checker import status_checker
# Configure logger
logger = logging.getLogger(__name__)
router = APIRouter()
@@ -29,9 +34,91 @@ async def root():
)
async def health_check():
"""Check the health status of the service adapters"""
logger.debug("Health check endpoint called")
return HealthResponse(status="healthy", timestamp=datetime.now().isoformat())
@router.get(
"/debug/logging",
summary="Logging Debug Info",
description="Get current logging configuration and test log levels",
tags=["Debug"],
)
async def debug_logging():
"""Debug endpoint to test unified logging configuration"""
# Test different log levels
logger.debug("This is a DEBUG message from routes.general")
logger.info("This is an INFO message from routes.general")
logger.warning("This is a WARNING message from routes.general")
logger.error("This is an ERROR message from routes.general")
# Test request logger
from services.logging_config import get_request_logger
request_logger = get_request_logger()
request_logger.info("This is a request logger message")
# Test application logger
from services.logging_config import get_application_logger
app_logger = get_application_logger()
app_logger.info("This is an application logger message")
# Get current logging configuration
root_logger = logging.getLogger()
config_info = {
"root_level": logging.getLevelName(root_logger.level),
"handlers": [str(h) for h in root_logger.handlers],
"handler_count": len(root_logger.handlers),
"status_checker_level": logging.getLevelName(logging.getLogger("services.status_checker").level),
"general_level": logging.getLevelName(logging.getLogger("routes.general").level),
"request_logger_level": logging.getLevelName(request_logger.level),
"application_logger_level": logging.getLevelName(app_logger.level),
"uvicorn_access_level": logging.getLevelName(logging.getLogger("uvicorn.access").level),
}
logger.info("Unified logging debug info requested")
return {
"message": "Unified log messages sent to console",
"config": config_info,
"note": "All logs now use the same format and handler"
}
@router.get(
"/debug/sensor/{service_name}",
summary="Debug Sensor Data",
description="Get raw sensor data for debugging health check issues",
tags=["Debug"],
)
async def debug_sensor(service_name: str):
"""Debug endpoint to inspect raw sensor data"""
from services.config import SERVICES
from services.health_checkers import factory
if service_name not in SERVICES:
return {"error": f"Service {service_name} not found"}
config = SERVICES[service_name]
if config.get("health_check_type") != "sensor":
return {"error": f"Service {service_name} is not using sensor health checking"}
try:
# Create sensor checker
checker = factory.create_checker("sensor", timeout=10.0)
# Get raw sensor data
result = await checker.check_health(service_name, config)
return {
"service_name": service_name,
"config": config,
"result": result.to_dict(),
"raw_sensor_data": result.metadata
}
except Exception as e:
logger.error(f"Error debugging sensor for {service_name}: {e}")
return {"error": str(e)}
@router.get(
"/services",
response_model=dict,
@@ -41,11 +128,23 @@ async def health_check():
)
async def get_services():
"""Get status of all configured external services (Home Assistant, Frigate, Immich, n8n)"""
logger.info("Service status endpoint called - checking all services")
# Check all services concurrently
status_results = await status_checker.check_all_services()
service_status = {}
for service_name, config in SERVICES.items():
status_info = status_results.get(service_name, {})
service_status[service_name] = ServiceStatus(
enabled=config["enabled"],
url=config["url"],
status="unknown", # Would check actual service status
status=status_info.get("status", "unknown"),
response_time=status_info.get("response_time"),
error=status_info.get("error"),
uptime=status_info.get("uptime"),
metadata=status_info.get("metadata", {})
)
logger.info(f"Service status check completed - returning status for {len(service_status)} services")
return service_status