Adds a "Pending Setup" status so the user knows they need to select groups before their streams are imported.

This commit is contained in:
SergeantPanda 2025-05-05 19:50:20 -05:00
parent 898224dc72
commit ae93bc2a1f
6 changed files with 42 additions and 14 deletions

View file

@ -20,6 +20,7 @@ class M3UAccount(models.Model):
PARSING = "parsing", "Parsing"
ERROR = "error", "Error"
SUCCESS = "success", "Success"
PENDING_SETUP = "pending_setup", "Pending Setup"
"""Represents an M3U Account for IPTV streams."""
name = models.CharField(

View file

@ -28,17 +28,10 @@ def create_or_update_refresh_task(sender, instance, **kwargs):
period=IntervalSchedule.HOURS
)
if not instance.refresh_task:
refresh_task = PeriodicTask.objects.create(
name=task_name,
interval=interval,
task="apps.m3u.tasks.refresh_single_m3u_account",
kwargs=json.dumps({"account_id": instance.id}),
enabled=instance.refresh_interval != 0,
)
M3UAccount.objects.filter(id=instance.id).update(refresh_task=refresh_task)
else:
task = instance.refresh_task
# First check if the task already exists to avoid validation errors
try:
task = PeriodicTask.objects.get(name=task_name)
# Task exists, just update it
updated_fields = []
if task.enabled != (instance.refresh_interval != 0):
@ -52,6 +45,21 @@ def create_or_update_refresh_task(sender, instance, **kwargs):
if updated_fields:
task.save(update_fields=updated_fields)
# Ensure instance has the task
if instance.refresh_task_id != task.id:
M3UAccount.objects.filter(id=instance.id).update(refresh_task=task)
except PeriodicTask.DoesNotExist:
# Create new task if it doesn't exist
refresh_task = PeriodicTask.objects.create(
name=task_name,
interval=interval,
task="apps.m3u.tasks.refresh_single_m3u_account",
kwargs=json.dumps({"account_id": instance.id}),
enabled=instance.refresh_interval != 0,
)
M3UAccount.objects.filter(id=instance.id).update(refresh_task=refresh_task)
@receiver(post_delete, sender=M3UAccount)
def delete_refresh_task(sender, instance, **kwargs):
"""

View file

@ -547,7 +547,13 @@ def refresh_m3u_groups(account_id, use_cache=False, full_refresh=False):
release_task_lock('refresh_m3u_account_groups', account_id)
send_m3u_update(account_id, "processing_groups", 100)
# Use update() instead of save() to avoid triggering signals
M3UAccount.objects.filter(id=account_id).update(
status=M3UAccount.Status.PENDING_SETUP,
last_message="M3U groups loaded. Please select groups or refresh M3U to complete setup."
)
send_m3u_update(account_id, "processing_groups", 100, status="pending_setup", message="M3U groups loaded. Please select groups or refresh M3U to complete setup.")
if not full_refresh:
channel_layer = get_channel_layer()

View file

@ -190,8 +190,8 @@ export const WebsocketProvider = ({ children }) => {
// Update the store with progress information
setRefreshProgress(parsedEvent.data);
// If complete (progress is 100%), also update the playlist status
if (parsedEvent.data.progress === 100 && parsedEvent.data.account) {
// Always update status for pending_setup, not just when progress is 100%
if ((parsedEvent.data.progress === 100 || parsedEvent.data.status === "pending_setup") && parsedEvent.data.account) {
const playlistsState = usePlaylistsStore.getState();
const playlist = playlistsState.playlists.find(p => p.id === parsedEvent.data.account);

View file

@ -35,6 +35,17 @@ export default function M3URefreshNotification() {
[data.account]: data,
});
// Special handling for pending setup status
if (data.status === "pending_setup") {
notifications.show({
title: `M3U Setup: ${playlist.name}`,
message: data.message || "M3U groups loaded. Please select groups or refresh M3U to complete setup.",
color: 'orange.5',
autoClose: 5000, // Keep visible a bit longer
});
return;
}
// Check for error status FIRST before doing anything else
if (data.status === "error") {
// Only show the error notification if we have a complete task (progress=100)

View file

@ -33,6 +33,7 @@ const formatStatusText = (status) => {
case 'parsing': return 'Parsing';
case 'error': return 'Error';
case 'success': return 'Success';
case 'pending_setup': return '⚠️ Pending Setup';
default: return status ? status.charAt(0).toUpperCase() + status.slice(1) : 'Unknown';
}
};
@ -45,6 +46,7 @@ const getStatusColor = (status) => {
case 'parsing': return 'indigo.5';
case 'error': return 'red.5';
case 'success': return 'green.5';
case 'pending_setup': return 'orange.5'; // Orange to indicate action needed
default: return 'gray.5';
}
};