Compare commits
16 Commits
3a1cb68cf0
...
c73c7e63fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c73c7e63fe | ||
|
|
3e78e2e2cf | ||
|
|
05825b6815 | ||
|
|
4720c8f87b | ||
|
|
0c936d0bf9 | ||
|
|
fcbc66f8f5 | ||
|
|
aab6478f9a | ||
|
|
177d418ac3 | ||
|
|
7cc88c13f3 | ||
|
|
8bf172755b | ||
|
|
27c8f92a3b | ||
|
|
cd0a824064 | ||
|
|
0008fac1d2 | ||
|
|
4659913711 | ||
|
|
bb23cb6629 | ||
|
|
b3f7df6801 |
@@ -50,17 +50,6 @@ public class CatalogsController : ControllerBase
|
|||||||
[HttpPut("{id:int}")]
|
[HttpPut("{id:int}")]
|
||||||
public async Task<ActionResult<CatalogReadDto>> Update(int id, CatalogWriteDto dto, CancellationToken cancellationToken)
|
public async Task<ActionResult<CatalogReadDto>> Update(int id, CatalogWriteDto dto, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var current = await _mediator.Send(new GetCatalogByIdQuery(id), cancellationToken);
|
|
||||||
if (current == null)
|
|
||||||
{
|
|
||||||
return NotFound();
|
|
||||||
}
|
|
||||||
if (dto.UpdateProcedure == CatalogUpdateProcedure.Update &&
|
|
||||||
!string.Equals(current.CatTitle, dto.CatTitle, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return BadRequest("Titel kann nicht geändert werden.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var updated = await _mediator.Send(new UpdateCatalogCommand(id, dto), cancellationToken);
|
var updated = await _mediator.Send(new UpdateCatalogCommand(id, dto), cancellationToken);
|
||||||
if (updated == null)
|
if (updated == null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Text;
|
|||||||
using DbFirst.Application.Repositories;
|
using DbFirst.Application.Repositories;
|
||||||
using DbFirst.Domain.Entities;
|
using DbFirst.Domain.Entities;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using DbFirst.Application.Layouts;
|
||||||
|
|
||||||
namespace DbFirst.API.Controllers;
|
namespace DbFirst.API.Controllers;
|
||||||
|
|
||||||
@@ -83,12 +84,4 @@ public class LayoutsController : ControllerBase
|
|||||||
LayoutData = layoutData
|
LayoutData = layoutData
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class LayoutDto
|
|
||||||
{
|
|
||||||
public string LayoutType { get; set; } = string.Empty;
|
|
||||||
public string LayoutKey { get; set; } = string.Empty;
|
|
||||||
public string UserName { get; set; } = string.Empty;
|
|
||||||
public string LayoutData { get; set; } = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,9 @@ using DbFirst.API.Middleware;
|
|||||||
using DbFirst.API.Dashboards;
|
using DbFirst.API.Dashboards;
|
||||||
using DbFirst.API.Hubs;
|
using DbFirst.API.Hubs;
|
||||||
using DbFirst.Application;
|
using DbFirst.Application;
|
||||||
using DbFirst.Application.Repositories;
|
|
||||||
using DbFirst.Domain;
|
using DbFirst.Domain;
|
||||||
using DbFirst.Domain.Entities;
|
using DbFirst.Domain.Entities;
|
||||||
using DbFirst.Infrastructure;
|
using DbFirst.Infrastructure;
|
||||||
using DbFirst.Infrastructure.Repositories;
|
|
||||||
using DevExpress.AspNetCore;
|
using DevExpress.AspNetCore;
|
||||||
using DevExpress.DashboardAspNetCore;
|
using DevExpress.DashboardAspNetCore;
|
||||||
using DevExpress.DashboardCommon;
|
using DevExpress.DashboardCommon;
|
||||||
@@ -51,10 +49,6 @@ builder.Services.AddCors(options =>
|
|||||||
builder.Services.AddInfrastructure(builder.Configuration);
|
builder.Services.AddInfrastructure(builder.Configuration);
|
||||||
builder.Services.AddApplication();
|
builder.Services.AddApplication();
|
||||||
|
|
||||||
builder.Services.AddScoped<ICatalogRepository, CatalogRepository>();
|
|
||||||
builder.Services.AddScoped<IMassDataRepository, MassDataRepository>();
|
|
||||||
builder.Services.AddScoped<ILayoutRepository, LayoutRepository>();
|
|
||||||
|
|
||||||
builder.Services.AddDevExpressControls();
|
builder.Services.AddDevExpressControls();
|
||||||
builder.Services.AddSignalR();
|
builder.Services.AddSignalR();
|
||||||
builder.Services.AddSingleton<IDashboardChangeNotifier, DashboardChangeNotifier>();
|
builder.Services.AddSingleton<IDashboardChangeNotifier, DashboardChangeNotifier>();
|
||||||
|
|||||||
@@ -25,18 +25,20 @@ public class UpdateCatalogHandler : IRequestHandler<UpdateCatalogCommand, Catalo
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.Dto.UpdateProcedure == CatalogUpdateProcedure.Update &&
|
||||||
|
!string.Equals(existing.CatTitle, request.Dto.CatTitle, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Titel kann nicht geändert werden.");
|
||||||
|
}
|
||||||
|
|
||||||
var entity = _mapper.Map<VwmyCatalog>(request.Dto);
|
var entity = _mapper.Map<VwmyCatalog>(request.Dto);
|
||||||
entity.Guid = request.Id;
|
entity.Guid = request.Id;
|
||||||
entity.CatTitle = request.Dto.UpdateProcedure == CatalogUpdateProcedure.Update
|
|
||||||
? existing.CatTitle
|
|
||||||
: request.Dto.CatTitle;
|
|
||||||
entity.AddedWho = existing.AddedWho;
|
entity.AddedWho = existing.AddedWho;
|
||||||
entity.AddedWhen = existing.AddedWhen;
|
entity.AddedWhen = existing.AddedWhen;
|
||||||
entity.ChangedWho = "system";
|
entity.ChangedWho = "system";
|
||||||
entity.ChangedWhen = DateTime.UtcNow;
|
entity.ChangedWhen = DateTime.UtcNow;
|
||||||
|
|
||||||
var procedure = request.Dto.UpdateProcedure;
|
var updated = await _repository.UpdateAsync(request.Id, entity, request.Dto.UpdateProcedure, cancellationToken);
|
||||||
var updated = await _repository.UpdateAsync(request.Id, entity, procedure, cancellationToken);
|
|
||||||
return updated == null ? null : _mapper.Map<CatalogReadDto>(updated);
|
return updated == null ? null : _mapper.Map<CatalogReadDto>(updated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
DbFirst.Application/Layouts/LayoutDto.cs
Normal file
9
DbFirst.Application/Layouts/LayoutDto.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace DbFirst.Application.Layouts;
|
||||||
|
|
||||||
|
public class LayoutDto
|
||||||
|
{
|
||||||
|
public string LayoutType { get; set; } = string.Empty;
|
||||||
|
public string LayoutKey { get; set; } = string.Empty;
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public string LayoutData { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
6
DbFirst.BlazorWebApp/AppSettings.cs
Normal file
6
DbFirst.BlazorWebApp/AppSettings.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace DbFirst.BlazorWebApp;
|
||||||
|
|
||||||
|
public class AppSettings
|
||||||
|
{
|
||||||
|
public string ApiBaseUrl { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using DbFirst.BlazorWebApp.Services;
|
using DbFirst.BlazorWebApp.Services;
|
||||||
using DevExpress.Blazor;
|
using DevExpress.Blazor;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.AspNetCore.Components.Forms;
|
||||||
using Microsoft.AspNetCore.Components.Rendering;
|
using Microsoft.AspNetCore.Components.Rendering;
|
||||||
|
|
||||||
namespace DbFirst.BlazorWebApp.Components;
|
namespace DbFirst.BlazorWebApp.Components;
|
||||||
@@ -27,6 +28,15 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
|||||||
protected SizeMode _sizeMode = SizeMode.Medium;
|
protected SizeMode _sizeMode = SizeMode.Medium;
|
||||||
protected static readonly List<SizeMode> _sizeModes = Enum.GetValues<SizeMode>().ToList();
|
protected static readonly List<SizeMode> _sizeModes = Enum.GetValues<SizeMode>().ToList();
|
||||||
|
|
||||||
|
protected string? errorMessage;
|
||||||
|
protected string? infoMessage;
|
||||||
|
protected bool isLoading;
|
||||||
|
protected bool hasLoaded;
|
||||||
|
protected EditContext? editContext;
|
||||||
|
protected ValidationMessageStore? validationMessageStore;
|
||||||
|
protected string popupHeaderText = "Edit";
|
||||||
|
protected int _focusedVisibleIndex;
|
||||||
|
|
||||||
private const string LayoutType = "GRID_BANDS";
|
private const string LayoutType = "GRID_BANDS";
|
||||||
|
|
||||||
// --- Lifecycle ---
|
// --- Lifecycle ---
|
||||||
@@ -147,12 +157,12 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
|||||||
.Select(c => c.FieldName)
|
.Select(c => c.FieldName)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
_ = InvokeAsync(StateHasChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void UpdateBandOptions()
|
protected void UpdateBandOptions()
|
||||||
{
|
{
|
||||||
bandOptions = new List<BandOption> { new() { Id = string.Empty, Caption = "Ohne Band" } };
|
bandOptions = [new() { Id = string.Empty, Caption = "Ohne Band" }];
|
||||||
bandOptions.AddRange(bandLayout.Bands.Select(b => new BandOption { Id = b.Id, Caption = b.Caption }));
|
bandOptions.AddRange(bandLayout.Bands.Select(b => new BandOption { Id = b.Id, Caption = b.Caption }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,4 +226,53 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
|||||||
builder.AddAttribute(seq++, "ReadOnly", true);
|
builder.AddAttribute(seq++, "ReadOnly", true);
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void SetEditContext(EditContext context)
|
||||||
|
{
|
||||||
|
if (editContext == context) return;
|
||||||
|
if (editContext != null)
|
||||||
|
editContext.OnFieldChanged -= OnEditFieldChanged;
|
||||||
|
editContext = context;
|
||||||
|
validationMessageStore = new ValidationMessageStore(editContext);
|
||||||
|
editContext.OnFieldChanged += OnEditFieldChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnEditFieldChanged(object? sender, FieldChangedEventArgs e)
|
||||||
|
{
|
||||||
|
validationMessageStore?.Clear();
|
||||||
|
editContext?.NotifyValidationStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetPopupHeaderText(bool isNew) => popupHeaderText = isNew ? "Neu" : "Edit";
|
||||||
|
|
||||||
|
protected async Task EditFocusedRow()
|
||||||
|
=> await gridRef!.StartEditRowAsync(_focusedVisibleIndex);
|
||||||
|
|
||||||
|
protected Task DeleteFocusedRow()
|
||||||
|
{
|
||||||
|
gridRef!.ShowRowDeleteConfirmation(_focusedVisibleIndex);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task SaveLayoutWithFeedbackAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await SaveLayoutAsync();
|
||||||
|
infoMessage = "Layout gespeichert.";
|
||||||
|
errorMessage = null;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
errorMessage = $"Layout konnte nicht gespeichert werden: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task ResetLayoutWithFeedbackAsync()
|
||||||
|
{
|
||||||
|
await ResetLayoutAsync();
|
||||||
|
infoMessage = "Layout zurückgesetzt.";
|
||||||
|
errorMessage = null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
@inherits BandGridBase<CatalogReadDto>
|
@inherits BandGridBase<CatalogReadDto>
|
||||||
@inject CatalogApiClient Api
|
@inject ICatalogApiClient Api
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
||||||
{
|
{
|
||||||
@@ -149,14 +149,7 @@ else
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<CatalogReadDto> items = new();
|
private List<CatalogReadDto> items = new();
|
||||||
private bool isLoading;
|
|
||||||
private bool hasLoaded;
|
|
||||||
private string? errorMessage;
|
|
||||||
private string? infoMessage;
|
|
||||||
private EditContext? editContext;
|
|
||||||
private ValidationMessageStore? validationMessageStore;
|
|
||||||
private int? focusedRowKey;
|
private int? focusedRowKey;
|
||||||
private string popupHeaderText = "Edit";
|
|
||||||
|
|
||||||
protected override string LayoutKey => "CatalogsGrid";
|
protected override string LayoutKey => "CatalogsGrid";
|
||||||
protected override bool ShowCommandColumn => false;
|
protected override bool ShowCommandColumn => false;
|
||||||
@@ -209,17 +202,7 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetEditContext(EditContext context)
|
protected override void OnEditFieldChanged(object? sender, FieldChangedEventArgs e)
|
||||||
{
|
|
||||||
if (editContext == context) return;
|
|
||||||
if (editContext != null)
|
|
||||||
editContext.OnFieldChanged -= OnEditFieldChanged;
|
|
||||||
editContext = context;
|
|
||||||
validationMessageStore = new ValidationMessageStore(editContext);
|
|
||||||
editContext.OnFieldChanged += OnEditFieldChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEditFieldChanged(object? sender, FieldChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
if (validationMessageStore == null || editContext == null) return;
|
if (validationMessageStore == null || editContext == null) return;
|
||||||
|
|
||||||
@@ -237,8 +220,6 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetPopupHeaderText(bool isNew) => popupHeaderText = isNew ? "Neu" : "Edit";
|
|
||||||
|
|
||||||
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
||||||
{
|
{
|
||||||
popupHeaderText = e.IsNew ? "Neu" : "Edit";
|
popupHeaderText = e.IsNew ? "Neu" : "Edit";
|
||||||
@@ -378,36 +359,4 @@ else
|
|||||||
public int Value { get; set; }
|
public int Value { get; set; }
|
||||||
public string Text { get; set; } = string.Empty;
|
public string Text { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _focusedVisibleIndex;
|
|
||||||
|
|
||||||
private async Task EditFocusedRow()
|
|
||||||
=> await gridRef!.StartEditRowAsync(_focusedVisibleIndex);
|
|
||||||
|
|
||||||
private Task DeleteFocusedRow()
|
|
||||||
{
|
|
||||||
gridRef!.ShowRowDeleteConfirmation(_focusedVisibleIndex);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveLayoutWithFeedbackAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await SaveLayoutAsync();
|
|
||||||
infoMessage = "Layout gespeichert.";
|
|
||||||
errorMessage = null;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
errorMessage = $"Layout konnte nicht gespeichert werden: {ex.Message}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ResetLayoutWithFeedbackAsync()
|
|
||||||
{
|
|
||||||
await ResetLayoutAsync();
|
|
||||||
infoMessage = "Layout zurückgesetzt.";
|
|
||||||
errorMessage = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
@inherits BandGridBase<MassDataReadDto>
|
@inherits BandGridBase<MassDataReadDto>
|
||||||
@inject MassDataApiClient Api
|
@inject IMassDataApiClient Api
|
||||||
|
|
||||||
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
||||||
{
|
{
|
||||||
@@ -175,16 +175,9 @@ else
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<MassDataReadDto> items = new();
|
private List<MassDataReadDto> items = new();
|
||||||
private bool isLoading;
|
|
||||||
private bool hasLoaded;
|
|
||||||
private string? errorMessage;
|
|
||||||
private string? infoMessage;
|
|
||||||
private int pageIndex;
|
private int pageIndex;
|
||||||
private int pageCount = 1;
|
private int pageCount = 1;
|
||||||
private int? pageSize = 100;
|
private int? pageSize = 100;
|
||||||
private string popupHeaderText = "Edit";
|
|
||||||
private EditContext? editContext;
|
|
||||||
private ValidationMessageStore? validationMessageStore;
|
|
||||||
private int? focusedRowKey;
|
private int? focusedRowKey;
|
||||||
|
|
||||||
protected override string LayoutKey => "MassDataGrid";
|
protected override string LayoutKey => "MassDataGrid";
|
||||||
@@ -259,17 +252,7 @@ else
|
|||||||
await LoadPage(0);
|
await LoadPage(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetEditContext(EditContext context)
|
protected override void OnEditFieldChanged(object? sender, FieldChangedEventArgs e)
|
||||||
{
|
|
||||||
if (editContext == context) return;
|
|
||||||
if (editContext != null)
|
|
||||||
editContext.OnFieldChanged -= OnEditFieldChanged;
|
|
||||||
editContext = context;
|
|
||||||
validationMessageStore = new ValidationMessageStore(editContext);
|
|
||||||
editContext.OnFieldChanged += OnEditFieldChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnEditFieldChanged(object? sender, FieldChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
if (validationMessageStore == null || editContext == null) return;
|
if (validationMessageStore == null || editContext == null) return;
|
||||||
if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.UpdateProcedure))
|
if (e.FieldIdentifier.FieldName == nameof(MassDataEditModel.UpdateProcedure))
|
||||||
@@ -285,8 +268,6 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetPopupHeaderText(bool isNew) => popupHeaderText = isNew ? "Neu" : "Edit";
|
|
||||||
|
|
||||||
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.IsNew)
|
if (e.IsNew)
|
||||||
@@ -391,36 +372,4 @@ else
|
|||||||
public int? Value { get; set; }
|
public int? Value { get; set; }
|
||||||
public string Text { get; set; } = string.Empty;
|
public string Text { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int _focusedVisibleIndex;
|
|
||||||
|
|
||||||
private async Task EditFocusedRow()
|
|
||||||
=> await gridRef!.StartEditRowAsync(_focusedVisibleIndex);
|
|
||||||
|
|
||||||
private Task DeleteFocusedRow()
|
|
||||||
{
|
|
||||||
gridRef!.ShowRowDeleteConfirmation(_focusedVisibleIndex);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveLayoutWithFeedbackAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await SaveLayoutAsync();
|
|
||||||
infoMessage = "Layout gespeichert.";
|
|
||||||
errorMessage = null;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
errorMessage = $"Layout konnte nicht gespeichert werden: {ex.Message}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ResetLayoutWithFeedbackAsync()
|
|
||||||
{
|
|
||||||
await ResetLayoutAsync();
|
|
||||||
infoMessage = "Layout zurückgesetzt.";
|
|
||||||
errorMessage = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
@page "/dashboard"
|
@page "/dashboard"
|
||||||
@page "/dashboards/{DashboardId?}"
|
@page "/dashboards/{DashboardId?}"
|
||||||
@implements IAsyncDisposable
|
@implements IAsyncDisposable
|
||||||
@inject Microsoft.Extensions.Configuration.IConfiguration Configuration
|
@inject IOptions<AppSettings> AppSettingsOptions
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject DashboardApiClient DashboardApi
|
@inject IDashboardApiClient DashboardApi
|
||||||
|
|
||||||
<PageTitle>Dashboards</PageTitle>
|
<PageTitle>Dashboards</PageTitle>
|
||||||
|
|
||||||
@@ -45,12 +45,17 @@
|
|||||||
private string SelectedDashboardId { get; set; } = string.Empty;
|
private string SelectedDashboardId { get; set; } = string.Empty;
|
||||||
private string DashboardKey => $"{SelectedDashboardId}-{(IsDesigner ? "designer" : "viewer")}";
|
private string DashboardKey => $"{SelectedDashboardId}-{(IsDesigner ? "designer" : "viewer")}";
|
||||||
|
|
||||||
private string DashboardEndpoint => $"{Configuration["ApiBaseUrl"]?.TrimEnd('/')}/api/dashboard";
|
private string DashboardEndpoint => $"{AppSettingsOptions.Value.ApiBaseUrl.TrimEnd('/')}/api/dashboard";
|
||||||
private string HubEndpoint => $"{Configuration["ApiBaseUrl"]?.TrimEnd('/')}/hubs/dashboards";
|
private string HubEndpoint => $"{AppSettingsOptions.Value.ApiBaseUrl.TrimEnd('/')}/hubs/dashboards";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await RefreshDashboards();
|
await RefreshDashboards();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (!firstRender) return;
|
||||||
|
|
||||||
_hubConnection = new HubConnectionBuilder()
|
_hubConnection = new HubConnectionBuilder()
|
||||||
.WithUrl(HubEndpoint)
|
.WithUrl(HubEndpoint)
|
||||||
|
|||||||
@@ -18,3 +18,4 @@
|
|||||||
@using DevExpress.DashboardBlazor
|
@using DevExpress.DashboardBlazor
|
||||||
@using DevExpress.DashboardWeb
|
@using DevExpress.DashboardWeb
|
||||||
@using DevExpress.Data.Filtering
|
@using DevExpress.Data.Filtering
|
||||||
|
@using Microsoft.Extensions.Options
|
||||||
7
DbFirst.BlazorWebApp/Models/ApiResult.cs
Normal file
7
DbFirst.BlazorWebApp/Models/ApiResult.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace DbFirst.BlazorWebApp.Models;
|
||||||
|
|
||||||
|
public record ApiResult<T>(bool Success, T? Value, string? Error)
|
||||||
|
{
|
||||||
|
public static ApiResult<T> Ok(T? value) => new(true, value, null);
|
||||||
|
public static ApiResult<T> Fail(string? error) => new(false, default, error);
|
||||||
|
}
|
||||||
@@ -4,8 +4,8 @@ namespace DbFirst.BlazorWebApp.Models.Grid
|
|||||||
{
|
{
|
||||||
public class BandLayout
|
public class BandLayout
|
||||||
{
|
{
|
||||||
public List<BandDefinition> Bands { get; set; } = new();
|
public List<BandDefinition> Bands { get; set; } = [];
|
||||||
public List<string> ColumnOrder { get; set; } = new();
|
public List<string> ColumnOrder { get; set; } = [];
|
||||||
public Dictionary<string, string?> ColumnWidths { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
public Dictionary<string, string?> ColumnWidths { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
||||||
public GridPersistentLayout? GridLayout { get; set; }
|
public GridPersistentLayout? GridLayout { get; set; }
|
||||||
public SizeMode SizeMode { get; set; } = SizeMode.Medium;
|
public SizeMode SizeMode { get; set; } = SizeMode.Medium;
|
||||||
@@ -15,7 +15,7 @@ namespace DbFirst.BlazorWebApp.Models.Grid
|
|||||||
{
|
{
|
||||||
public string Id { get; set; } = string.Empty;
|
public string Id { get; set; } = string.Empty;
|
||||||
public string Caption { get; set; } = string.Empty;
|
public string Caption { get; set; } = string.Empty;
|
||||||
public List<string> Columns { get; set; } = new();
|
public List<string> Columns { get; set; } = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BandOption
|
public class BandOption
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using DbFirst.BlazorWebApp;
|
||||||
using DbFirst.BlazorWebApp.Components;
|
using DbFirst.BlazorWebApp.Components;
|
||||||
using DbFirst.BlazorWebApp.Services;
|
using DbFirst.BlazorWebApp.Services;
|
||||||
using DevExpress.Blazor;
|
using DevExpress.Blazor;
|
||||||
@@ -13,33 +14,18 @@ builder.Services.AddScoped<ThemeState>();
|
|||||||
builder.Services.AddScoped<BandLayoutService>();
|
builder.Services.AddScoped<BandLayoutService>();
|
||||||
|
|
||||||
var apiBaseUrl = builder.Configuration["ApiBaseUrl"];
|
var apiBaseUrl = builder.Configuration["ApiBaseUrl"];
|
||||||
if (!string.IsNullOrWhiteSpace(apiBaseUrl))
|
builder.Services.Configure<AppSettings>(builder.Configuration);
|
||||||
|
void ConfigureClient(HttpClient client)
|
||||||
{
|
{
|
||||||
builder.Services.AddHttpClient<CatalogApiClient>(client =>
|
if (!string.IsNullOrWhiteSpace(apiBaseUrl))
|
||||||
{
|
|
||||||
client.BaseAddress = new Uri(apiBaseUrl);
|
client.BaseAddress = new Uri(apiBaseUrl);
|
||||||
});
|
|
||||||
builder.Services.AddHttpClient<DashboardApiClient>(client =>
|
|
||||||
{
|
|
||||||
client.BaseAddress = new Uri(apiBaseUrl);
|
|
||||||
});
|
|
||||||
builder.Services.AddHttpClient<MassDataApiClient>(client =>
|
|
||||||
{
|
|
||||||
client.BaseAddress = new Uri(apiBaseUrl);
|
|
||||||
});
|
|
||||||
builder.Services.AddHttpClient<LayoutApiClient>(client =>
|
|
||||||
{
|
|
||||||
client.BaseAddress = new Uri(apiBaseUrl);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builder.Services.AddHttpClient<CatalogApiClient>();
|
|
||||||
builder.Services.AddHttpClient<DashboardApiClient>();
|
|
||||||
builder.Services.AddHttpClient<MassDataApiClient>();
|
|
||||||
builder.Services.AddHttpClient<LayoutApiClient>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.Services.AddHttpClient<ICatalogApiClient, CatalogApiClient>(ConfigureClient);
|
||||||
|
builder.Services.AddHttpClient<IDashboardApiClient, DashboardApiClient>(ConfigureClient);
|
||||||
|
builder.Services.AddHttpClient<IMassDataApiClient, MassDataApiClient>(ConfigureClient);
|
||||||
|
builder.Services.AddHttpClient<ILayoutApiClient, LayoutApiClient>(ConfigureClient);
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
|
|||||||
@@ -5,20 +5,26 @@ using System.Text.Json;
|
|||||||
|
|
||||||
namespace DbFirst.BlazorWebApp.Services
|
namespace DbFirst.BlazorWebApp.Services
|
||||||
{
|
{
|
||||||
public class BandLayoutService(LayoutApiClient layoutApi, IJSRuntime jsRuntime)
|
public class BandLayoutService(ILayoutApiClient layoutApi, IJSRuntime jsRuntime)
|
||||||
{
|
{
|
||||||
private const string LayoutUserStorageKey = "layoutUser";
|
private const string LayoutUserStorageKey = "layoutUser";
|
||||||
private readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
|
private readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
|
||||||
|
private string? _cachedLayoutUser;
|
||||||
|
|
||||||
public async Task<string> EnsureLayoutUserAsync()
|
public async Task<string> EnsureLayoutUserAsync()
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(_cachedLayoutUser))
|
||||||
|
return _cachedLayoutUser;
|
||||||
|
|
||||||
var layoutUser = await jsRuntime.InvokeAsync<string?>("localStorage.getItem", LayoutUserStorageKey);
|
var layoutUser = await jsRuntime.InvokeAsync<string?>("localStorage.getItem", LayoutUserStorageKey);
|
||||||
if (string.IsNullOrWhiteSpace(layoutUser))
|
if (string.IsNullOrWhiteSpace(layoutUser))
|
||||||
{
|
{
|
||||||
layoutUser = Guid.NewGuid().ToString("N");
|
layoutUser = Guid.NewGuid().ToString("N");
|
||||||
await jsRuntime.InvokeVoidAsync("localStorage.setItem", LayoutUserStorageKey, layoutUser);
|
await jsRuntime.InvokeVoidAsync("localStorage.setItem", LayoutUserStorageKey, layoutUser);
|
||||||
}
|
}
|
||||||
return layoutUser;
|
|
||||||
|
_cachedLayoutUser = layoutUser;
|
||||||
|
return _cachedLayoutUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<BandLayout> LoadBandLayoutAsync(
|
public async Task<BandLayout> LoadBandLayoutAsync(
|
||||||
@@ -82,9 +88,9 @@ namespace DbFirst.BlazorWebApp.Services
|
|||||||
Dictionary<string, ColumnDefinition> columnLookup)
|
Dictionary<string, ColumnDefinition> columnLookup)
|
||||||
{
|
{
|
||||||
layout ??= new BandLayout();
|
layout ??= new BandLayout();
|
||||||
layout.Bands ??= new List<BandDefinition>();
|
layout.Bands ??= [];
|
||||||
layout.ColumnOrder ??= new List<string>();
|
layout.ColumnOrder ??= [];
|
||||||
layout.ColumnWidths ??= new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
|
layout.ColumnWidths ??= [];
|
||||||
|
|
||||||
foreach (var band in layout.Bands)
|
foreach (var band in layout.Bands)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using DbFirst.BlazorWebApp.Models;
|
|||||||
|
|
||||||
namespace DbFirst.BlazorWebApp.Services;
|
namespace DbFirst.BlazorWebApp.Services;
|
||||||
|
|
||||||
public class CatalogApiClient
|
public class CatalogApiClient : ICatalogApiClient
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private const string Endpoint = "api/catalogs";
|
private const string Endpoint = "api/catalogs";
|
||||||
@@ -14,20 +14,20 @@ public class CatalogApiClient
|
|||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<CatalogReadDto>> GetAllAsync()
|
public async Task<List<CatalogReadDto>> GetAllAsync(CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var result = await _httpClient.GetFromJsonAsync<List<CatalogReadDto>>(Endpoint);
|
var result = await _httpClient.GetFromJsonAsync<List<CatalogReadDto>>(Endpoint, ct);
|
||||||
return result ?? new List<CatalogReadDto>();
|
return result ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CatalogReadDto?> GetByIdAsync(int id)
|
public async Task<CatalogReadDto?> GetByIdAsync(int id, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
return await _httpClient.GetFromJsonAsync<CatalogReadDto>($"{Endpoint}/{id}");
|
return await _httpClient.GetFromJsonAsync<CatalogReadDto>($"{Endpoint}/{id}", ct);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult<CatalogReadDto?>> CreateAsync(CatalogWriteDto dto)
|
public async Task<ApiResult<CatalogReadDto?>> CreateAsync(CatalogWriteDto dto, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.PostAsJsonAsync(Endpoint, dto);
|
var response = await _httpClient.PostAsJsonAsync(Endpoint, dto, ct);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var payload = await response.Content.ReadFromJsonAsync<CatalogReadDto>();
|
var payload = await response.Content.ReadFromJsonAsync<CatalogReadDto>();
|
||||||
@@ -38,9 +38,9 @@ public class CatalogApiClient
|
|||||||
return ApiResult<CatalogReadDto?>.Fail(error);
|
return ApiResult<CatalogReadDto?>.Fail(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult<bool>> UpdateAsync(int id, CatalogWriteDto dto)
|
public async Task<ApiResult<bool>> UpdateAsync(int id, CatalogWriteDto dto, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.PutAsJsonAsync($"{Endpoint}/{id}", dto);
|
var response = await _httpClient.PutAsJsonAsync($"{Endpoint}/{id}", dto, ct);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
return ApiResult<bool>.Ok(true);
|
return ApiResult<bool>.Ok(true);
|
||||||
@@ -50,9 +50,9 @@ public class CatalogApiClient
|
|||||||
return ApiResult<bool>.Fail(error);
|
return ApiResult<bool>.Fail(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult<bool>> DeleteAsync(int id)
|
public async Task<ApiResult<bool>> DeleteAsync(int id, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.DeleteAsync($"{Endpoint}/{id}");
|
var response = await _httpClient.DeleteAsync($"{Endpoint}/{id}", ct);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
return ApiResult<bool>.Ok(true);
|
return ApiResult<bool>.Ok(true);
|
||||||
@@ -62,10 +62,3 @@ public class CatalogApiClient
|
|||||||
return ApiResult<bool>.Fail(error);
|
return ApiResult<bool>.Fail(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ApiResult<T>(bool Success, T? Value, string? Error)
|
|
||||||
{
|
|
||||||
public static ApiResult<T> Ok(T? value) => new(true, value, null);
|
|
||||||
public static ApiResult<T> Fail(string? error) => new(false, default, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using DbFirst.BlazorWebApp.Models;
|
|||||||
|
|
||||||
namespace DbFirst.BlazorWebApp.Services;
|
namespace DbFirst.BlazorWebApp.Services;
|
||||||
|
|
||||||
public class DashboardApiClient
|
public class DashboardApiClient : IDashboardApiClient
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private const string Endpoint = "api/dashboard/dashboards";
|
private const string Endpoint = "api/dashboard/dashboards";
|
||||||
@@ -13,9 +13,9 @@ public class DashboardApiClient
|
|||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<DashboardInfoDto>> GetAllAsync()
|
public async Task<List<DashboardInfoDto>> GetAllAsync(CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var result = await _httpClient.GetFromJsonAsync<List<DashboardInfoDto>>(Endpoint);
|
var result = await _httpClient.GetFromJsonAsync<List<DashboardInfoDto>>(Endpoint, ct);
|
||||||
return result ?? new List<DashboardInfoDto>();
|
return result ?? [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
DbFirst.BlazorWebApp/Services/ICatalogApiClient.cs
Normal file
12
DbFirst.BlazorWebApp/Services/ICatalogApiClient.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using DbFirst.BlazorWebApp.Models;
|
||||||
|
|
||||||
|
namespace DbFirst.BlazorWebApp.Services;
|
||||||
|
|
||||||
|
public interface ICatalogApiClient
|
||||||
|
{
|
||||||
|
Task<List<CatalogReadDto>> GetAllAsync(CancellationToken ct = default);
|
||||||
|
Task<CatalogReadDto?> GetByIdAsync(int id, CancellationToken ct = default);
|
||||||
|
Task<ApiResult<CatalogReadDto?>> CreateAsync(CatalogWriteDto dto, CancellationToken ct = default);
|
||||||
|
Task<ApiResult<bool>> UpdateAsync(int id, CatalogWriteDto dto, CancellationToken ct = default);
|
||||||
|
Task<ApiResult<bool>> DeleteAsync(int id, CancellationToken ct = default);
|
||||||
|
}
|
||||||
9
DbFirst.BlazorWebApp/Services/IDashboardApiClient.cs
Normal file
9
DbFirst.BlazorWebApp/Services/IDashboardApiClient.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using DbFirst.BlazorWebApp.Models;
|
||||||
|
|
||||||
|
namespace DbFirst.BlazorWebApp.Services
|
||||||
|
{
|
||||||
|
public interface IDashboardApiClient
|
||||||
|
{
|
||||||
|
Task<List<DashboardInfoDto>> GetAllAsync(CancellationToken ct = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
DbFirst.BlazorWebApp/Services/ILayoutApiClient.cs
Normal file
11
DbFirst.BlazorWebApp/Services/ILayoutApiClient.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using DbFirst.BlazorWebApp.Models;
|
||||||
|
|
||||||
|
namespace DbFirst.BlazorWebApp.Services
|
||||||
|
{
|
||||||
|
public interface ILayoutApiClient
|
||||||
|
{
|
||||||
|
Task<LayoutDto?> GetAsync(string layoutType, string layoutKey, string userName, CancellationToken ct = default);
|
||||||
|
Task<LayoutDto> UpsertAsync(LayoutDto dto, CancellationToken ct = default);
|
||||||
|
Task DeleteAsync(string layoutType, string layoutKey, string userName, CancellationToken ct = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
DbFirst.BlazorWebApp/Services/IMassDataApiClient.cs
Normal file
12
DbFirst.BlazorWebApp/Services/IMassDataApiClient.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using DbFirst.BlazorWebApp.Models;
|
||||||
|
|
||||||
|
namespace DbFirst.BlazorWebApp.Services
|
||||||
|
{
|
||||||
|
public interface IMassDataApiClient
|
||||||
|
{
|
||||||
|
Task<int> GetCountAsync(CancellationToken ct = default);
|
||||||
|
Task<List<MassDataReadDto>> GetAllAsync(int? skip, int? take, CancellationToken ct = default);
|
||||||
|
Task<ApiResult<MassDataReadDto?>> UpsertAsync(MassDataWriteDto dto, CancellationToken ct = default);
|
||||||
|
Task<MassDataReadDto?> GetByCustomerNameAsync(string customerName, CancellationToken ct = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ using DbFirst.BlazorWebApp.Models;
|
|||||||
|
|
||||||
namespace DbFirst.BlazorWebApp.Services;
|
namespace DbFirst.BlazorWebApp.Services;
|
||||||
|
|
||||||
public class LayoutApiClient
|
public class LayoutApiClient : ILayoutApiClient
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private const string Endpoint = "api/layouts";
|
private const string Endpoint = "api/layouts";
|
||||||
@@ -13,10 +13,10 @@ public class LayoutApiClient
|
|||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LayoutDto?> GetAsync(string layoutType, string layoutKey, string userName)
|
public async Task<LayoutDto?> GetAsync(string layoutType, string layoutKey, string userName, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var url = $"{Endpoint}?layoutType={Uri.EscapeDataString(layoutType)}&layoutKey={Uri.EscapeDataString(layoutKey)}&userName={Uri.EscapeDataString(userName)}";
|
var url = $"{Endpoint}?layoutType={Uri.EscapeDataString(layoutType)}&layoutKey={Uri.EscapeDataString(layoutKey)}&userName={Uri.EscapeDataString(userName)}";
|
||||||
var response = await _httpClient.GetAsync(url);
|
var response = await _httpClient.GetAsync(url, ct);
|
||||||
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -26,12 +26,12 @@ public class LayoutApiClient
|
|||||||
return await response.Content.ReadFromJsonAsync<LayoutDto>();
|
return await response.Content.ReadFromJsonAsync<LayoutDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LayoutDto> UpsertAsync(LayoutDto dto)
|
public async Task<LayoutDto> UpsertAsync(LayoutDto dto, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.PostAsJsonAsync(Endpoint, dto);
|
var response = await _httpClient.PostAsJsonAsync(Endpoint, dto, ct);
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var detail = await ReadErrorAsync(response);
|
var detail = await ApiClientHelper.ReadErrorAsync(response);
|
||||||
throw new InvalidOperationException(detail);
|
throw new InvalidOperationException(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,21 +39,10 @@ public class LayoutApiClient
|
|||||||
return payload ?? dto;
|
return payload ?? dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<string> ReadErrorAsync(HttpResponseMessage response)
|
public async Task DeleteAsync(string layoutType, string layoutKey, string userName, CancellationToken ct = default)
|
||||||
{
|
|
||||||
var body = await response.Content.ReadAsStringAsync();
|
|
||||||
if (!string.IsNullOrWhiteSpace(body))
|
|
||||||
{
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $"{(int)response.StatusCode} {response.ReasonPhrase}".Trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteAsync(string layoutType, string layoutKey, string userName)
|
|
||||||
{
|
{
|
||||||
var url = $"{Endpoint}?layoutType={Uri.EscapeDataString(layoutType)}&layoutKey={Uri.EscapeDataString(layoutKey)}&userName={Uri.EscapeDataString(userName)}";
|
var url = $"{Endpoint}?layoutType={Uri.EscapeDataString(layoutType)}&layoutKey={Uri.EscapeDataString(layoutKey)}&userName={Uri.EscapeDataString(userName)}";
|
||||||
var response = await _httpClient.DeleteAsync(url);
|
var response = await _httpClient.DeleteAsync(url, ct);
|
||||||
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using DbFirst.BlazorWebApp.Models;
|
|||||||
|
|
||||||
namespace DbFirst.BlazorWebApp.Services;
|
namespace DbFirst.BlazorWebApp.Services;
|
||||||
|
|
||||||
public class MassDataApiClient
|
public class MassDataApiClient : IMassDataApiClient
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private const string Endpoint = "api/massdata";
|
private const string Endpoint = "api/massdata";
|
||||||
@@ -13,13 +13,13 @@ public class MassDataApiClient
|
|||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GetCountAsync()
|
public async Task<int> GetCountAsync(CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var result = await _httpClient.GetFromJsonAsync<int?>("api/massdata/count");
|
var result = await _httpClient.GetFromJsonAsync<int?>("api/massdata/count", ct);
|
||||||
return result ?? 0;
|
return result ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<MassDataReadDto>> GetAllAsync(int? skip, int? take)
|
public async Task<List<MassDataReadDto>> GetAllAsync(int? skip, int? take, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var query = new List<string>();
|
var query = new List<string>();
|
||||||
if (skip.HasValue)
|
if (skip.HasValue)
|
||||||
@@ -32,13 +32,13 @@ public class MassDataApiClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
var url = query.Count == 0 ? Endpoint : $"{Endpoint}?{string.Join("&", query)}";
|
var url = query.Count == 0 ? Endpoint : $"{Endpoint}?{string.Join("&", query)}";
|
||||||
var result = await _httpClient.GetFromJsonAsync<List<MassDataReadDto>>(url);
|
var result = await _httpClient.GetFromJsonAsync<List<MassDataReadDto>>(url, ct);
|
||||||
return result ?? new List<MassDataReadDto>();
|
return result ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ApiResult<MassDataReadDto?>> UpsertAsync(MassDataWriteDto dto)
|
public async Task<ApiResult<MassDataReadDto?>> UpsertAsync(MassDataWriteDto dto, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var response = await _httpClient.PostAsJsonAsync($"{Endpoint}/upsert", dto);
|
var response = await _httpClient.PostAsJsonAsync($"{Endpoint}/upsert", dto, ct);
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var payload = await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
var payload = await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
||||||
@@ -49,14 +49,14 @@ public class MassDataApiClient
|
|||||||
return ApiResult<MassDataReadDto?>.Fail(error);
|
return ApiResult<MassDataReadDto?>.Fail(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<MassDataReadDto?> GetByCustomerNameAsync(string customerName)
|
public async Task<MassDataReadDto?> GetByCustomerNameAsync(string customerName, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(customerName))
|
if (string.IsNullOrWhiteSpace(customerName))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = await _httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}");
|
var response = await _httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}", ct);
|
||||||
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using DbFirst.Application.Repositories;
|
||||||
|
using DbFirst.Infrastructure.Repositories;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -15,6 +17,10 @@ public static class DependencyInjection
|
|||||||
services.AddDbContext<MassDataDbContext>(options =>
|
services.AddDbContext<MassDataDbContext>(options =>
|
||||||
options.UseSqlServer(configuration.GetConnectionString("MassDataConnection")));
|
options.UseSqlServer(configuration.GetConnectionString("MassDataConnection")));
|
||||||
|
|
||||||
|
services.AddScoped<ICatalogRepository, CatalogRepository>();
|
||||||
|
services.AddScoped<IMassDataRepository, MassDataRepository>();
|
||||||
|
services.AddScoped<ILayoutRepository, LayoutRepository>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class LayoutRepository : ILayoutRepository
|
|||||||
UserName = userName,
|
UserName = userName,
|
||||||
LayoutData = layoutData,
|
LayoutData = layoutData,
|
||||||
AddedWho = userName,
|
AddedWho = userName,
|
||||||
AddedWhen = DateTime.Now
|
AddedWhen = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
_db.SmfLayouts.Add(entity);
|
_db.SmfLayouts.Add(entity);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user