WIP: p2 plugin
Some checks failed
Build Docker Images / test (map[name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Failing after 1m14s
Build Docker Images / test (map[name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Failing after 1m10s
Build Docker Images / build-and-push (map[image_suffix:morska name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Failing after 1m12s
Build Docker Images / build-and-push (map[image_suffix:pedrollopl name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Failing after 1m7s
Some checks failed
Build Docker Images / test (map[name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Failing after 1m14s
Build Docker Images / test (map[name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Failing after 1m10s
Build Docker Images / build-and-push (map[image_suffix:morska name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Failing after 1m12s
Build Docker Images / build-and-push (map[image_suffix:pedrollopl name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Failing after 1m7s
This commit is contained in:
245
DiunaBI.UI.Shared/Pages/JobDetailPage.razor
Normal file
245
DiunaBI.UI.Shared/Pages/JobDetailPage.razor
Normal file
@@ -0,0 +1,245 @@
|
||||
@page "/jobs/{id:guid}"
|
||||
@using DiunaBI.UI.Shared.Services
|
||||
@using DiunaBI.Domain.Entities
|
||||
@using MudBlazor
|
||||
@inject JobService JobService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
<MudCard>
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h5">Job Details</MudText>
|
||||
</CardHeaderContent>
|
||||
<CardHeaderActions>
|
||||
@if (job != null && job.Status == JobStatus.Failed)
|
||||
{
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Warning"
|
||||
OnClick="RetryJob"
|
||||
StartIcon="@Icons.Material.Filled.Refresh">
|
||||
Retry
|
||||
</MudButton>
|
||||
}
|
||||
@if (job != null && (job.Status == JobStatus.Pending || job.Status == JobStatus.Retrying))
|
||||
{
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Error"
|
||||
OnClick="CancelJob"
|
||||
StartIcon="@Icons.Material.Filled.Cancel">
|
||||
Cancel
|
||||
</MudButton>
|
||||
}
|
||||
<MudButton Variant="Variant.Text"
|
||||
OnClick="GoBack"
|
||||
StartIcon="@Icons.Material.Filled.ArrowBack">
|
||||
Back to List
|
||||
</MudButton>
|
||||
</CardHeaderActions>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
@if (isLoading)
|
||||
{
|
||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true" />
|
||||
}
|
||||
else if (job == null)
|
||||
{
|
||||
<MudAlert Severity="Severity.Error">Job not found</MudAlert>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudGrid>
|
||||
<MudItem xs="12" md="6">
|
||||
<MudTextField Value="@job.LayerName"
|
||||
Label="Layer Name"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="6">
|
||||
<MudTextField Value="@job.PluginName"
|
||||
Label="Plugin Name"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" md="4">
|
||||
<MudTextField Value="@job.JobType.ToString()"
|
||||
Label="Job Type"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="4">
|
||||
<MudTextField Value="@job.Status.ToString()"
|
||||
Label="Status"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"
|
||||
Adornment="Adornment.Start"
|
||||
AdornmentIcon="@GetStatusIcon(job.Status)"
|
||||
AdornmentColor="@GetStatusColor(job.Status)"/>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="4">
|
||||
<MudTextField Value="@job.Priority.ToString()"
|
||||
Label="Priority"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" md="6">
|
||||
<MudTextField Value="@job.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss")"
|
||||
Label="Created At"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="6">
|
||||
<MudTextField Value="@(job.LastAttemptAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-")"
|
||||
Label="Last Attempt At"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" md="6">
|
||||
<MudTextField Value="@(job.CompletedAt?.ToString("yyyy-MM-dd HH:mm:ss") ?? "-")"
|
||||
Label="Completed At"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="6">
|
||||
<MudTextField Value="@($"{job.RetryCount} / {job.MaxRetries}")"
|
||||
Label="Retry Count / Max Retries"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"/>
|
||||
</MudItem>
|
||||
|
||||
@if (!string.IsNullOrEmpty(job.LastError))
|
||||
{
|
||||
<MudItem xs="12">
|
||||
<MudTextField Value="@job.LastError"
|
||||
Label="Last Error"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
FullWidth="true"
|
||||
Lines="5"
|
||||
AdornmentIcon="@Icons.Material.Filled.Error"
|
||||
AdornmentColor="Color.Error"/>
|
||||
</MudItem>
|
||||
}
|
||||
|
||||
<MudItem xs="12">
|
||||
<MudDivider Class="my-4"/>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12">
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
Color="Color.Primary"
|
||||
OnClick="@(() => NavigationManager.NavigateTo($"/layers/{job.LayerId}"))"
|
||||
StartIcon="@Icons.Material.Filled.Layers">
|
||||
View Layer Details
|
||||
</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
}
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
private QueueJob? job;
|
||||
private bool isLoading = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadJob();
|
||||
}
|
||||
|
||||
private async Task LoadJob()
|
||||
{
|
||||
isLoading = true;
|
||||
try
|
||||
{
|
||||
job = await JobService.GetJobByIdAsync(Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Loading job failed: {ex.Message}");
|
||||
Snackbar.Add("Failed to load job", Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RetryJob()
|
||||
{
|
||||
if (job == null) return;
|
||||
|
||||
var success = await JobService.RetryJobAsync(job.Id);
|
||||
if (success)
|
||||
{
|
||||
Snackbar.Add("Job reset to Pending status", Severity.Success);
|
||||
await LoadJob();
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add("Failed to retry job", Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CancelJob()
|
||||
{
|
||||
if (job == null) return;
|
||||
|
||||
var success = await JobService.CancelJobAsync(job.Id);
|
||||
if (success)
|
||||
{
|
||||
Snackbar.Add("Job cancelled", Severity.Success);
|
||||
await LoadJob();
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add("Failed to cancel job", Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void GoBack()
|
||||
{
|
||||
NavigationManager.NavigateTo("/jobs");
|
||||
}
|
||||
|
||||
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 string GetStatusIcon(JobStatus status)
|
||||
{
|
||||
return status switch
|
||||
{
|
||||
JobStatus.Pending => Icons.Material.Filled.HourglassEmpty,
|
||||
JobStatus.Running => Icons.Material.Filled.PlayArrow,
|
||||
JobStatus.Completed => Icons.Material.Filled.CheckCircle,
|
||||
JobStatus.Failed => Icons.Material.Filled.Error,
|
||||
JobStatus.Retrying => Icons.Material.Filled.Refresh,
|
||||
_ => Icons.Material.Filled.Help
|
||||
};
|
||||
}
|
||||
}
|
||||
8
DiunaBI.UI.Shared/Pages/JobListPage.razor
Normal file
8
DiunaBI.UI.Shared/Pages/JobListPage.razor
Normal file
@@ -0,0 +1,8 @@
|
||||
@page "/jobs"
|
||||
@using DiunaBI.UI.Shared.Components
|
||||
|
||||
<PageTitle>Jobs</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge">
|
||||
<JobListComponent />
|
||||
</MudContainer>
|
||||
@@ -3,7 +3,9 @@
|
||||
@using DiunaBI.Application.DTOModels
|
||||
@using MudBlazor
|
||||
@inject LayerService LayerService
|
||||
@inject JobService JobService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
<MudCard>
|
||||
<MudCardHeader>
|
||||
@@ -11,18 +13,24 @@
|
||||
<MudText Typo="Typo.h5">Layer Details</MudText>
|
||||
</CardHeaderContent>
|
||||
<CardHeaderActions>
|
||||
<!--
|
||||
<MudButton Variant="Variant.Text" OnClick="Export">Export</MudButton>
|
||||
@if (layer != null && layer.Type == LayerType.Administration)
|
||||
@if (layer != null && layer.Type == LayerType.Administration && IsWorkerLayer())
|
||||
{
|
||||
<MudButton Variant="Variant.Text" Href="@($"/layers/edit/{layer.Id}/duplicate")">Duplicate</MudButton>
|
||||
<MudButton Variant="Variant.Text" Href="@($"/layers/edit/{layer.Id}")">Edit</MudButton>
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
OnClick="RunNow"
|
||||
Disabled="isRunningJob"
|
||||
StartIcon="@Icons.Material.Filled.PlayArrow">
|
||||
@if (isRunningJob)
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate="true"/>
|
||||
<span style="margin-left: 8px;">Creating Job...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Run Now</span>
|
||||
}
|
||||
</MudButton>
|
||||
}
|
||||
@if (layer != null && layer.Type == LayerType.Processed)
|
||||
{
|
||||
<MudButton Variant="Variant.Text" OnClick="ProcessLayer">Process Layer</MudButton>
|
||||
}
|
||||
-->
|
||||
<MudButton Variant="Variant.Text" OnClick="GoBack" StartIcon="@Icons.Material.Filled.ArrowBack">Back to List</MudButton>
|
||||
</CardHeaderActions>
|
||||
</MudCardHeader>
|
||||
|
||||
@@ -10,9 +10,6 @@ public partial class LayerDetailPage : ComponentBase
|
||||
[Parameter]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Inject]
|
||||
private ISnackbar Snackbar { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; set; } = null!;
|
||||
|
||||
@@ -413,4 +410,54 @@ public partial class LayerDetailPage : ComponentBase
|
||||
{
|
||||
return userCache.TryGetValue(userId, out var username) ? username : string.Empty;
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
Snackbar.Add("Job created successfully!", Severity.Success);
|
||||
}
|
||||
|
||||
// Navigate to job detail page
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user