DataInbox list
This commit is contained in:
@@ -4,6 +4,8 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using DiunaBI.Infrastructure.Data;
|
using DiunaBI.Infrastructure.Data;
|
||||||
using DiunaBI.Domain.Entities;
|
using DiunaBI.Domain.Entities;
|
||||||
|
using DiunaBI.Application.DTOModels;
|
||||||
|
using DiunaBI.Application.DTOModels.Common;
|
||||||
|
|
||||||
namespace DiunaBI.API.Controllers;
|
namespace DiunaBI.API.Controllers;
|
||||||
|
|
||||||
@@ -89,17 +91,91 @@ public class DataInboxController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult GetAll()
|
[Route("GetAll")]
|
||||||
|
public IActionResult GetAll([FromQuery] int start, [FromQuery] int limit, [FromQuery] string? name, [FromQuery] string? source)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dataInbox = _db.DataInbox.AsNoTracking().ToList();
|
var query = _db.DataInbox.AsQueryable();
|
||||||
_logger.LogDebug("DataInbox: Retrieved {Count} records", dataInbox.Count);
|
|
||||||
return Ok(dataInbox);
|
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)
|
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());
|
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
|
||||||
services.AddScoped<AuthService>();
|
services.AddScoped<AuthService>();
|
||||||
services.AddScoped<LayerService>();
|
services.AddScoped<LayerService>();
|
||||||
|
services.AddScoped<DataInboxService>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
<MudNavMenu>
|
<MudNavMenu>
|
||||||
<MudNavLink Href="/dashboard" Icon="@Icons.Material.Filled.Dashboard">Dashboard</MudNavLink>
|
<MudNavLink Href="/dashboard" Icon="@Icons.Material.Filled.Dashboard">Dashboard</MudNavLink>
|
||||||
<MudNavLink Href="/layers" Icon="@Icons.Material.Filled.Inventory">Layers</MudNavLink>
|
<MudNavLink Href="/layers" Icon="@Icons.Material.Filled.Inventory">Layers</MudNavLink>
|
||||||
|
<MudNavLink Href="/datainbox" Icon="@Icons.Material.Filled.Inbox">Data Inbox</MudNavLink>
|
||||||
</MudNavMenu>
|
</MudNavMenu>
|
||||||
</MudDrawer>
|
</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