2025-11-20 21:03:19 +01:00
|
|
|
using DiunaBI.Application.DTOModels;
|
2025-12-05 09:51:04 +01:00
|
|
|
using DiunaBI.UI.Shared.Services;
|
2025-11-20 21:03:19 +01:00
|
|
|
using Microsoft.AspNetCore.Components;
|
|
|
|
|
using MudBlazor;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
2025-12-05 09:51:04 +01:00
|
|
|
namespace DiunaBI.UI.Shared.Pages.Layers;
|
2025-11-20 21:03:19 +01:00
|
|
|
|
2025-12-05 09:51:04 +01:00
|
|
|
public partial class Details : ComponentBase
|
2025-11-20 21:03:19 +01:00
|
|
|
{
|
|
|
|
|
[Parameter]
|
|
|
|
|
public Guid Id { get; set; }
|
|
|
|
|
|
2025-12-01 17:56:17 +01:00
|
|
|
[Inject]
|
|
|
|
|
private IDialogService DialogService { get; set; } = null!;
|
|
|
|
|
|
2025-12-05 09:51:04 +01:00
|
|
|
[Inject]
|
|
|
|
|
private LayerService LayerService { get; set; } = null!;
|
|
|
|
|
|
|
|
|
|
[Inject]
|
|
|
|
|
private JobService JobService { get; set; } = null!;
|
|
|
|
|
|
|
|
|
|
[Inject]
|
|
|
|
|
private NavigationManager NavigationManager { get; set; } = null!;
|
|
|
|
|
|
|
|
|
|
[Inject]
|
|
|
|
|
private ISnackbar Snackbar { get; set; } = null!;
|
|
|
|
|
|
2025-12-08 21:42:10 +01:00
|
|
|
[Inject]
|
|
|
|
|
private DateTimeHelper DateTimeHelper { get; set; } = null!;
|
|
|
|
|
|
2025-11-20 21:03:19 +01:00
|
|
|
private LayerDto? layer;
|
|
|
|
|
private List<RecordDto> records = new();
|
|
|
|
|
private List<string> displayedColumns = new();
|
|
|
|
|
private double valueSum = 0;
|
2025-12-05 23:49:16 +01:00
|
|
|
private Dictionary<string, double> columnSums = new();
|
|
|
|
|
private double totalSum = 0;
|
2025-11-20 21:03:19 +01:00
|
|
|
private bool isLoading = false;
|
2025-12-01 17:56:17 +01:00
|
|
|
private Guid? editingRecordId = null;
|
|
|
|
|
private RecordDto? editingRecord = null;
|
|
|
|
|
private bool isAddingNew = false;
|
|
|
|
|
private RecordDto newRecord = new();
|
|
|
|
|
private bool isEditable => layer?.Type == LayerType.Dictionary || layer?.Type == LayerType.Administration;
|
2025-12-05 23:49:16 +01:00
|
|
|
private bool showHistoryTab => layer?.Type == LayerType.Administration || layer?.Type == LayerType.Dictionary;
|
|
|
|
|
private bool showSummary => layer?.Type == LayerType.Import || layer?.Type == LayerType.Processed;
|
2025-11-20 21:03:19 +01:00
|
|
|
|
2025-12-01 18:37:09 +01:00
|
|
|
// History tab state
|
|
|
|
|
private bool isLoadingHistory = false;
|
|
|
|
|
private bool isHistoryTabInitialized = false;
|
|
|
|
|
private RecordDto? selectedRecordForHistory = null;
|
|
|
|
|
private DeletedRecordDto? selectedDeletedRecordForHistory = null;
|
|
|
|
|
private List<RecordHistoryDto> recordHistory = new();
|
|
|
|
|
private List<DeletedRecordDto> deletedRecords = new();
|
|
|
|
|
private Dictionary<Guid, string> userCache = new();
|
|
|
|
|
|
2025-11-20 21:03:19 +01:00
|
|
|
protected override async Task OnInitializedAsync()
|
|
|
|
|
{
|
2025-12-08 21:42:10 +01:00
|
|
|
await DateTimeHelper.InitializeAsync();
|
2025-11-20 21:03:19 +01:00
|
|
|
await LoadLayer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
|
|
|
{
|
|
|
|
|
await LoadLayer();
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-01 18:37:09 +01:00
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
|
|
|
{
|
|
|
|
|
if (!isHistoryTabInitialized && !isLoadingHistory &&
|
|
|
|
|
selectedRecordForHistory == null && selectedDeletedRecordForHistory == null &&
|
|
|
|
|
deletedRecords.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
await LoadDeletedRecordsAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 21:03:19 +01:00
|
|
|
private async Task LoadLayer()
|
|
|
|
|
{
|
|
|
|
|
isLoading = true;
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
layer = await LayerService.GetLayerByIdAsync(Id);
|
|
|
|
|
|
|
|
|
|
if (layer != null && layer.Records != null)
|
|
|
|
|
{
|
2025-12-04 15:53:11 +01:00
|
|
|
records = layer.Records.OrderBy(r => r.Code).ToList();
|
2025-11-20 21:03:19 +01:00
|
|
|
CalculateDisplayedColumns();
|
2025-12-05 23:49:16 +01:00
|
|
|
CalculateColumnSums();
|
2025-12-01 18:37:09 +01:00
|
|
|
BuildUserCache();
|
2025-11-20 21:03:19 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine($"Error loading layer: {ex.Message}");
|
|
|
|
|
Snackbar.Add("Error loading layer", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
isLoading = false;
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CalculateDisplayedColumns()
|
|
|
|
|
{
|
|
|
|
|
displayedColumns.Clear();
|
|
|
|
|
|
|
|
|
|
// Check which Value columns have data
|
|
|
|
|
for (int i = 1; i <= 32; i++)
|
|
|
|
|
{
|
|
|
|
|
var columnName = $"Value{i}";
|
|
|
|
|
var hasData = records.Any(r => GetRecordValueByName(r, columnName) != null);
|
|
|
|
|
|
|
|
|
|
if (hasData)
|
|
|
|
|
{
|
|
|
|
|
displayedColumns.Add(columnName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if Desc1 has data
|
|
|
|
|
if (records.Any(r => !string.IsNullOrEmpty(r.Desc1)))
|
|
|
|
|
{
|
|
|
|
|
displayedColumns.Add("Description1");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-05 23:49:16 +01:00
|
|
|
private void CalculateColumnSums()
|
2025-11-20 21:03:19 +01:00
|
|
|
{
|
2025-12-05 23:49:16 +01:00
|
|
|
columnSums.Clear();
|
|
|
|
|
totalSum = 0;
|
|
|
|
|
|
|
|
|
|
// Calculate sum for each displayed value column
|
|
|
|
|
foreach (var columnName in displayedColumns.Where(c => c.StartsWith("Value")))
|
|
|
|
|
{
|
|
|
|
|
var sum = records
|
|
|
|
|
.Select(r => GetRecordValueByName(r, columnName))
|
|
|
|
|
.Where(v => v.HasValue)
|
|
|
|
|
.Sum(v => v!.Value);
|
|
|
|
|
|
|
|
|
|
columnSums[columnName] = sum;
|
|
|
|
|
totalSum += sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Keep valueSum for backward compatibility (Value1 sum)
|
|
|
|
|
valueSum = columnSums.ContainsKey("Value1") ? columnSums["Value1"] : 0;
|
2025-11-20 21:03:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetRecordValue(RecordDto record, string columnName)
|
|
|
|
|
{
|
|
|
|
|
if (columnName == "Description1")
|
|
|
|
|
{
|
|
|
|
|
return record.Desc1 ?? string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var value = GetRecordValueByName(record, columnName);
|
|
|
|
|
return value.HasValue ? value.Value.ToString("N2") : string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private double? GetRecordValueByName(RecordDto record, string columnName)
|
|
|
|
|
{
|
|
|
|
|
var property = typeof(RecordDto).GetProperty(columnName, BindingFlags.Public | BindingFlags.Instance);
|
|
|
|
|
if (property != null && property.PropertyType == typeof(double?))
|
|
|
|
|
{
|
|
|
|
|
return property.GetValue(record) as double?;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Export()
|
|
|
|
|
{
|
|
|
|
|
// TODO: Implement export functionality
|
|
|
|
|
Snackbar.Add("Export functionality coming soon", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ProcessLayer()
|
|
|
|
|
{
|
|
|
|
|
// TODO: Implement process layer functionality
|
|
|
|
|
Snackbar.Add("Process layer functionality coming soon", Severity.Error);
|
|
|
|
|
}
|
2025-12-01 17:56:17 +01:00
|
|
|
|
2025-12-02 13:23:03 +01:00
|
|
|
private void GoBack()
|
|
|
|
|
{
|
|
|
|
|
NavigationManager.NavigateTo("/layers");
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-01 17:56:17 +01:00
|
|
|
// Record editing methods
|
|
|
|
|
private void StartEdit(RecordDto record)
|
|
|
|
|
{
|
|
|
|
|
editingRecordId = record.Id;
|
|
|
|
|
editingRecord = new RecordDto
|
|
|
|
|
{
|
|
|
|
|
Id = record.Id,
|
|
|
|
|
Code = record.Code,
|
|
|
|
|
Desc1 = record.Desc1,
|
|
|
|
|
LayerId = record.LayerId
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CancelEdit()
|
|
|
|
|
{
|
|
|
|
|
editingRecordId = null;
|
|
|
|
|
editingRecord = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task SaveEdit()
|
|
|
|
|
{
|
|
|
|
|
if (editingRecord == null || layer == null) return;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(editingRecord.Code))
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Code is required", Severity.Warning);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(editingRecord.Desc1))
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Description is required", Severity.Warning);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var updated = await LayerService.UpdateRecordAsync(layer.Id, editingRecord.Id, editingRecord);
|
|
|
|
|
if (updated != null)
|
|
|
|
|
{
|
|
|
|
|
var record = records.FirstOrDefault(r => r.Id == editingRecord.Id);
|
|
|
|
|
if (record != null)
|
|
|
|
|
{
|
|
|
|
|
record.Code = updated.Code;
|
|
|
|
|
record.Desc1 = updated.Desc1;
|
|
|
|
|
record.ModifiedAt = updated.ModifiedAt;
|
|
|
|
|
}
|
|
|
|
|
editingRecordId = null;
|
|
|
|
|
editingRecord = null;
|
|
|
|
|
Snackbar.Add("Record updated successfully", Severity.Success);
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Failed to update record", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine($"Error updating record: {ex.Message}");
|
|
|
|
|
Snackbar.Add("Error updating record", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task DeleteRecord(RecordDto record)
|
|
|
|
|
{
|
|
|
|
|
if (layer == null) return;
|
|
|
|
|
|
|
|
|
|
var result = await DialogService.ShowMessageBox(
|
|
|
|
|
"Confirm Delete",
|
|
|
|
|
$"Are you sure you want to delete record '{record.Code}'?",
|
|
|
|
|
yesText: "Delete",
|
|
|
|
|
cancelText: "Cancel");
|
|
|
|
|
|
|
|
|
|
if (result == true)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var success = await LayerService.DeleteRecordAsync(layer.Id, record.Id);
|
|
|
|
|
if (success)
|
|
|
|
|
{
|
|
|
|
|
records.Remove(record);
|
|
|
|
|
CalculateDisplayedColumns();
|
2025-12-05 23:49:16 +01:00
|
|
|
CalculateColumnSums();
|
2025-12-01 17:56:17 +01:00
|
|
|
Snackbar.Add("Record deleted successfully", Severity.Success);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Failed to delete record", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine($"Error deleting record: {ex.Message}");
|
|
|
|
|
Snackbar.Add("Error deleting record", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StartAddNew()
|
|
|
|
|
{
|
|
|
|
|
isAddingNew = true;
|
|
|
|
|
newRecord = new RecordDto { LayerId = layer?.Id ?? Guid.Empty };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CancelAddNew()
|
|
|
|
|
{
|
|
|
|
|
isAddingNew = false;
|
|
|
|
|
newRecord = new();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task SaveNewRecord()
|
|
|
|
|
{
|
|
|
|
|
if (layer == null) return;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(newRecord.Code))
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Code is required", Severity.Warning);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(newRecord.Desc1))
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Description is required", Severity.Warning);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var created = await LayerService.CreateRecordAsync(layer.Id, newRecord);
|
|
|
|
|
if (created != null)
|
|
|
|
|
{
|
|
|
|
|
records.Add(created);
|
|
|
|
|
CalculateDisplayedColumns();
|
2025-12-05 23:49:16 +01:00
|
|
|
CalculateColumnSums();
|
2025-12-01 17:56:17 +01:00
|
|
|
isAddingNew = false;
|
|
|
|
|
newRecord = new();
|
|
|
|
|
Snackbar.Add("Record added successfully", Severity.Success);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Failed to add record", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine($"Error adding record: {ex.Message}");
|
|
|
|
|
Snackbar.Add("Error adding record", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-01 18:37:09 +01:00
|
|
|
|
|
|
|
|
// History tab methods
|
|
|
|
|
private async Task LoadDeletedRecordsAsync()
|
|
|
|
|
{
|
|
|
|
|
if (isHistoryTabInitialized || layer == null) return;
|
|
|
|
|
|
|
|
|
|
isHistoryTabInitialized = true;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"Loading deleted records for layer {layer.Id}");
|
|
|
|
|
deletedRecords = await LayerService.GetDeletedRecordsAsync(layer.Id);
|
|
|
|
|
Console.WriteLine($"Loaded {deletedRecords.Count} deleted records");
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine($"Error loading deleted records: {ex.Message}");
|
|
|
|
|
Console.Error.WriteLine($"Stack trace: {ex.StackTrace}");
|
|
|
|
|
deletedRecords = new List<DeletedRecordDto>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task OnRecordClickForHistory(TableRowClickEventArgs<RecordDto> args)
|
|
|
|
|
{
|
|
|
|
|
if (args.Item == null || layer == null) return;
|
|
|
|
|
|
|
|
|
|
selectedRecordForHistory = args.Item;
|
|
|
|
|
isLoadingHistory = true;
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
recordHistory = await LayerService.GetRecordHistoryAsync(layer.Id, args.Item.Id);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine($"Error loading record history: {ex.Message}");
|
|
|
|
|
Snackbar.Add("Error loading record history", Severity.Error);
|
|
|
|
|
recordHistory = new List<RecordHistoryDto>();
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
isLoadingHistory = false;
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ClearHistorySelection()
|
|
|
|
|
{
|
|
|
|
|
selectedRecordForHistory = null;
|
|
|
|
|
selectedDeletedRecordForHistory = null;
|
|
|
|
|
recordHistory.Clear();
|
|
|
|
|
isHistoryTabInitialized = false; // Reset so deleted records reload when returning to list
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task OnDeletedRecordClickForHistory(TableRowClickEventArgs<DeletedRecordDto> args)
|
|
|
|
|
{
|
|
|
|
|
if (args.Item == null || layer == null) return;
|
|
|
|
|
|
|
|
|
|
selectedDeletedRecordForHistory = args.Item;
|
|
|
|
|
selectedRecordForHistory = null;
|
|
|
|
|
isLoadingHistory = true;
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
recordHistory = await LayerService.GetRecordHistoryAsync(layer.Id, args.Item.RecordId);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.Error.WriteLine($"Error loading deleted record history: {ex.Message}");
|
|
|
|
|
Snackbar.Add("Error loading record history", Severity.Error);
|
|
|
|
|
recordHistory = new List<RecordHistoryDto>();
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
isLoadingHistory = false;
|
|
|
|
|
StateHasChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Color GetHistoryColor(string changeType)
|
|
|
|
|
{
|
|
|
|
|
return changeType switch
|
|
|
|
|
{
|
|
|
|
|
"Created" => Color.Success,
|
|
|
|
|
"Updated" => Color.Info,
|
|
|
|
|
"Deleted" => Color.Error,
|
|
|
|
|
_ => Color.Default
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BuildUserCache()
|
|
|
|
|
{
|
|
|
|
|
userCache.Clear();
|
|
|
|
|
|
|
|
|
|
if (layer == null) return;
|
|
|
|
|
|
|
|
|
|
// Add layer-level users to cache
|
|
|
|
|
if (layer.CreatedBy != null)
|
|
|
|
|
userCache.TryAdd(layer.CreatedBy.Id, layer.CreatedBy.Username ?? string.Empty);
|
|
|
|
|
if (layer.ModifiedBy != null)
|
|
|
|
|
userCache.TryAdd(layer.ModifiedBy.Id, layer.ModifiedBy.Username ?? string.Empty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetModifiedByUsername(Guid userId)
|
|
|
|
|
{
|
|
|
|
|
return userCache.TryGetValue(userId, out var username) ? username : string.Empty;
|
|
|
|
|
}
|
2025-12-03 13:33:38 +01:00
|
|
|
|
|
|
|
|
// Run Now button methods
|
|
|
|
|
private bool isRunningJob = false;
|
|
|
|
|
|
|
|
|
|
private bool IsWorkerLayer()
|
|
|
|
|
{
|
|
|
|
|
if (layer?.Records == null) return false;
|
|
|
|
|
|
|
|
|
|
var typeRecord = layer.Records.FirstOrDefault(x => x.Code == "Type");
|
|
|
|
|
return typeRecord?.Desc1 == "ImportWorker" || typeRecord?.Desc1 == "ProcessWorker";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task RunNow()
|
|
|
|
|
{
|
|
|
|
|
if (layer == null) return;
|
|
|
|
|
|
|
|
|
|
isRunningJob = true;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var result = await JobService.CreateJobForLayerAsync(layer.Id);
|
|
|
|
|
|
|
|
|
|
if (result != null && result.Success)
|
|
|
|
|
{
|
|
|
|
|
if (result.Existing)
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add($"Job already exists: {result.Message}", Severity.Info);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2025-12-04 22:20:00 +01:00
|
|
|
Snackbar.Add("Job created successfully! Watch real-time status updates.", Severity.Success);
|
2025-12-03 13:33:38 +01:00
|
|
|
}
|
|
|
|
|
|
2025-12-04 22:20:00 +01:00
|
|
|
// Navigate to job detail page to see real-time updates
|
2025-12-03 13:33:38 +01:00
|
|
|
NavigationManager.NavigateTo($"/jobs/{result.JobId}");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Snackbar.Add("Failed to create job", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine($"Error creating job: {ex.Message}");
|
|
|
|
|
Snackbar.Add($"Error creating job: {ex.Message}", Severity.Error);
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
isRunningJob = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-11-20 21:03:19 +01:00
|
|
|
}
|