using DiunaBI.UI.Shared.Services; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using DiunaBI.Application.DTOModels.Common; using DiunaBI.Domain.Entities; using MudBlazor; using Microsoft.JSInterop; namespace DiunaBI.UI.Shared.Components; public partial class JobListComponent : ComponentBase, IDisposable { [Inject] private JobService JobService { get; set; } = default!; [Inject] private EntityChangeHubService HubService { get; set; } = default!; [Inject] private ISnackbar Snackbar { get; set; } = default!; [Inject] private NavigationManager NavigationManager { get; set; } = default!; [Inject] private IJSRuntime JSRuntime { get; set; } = default!; private PagedResult jobs = new(); private bool isLoading = false; private int currentPage = 1; private int pageSize = 50; private JobStatus? selectedStatus = null; private JobType? selectedJobType = null; protected override async Task OnInitializedAsync() { await LoadJobs(); // Subscribe to SignalR entity changes HubService.EntityChanged += OnEntityChanged; } private async void OnEntityChanged(string module, string id, string operation) { Console.WriteLine($"🔔 JobListComponent.OnEntityChanged called: module={module}, id={id}, operation={operation}"); // Only react if it's a QueueJobs change if (module.Equals("QueueJobs", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine($"📨 Job {id} changed, refreshing job list"); await InvokeAsync(async () => { Console.WriteLine($"🔄 LoadJobs starting..."); await LoadJobs(); Console.WriteLine($"🔄 StateHasChanged calling..."); StateHasChanged(); Console.WriteLine($"✅ Job list refresh complete"); }); } else { Console.WriteLine($"⏭️ Skipping - module '{module}' is not QueueJobs"); } } private async Task LoadJobs() { isLoading = true; try { jobs = await JobService.GetJobsAsync(currentPage, pageSize, selectedStatus, selectedJobType); } catch (Exception ex) { Console.WriteLine($"Loading jobs failed: {ex.Message}"); Snackbar.Add("Failed to load jobs", Severity.Error); } finally { isLoading = false; } } private async Task OnPageChanged(int page) { currentPage = page; await LoadJobs(); } private async Task ClearFilters() { selectedStatus = null; selectedJobType = null; currentPage = 1; await LoadJobs(); } private async Task OnStatusClear() { selectedStatus = null; currentPage = 1; await LoadJobs(); } private async Task OnJobTypeClear() { selectedJobType = null; currentPage = 1; await LoadJobs(); } private void OnRowClick(QueueJob job) { NavigationManager.NavigateTo($"/jobs/{job.Id}"); } private async Task OnRowRightClick(MouseEventArgs e, QueueJob job) { var url = NavigationManager.ToAbsoluteUri($"/jobs/{job.Id}").ToString(); await JSRuntime.InvokeVoidAsync("open", url, "_blank"); } private Color GetStatusColor(JobStatus status) { return status switch { JobStatus.Pending => Color.Default, JobStatus.Running => Color.Info, JobStatus.Completed => Color.Success, JobStatus.Failed => Color.Error, JobStatus.Retrying => Color.Warning, _ => Color.Default }; } private Color GetJobTypeColor(JobType jobType) { return jobType switch { JobType.Import => Color.Primary, JobType.Process => Color.Secondary, _ => Color.Default }; } public void Dispose() { HubService.EntityChanged -= OnEntityChanged; } }