hot fixes for several UI and logic issues

This commit is contained in:
2025-11-17 15:41:51 -06:00
parent 5f2314a532
commit 72c4f3d29b
13 changed files with 233 additions and 93 deletions

View File

@@ -301,26 +301,71 @@ class ConfigService:
def delete_config(self, filename: str) -> None:
"""
Delete config file if not used by schedules.
Delete config file and cascade delete any associated schedules.
When a config is deleted, all schedules using that config (both enabled
and disabled) are automatically deleted as well, since they would be
invalid without the config file.
Args:
filename: Config filename to delete
Raises:
FileNotFoundError: If config doesn't exist
ValueError: If config used by active schedules
"""
filepath = os.path.join(self.configs_dir, filename)
if not os.path.exists(filepath):
raise FileNotFoundError(f"Config file '{filename}' not found")
# Check if used by schedules
schedules = self.get_schedules_using_config(filename)
if schedules:
schedule_list = ', '.join(schedules)
raise ValueError(
f"Cannot delete config '{filename}' because it is used by the following schedules: {schedule_list}"
# Delete any schedules using this config (both enabled and disabled)
try:
from web.services.schedule_service import ScheduleService
from flask import current_app
# Get database session from Flask app
db = current_app.db_session
# Get all schedules
schedule_service = ScheduleService(db)
result = schedule_service.list_schedules(page=1, per_page=10000)
schedules = result.get('schedules', [])
# Build full path for comparison
config_path = os.path.join(self.configs_dir, filename)
# Find and delete all schedules using this config (enabled or disabled)
deleted_schedules = []
for schedule in schedules:
schedule_config = schedule.get('config_file', '')
# Handle both absolute paths and just filenames
if schedule_config == filename or schedule_config == config_path:
schedule_id = schedule.get('id')
schedule_name = schedule.get('name', 'Unknown')
try:
schedule_service.delete_schedule(schedule_id)
deleted_schedules.append(schedule_name)
except Exception as e:
import logging
logging.getLogger(__name__).warning(
f"Failed to delete schedule {schedule_id} ('{schedule_name}'): {e}"
)
if deleted_schedules:
import logging
logging.getLogger(__name__).info(
f"Cascade deleted {len(deleted_schedules)} schedule(s) associated with config '{filename}': {', '.join(deleted_schedules)}"
)
except ImportError:
# If ScheduleService doesn't exist yet, skip schedule deletion
pass
except Exception as e:
# Log error but continue with config deletion
import logging
logging.getLogger(__name__).error(
f"Error deleting schedules for config {filename}: {e}", exc_info=True
)
# Delete file
@@ -404,30 +449,42 @@ class ConfigService:
# Import here to avoid circular dependency
try:
from web.services.schedule_service import ScheduleService
schedule_service = ScheduleService()
from flask import current_app
# Get all schedules
schedules = schedule_service.list_schedules()
# Get database session from Flask app
db = current_app.db_session
# Get all schedules (use large per_page to get all)
schedule_service = ScheduleService(db)
result = schedule_service.list_schedules(page=1, per_page=10000)
# Extract schedules list from paginated result
schedules = result.get('schedules', [])
# Build full path for comparison
config_path = os.path.join(self.configs_dir, filename)
# Find schedules using this config
# Find schedules using this config (only enabled schedules)
using_schedules = []
for schedule in schedules:
schedule_config = schedule.get('config_file', '')
# Handle both absolute paths and just filenames
if schedule_config == filename or schedule_config == config_path:
using_schedules.append(schedule.get('name', 'Unknown'))
# Only count enabled schedules
if schedule.get('enabled', False):
using_schedules.append(schedule.get('name', 'Unknown'))
return using_schedules
except ImportError:
# If ScheduleService doesn't exist yet, return empty list
return []
except Exception:
except Exception as e:
# If any error occurs, return empty list (safer than failing)
# Log the error for debugging
import logging
logging.getLogger(__name__).error(f"Error getting schedules using config {filename}: {e}", exc_info=True)
return []
def generate_filename_from_title(self, title: str) -> str: