DataInbox list
This commit is contained in:
@@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DiunaBI.Infrastructure.Data;
|
||||
using DiunaBI.Domain.Entities;
|
||||
using DiunaBI.Application.DTOModels;
|
||||
using DiunaBI.Application.DTOModels.Common;
|
||||
|
||||
namespace DiunaBI.API.Controllers;
|
||||
|
||||
@@ -89,17 +91,91 @@ public class DataInboxController : Controller
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IActionResult GetAll()
|
||||
[Route("GetAll")]
|
||||
public IActionResult GetAll([FromQuery] int start, [FromQuery] int limit, [FromQuery] string? name, [FromQuery] string? source)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dataInbox = _db.DataInbox.AsNoTracking().ToList();
|
||||
_logger.LogDebug("DataInbox: Retrieved {Count} records", dataInbox.Count);
|
||||
return Ok(dataInbox);
|
||||
var query = _db.DataInbox.AsQueryable();
|
||||
|
||||
if (name != null)
|
||||
{
|
||||
query = query.Where(x => x.Name.Contains(name));
|
||||
}
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
query = query.Where(x => x.Source.Contains(source));
|
||||
}
|
||||
|
||||
var totalCount = query.Count();
|
||||
|
||||
var items = query
|
||||
.OrderByDescending(x => x.CreatedAt)
|
||||
.Skip(start)
|
||||
.Take(limit)
|
||||
.AsNoTracking()
|
||||
.Select(x => new DataInboxDto
|
||||
{
|
||||
Id = x.Id,
|
||||
Name = x.Name,
|
||||
Source = x.Source,
|
||||
Data = x.Data,
|
||||
CreatedAt = x.CreatedAt
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var pagedResult = new PagedResult<DataInboxDto>
|
||||
{
|
||||
Items = items,
|
||||
TotalCount = totalCount,
|
||||
Page = (start / limit) + 1,
|
||||
PageSize = limit
|
||||
};
|
||||
|
||||
_logger.LogDebug("GetAll: Retrieved {Count} of {TotalCount} data inbox items (page {Page}) with filter name={Name}, source={Source}",
|
||||
items.Count, totalCount, pagedResult.Page, name, source);
|
||||
|
||||
return Ok(pagedResult);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "DataInbox: Error retrieving records");
|
||||
_logger.LogError(e, "GetAll: Error retrieving data inbox items");
|
||||
return BadRequest(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("{id:guid}")]
|
||||
public IActionResult Get(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dataInbox = _db.DataInbox
|
||||
.AsNoTracking()
|
||||
.FirstOrDefault(x => x.Id == id);
|
||||
|
||||
if (dataInbox == null)
|
||||
{
|
||||
_logger.LogWarning("Get: Data inbox item {Id} not found", id);
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var dto = new DataInboxDto
|
||||
{
|
||||
Id = dataInbox.Id,
|
||||
Name = dataInbox.Name,
|
||||
Source = dataInbox.Source,
|
||||
Data = dataInbox.Data,
|
||||
CreatedAt = dataInbox.CreatedAt
|
||||
};
|
||||
|
||||
_logger.LogDebug("Get: Retrieved data inbox item {Id} {Name}", id, dataInbox.Name);
|
||||
return Ok(dto);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Get: Error retrieving data inbox item {Id}", id);
|
||||
return BadRequest(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
17
DiunaBI.Application/DTOModels/DataInboxDto.cs
Normal file
17
DiunaBI.Application/DTOModels/DataInboxDto.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace DiunaBI.Application.DTOModels;
|
||||
|
||||
public class DataInboxDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Source { get; set; } = string.Empty;
|
||||
public string Data { get; set; } = string.Empty;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
|
||||
public class DataInboxFilterRequest
|
||||
{
|
||||
public string? Search { get; set; }
|
||||
public int Page { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 50;
|
||||
}
|
||||
75
DiunaBI.UI.Shared/Components/DataInboxListComponent.razor
Normal file
75
DiunaBI.UI.Shared/Components/DataInboxListComponent.razor
Normal file
@@ -0,0 +1,75 @@
|
||||
@using MudBlazor.Internal
|
||||
<MudExpansionPanels Class="mb-4">
|
||||
<MudExpansionPanel Icon="@Icons.Material.Filled.FilterList"
|
||||
Text="Filters"
|
||||
Expanded="true">
|
||||
<MudGrid>
|
||||
<MudItem xs="12" sm="6" md="4">
|
||||
<MudTextField @bind-Value="filterRequest.Search"
|
||||
Label="Search"
|
||||
Placeholder="Name, source..."
|
||||
Immediate="true"
|
||||
DebounceInterval="500"
|
||||
OnDebounceIntervalElapsed="SearchDataInbox"
|
||||
Clearable="true"/>
|
||||
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" sm="6" md="4">
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
OnClick="ClearFilters"
|
||||
StartIcon="Icons.Material.Filled.Clear">
|
||||
Clear filters
|
||||
</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudExpansionPanel>
|
||||
</MudExpansionPanels>
|
||||
|
||||
<MudDivider Class="my-4"></MudDivider>
|
||||
|
||||
<MudTable Items="dataInbox.Items"
|
||||
Dense="true"
|
||||
Hover="true"
|
||||
Loading="isLoading"
|
||||
LoadingProgressColor="Color.Info"
|
||||
T="DataInboxDto"
|
||||
Style="cursor: pointer;">
|
||||
<HeaderContent>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Source</MudTh>
|
||||
<MudTh>Created At</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Source">@context.Source</MudTd>
|
||||
<MudTd DataLabel="Created At">@context.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss")</MudTd>
|
||||
</RowTemplate>
|
||||
<NoRecordsContent>
|
||||
<MudText>No data inbox items to display</MudText>
|
||||
</NoRecordsContent>
|
||||
<LoadingContent>
|
||||
Loading...
|
||||
</LoadingContent>
|
||||
</MudTable>
|
||||
|
||||
@if (dataInbox.TotalCount > 0)
|
||||
{
|
||||
<MudGrid Class="mt-4" AlignItems="Center.Center">
|
||||
<MudItem xs="12" sm="6">
|
||||
<MudText Typo="Typo.body2">
|
||||
Results @((dataInbox.Page - 1) * dataInbox.PageSize + 1) - @Math.Min(dataInbox.Page * dataInbox.PageSize, dataInbox.TotalCount)
|
||||
of @dataInbox.TotalCount
|
||||
</MudText>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="6" Class="d-flex justify-end">
|
||||
<MudPagination Count="dataInbox.TotalPages"
|
||||
Selected="dataInbox.Page"
|
||||
SelectedChanged="OnPageChanged"
|
||||
ShowFirstButton="true"
|
||||
ShowLastButton="true"
|
||||
Variant="Variant.Outlined"
|
||||
/>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
}
|
||||
60
DiunaBI.UI.Shared/Components/DataInboxListComponent.razor.cs
Normal file
60
DiunaBI.UI.Shared/Components/DataInboxListComponent.razor.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using DiunaBI.UI.Shared.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using DiunaBI.Application.DTOModels;
|
||||
using DiunaBI.Application.DTOModels.Common;
|
||||
using MudBlazor;
|
||||
|
||||
namespace DiunaBI.UI.Shared.Components;
|
||||
|
||||
public partial class DataInboxListComponent : ComponentBase
|
||||
{
|
||||
[Inject] private DataInboxService DataInboxService { get; set; } = default!;
|
||||
[Inject] private ISnackbar Snackbar { get; set; } = default!;
|
||||
[Inject] private NavigationManager NavigationManager { get; set; } = default!;
|
||||
|
||||
|
||||
private PagedResult<DataInboxDto> dataInbox = new();
|
||||
private DataInboxFilterRequest filterRequest = new();
|
||||
private bool isLoading = false;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadDataInbox();
|
||||
}
|
||||
|
||||
private async Task LoadDataInbox()
|
||||
{
|
||||
isLoading = true;
|
||||
|
||||
try
|
||||
{
|
||||
dataInbox = await DataInboxService.GetDataInboxAsync(filterRequest);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Loading data inbox failed: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SearchDataInbox()
|
||||
{
|
||||
filterRequest.Page = 1;
|
||||
await LoadDataInbox();
|
||||
}
|
||||
|
||||
private async Task OnPageChanged(int page)
|
||||
{
|
||||
filterRequest.Page = page;
|
||||
await LoadDataInbox();
|
||||
}
|
||||
|
||||
private async Task ClearFilters()
|
||||
{
|
||||
filterRequest = new DataInboxFilterRequest();
|
||||
await LoadDataInbox();
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using MudBlazor
|
||||
<MudNavMenu>
|
||||
<MudNavLink href="dashboard" Icon="@Icons.Material.Filled.Dashboard" Match="NavLinkMatch.All">
|
||||
Dashboard
|
||||
</MudNavLink>
|
||||
<MudNavLink Href="layers" Icon="@Icons.Material.Filled.List" Match="NavLinkMatch.All">
|
||||
Layers
|
||||
</MudNavLink>
|
||||
</MudNavMenu>
|
||||
@@ -36,6 +36,7 @@ public static class ServiceCollectionExtensions
|
||||
// Services
|
||||
services.AddScoped<AuthService>();
|
||||
services.AddScoped<LayerService>();
|
||||
services.AddScoped<DataInboxService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<MudNavMenu>
|
||||
<MudNavLink Href="/dashboard" Icon="@Icons.Material.Filled.Dashboard">Dashboard</MudNavLink>
|
||||
<MudNavLink Href="/layers" Icon="@Icons.Material.Filled.Inventory">Layers</MudNavLink>
|
||||
<MudNavLink Href="/datainbox" Icon="@Icons.Material.Filled.Inbox">Data Inbox</MudNavLink>
|
||||
</MudNavMenu>
|
||||
</MudDrawer>
|
||||
|
||||
|
||||
8
DiunaBI.UI.Shared/Pages/DataInboxListPage.razor
Normal file
8
DiunaBI.UI.Shared/Pages/DataInboxListPage.razor
Normal file
@@ -0,0 +1,8 @@
|
||||
@page "/datainbox"
|
||||
@using DiunaBI.UI.Shared.Components
|
||||
|
||||
<PageTitle>Data Inbox</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge">
|
||||
<DataInboxListComponent />
|
||||
</MudContainer>
|
||||
49
DiunaBI.UI.Shared/Services/DataInboxService.cs
Normal file
49
DiunaBI.UI.Shared/Services/DataInboxService.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json;
|
||||
using DiunaBI.Application.DTOModels;
|
||||
using DiunaBI.Application.DTOModels.Common;
|
||||
|
||||
namespace DiunaBI.UI.Shared.Services;
|
||||
|
||||
public class DataInboxService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public DataInboxService(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
private readonly JsonSerializerOptions _jsonOptions = new()
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
public async Task<PagedResult<DataInboxDto>> GetDataInboxAsync(DataInboxFilterRequest filterRequest)
|
||||
{
|
||||
// Calculate start index from page number (page 1 = start 0, page 2 = start 50, etc.)
|
||||
var start = (filterRequest.Page - 1) * filterRequest.PageSize;
|
||||
var query = $"DataInbox/GetAll?start={start}&limit={filterRequest.PageSize}";
|
||||
|
||||
if (!string.IsNullOrEmpty(filterRequest.Search))
|
||||
query += $"&name={Uri.EscapeDataString(filterRequest.Search)}";
|
||||
|
||||
var response = await _httpClient.GetAsync(query);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonSerializer.Deserialize<PagedResult<DataInboxDto>>(json, _jsonOptions);
|
||||
|
||||
return result ?? new PagedResult<DataInboxDto>();
|
||||
}
|
||||
|
||||
public async Task<DataInboxDto?> GetDataInboxByIdAsync(Guid id)
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"DataInbox/{id}");
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return null;
|
||||
|
||||
return await response.Content.ReadFromJsonAsync<DataInboxDto>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user