Compare commits
9 Commits
1112fa215c
...
45011122b2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45011122b2 | ||
|
|
1b67d0472e | ||
|
|
a007842ab0 | ||
|
|
bf98432e20 | ||
|
|
d4b7f02c5e | ||
|
|
a0297d40a8 | ||
|
|
1c00449186 | ||
|
|
8a22217866 | ||
|
|
a6a17991bb |
@@ -132,13 +132,13 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
||||
UpdateBandOptions();
|
||||
}
|
||||
|
||||
protected void RemoveBand(BandDefinition band)
|
||||
protected async Task RemoveBand(BandDefinition band)
|
||||
{
|
||||
bandLayout.Bands.Remove(band);
|
||||
foreach (var key in columnBandAssignments.Where(p => p.Value == band.Id).Select(p => p.Key).ToList())
|
||||
columnBandAssignments.Remove(key);
|
||||
UpdateBandOptions();
|
||||
SyncBandsFromAssignments();
|
||||
await SyncBandsFromAssignments();
|
||||
}
|
||||
|
||||
protected void UpdateBandCaption(BandDefinition band, string value)
|
||||
@@ -147,19 +147,19 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
||||
UpdateBandOptions();
|
||||
}
|
||||
|
||||
protected void UpdateColumnBand(string fieldName, string? bandId)
|
||||
protected async Task UpdateColumnBand(string fieldName, string? bandId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(bandId))
|
||||
columnBandAssignments.Remove(fieldName);
|
||||
else
|
||||
columnBandAssignments[fieldName] = bandId;
|
||||
SyncBandsFromAssignments();
|
||||
await SyncBandsFromAssignments();
|
||||
}
|
||||
|
||||
protected string GetColumnBand(string fieldName)
|
||||
=> columnBandAssignments.TryGetValue(fieldName, out var bandId) ? bandId : string.Empty;
|
||||
|
||||
protected void SyncBandsFromAssignments()
|
||||
protected async Task SyncBandsFromAssignments()
|
||||
{
|
||||
foreach (var band in bandLayout.Bands)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
||||
.Select(c => c.FieldName)
|
||||
.ToList();
|
||||
}
|
||||
_ = InvokeAsync(StateHasChanged);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
protected void UpdateBandOptions()
|
||||
@@ -245,8 +245,8 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
||||
if (!_dateFilterTemplates.TryGetValue(fieldName, out var template))
|
||||
{
|
||||
// EventCallbacks einmalig erstellen – stabile Referenzen über alle Renders
|
||||
_fromCallbacks[fieldName] = EventCallback.Factory.Create<DateTime?>(this, (DateTime? v) => OnFilterFromChanged(fieldName, v));
|
||||
_toCallbacks[fieldName] = EventCallback.Factory.Create<DateTime?>(this, (DateTime? v) => OnFilterToChanged(fieldName, v));
|
||||
_fromCallbacks[fieldName] = EventCallback.Factory.Create<DateTime?>(this, async (DateTime? v) => await OnFilterFromChanged(fieldName, v));
|
||||
_toCallbacks[fieldName] = EventCallback.Factory.Create<DateTime?>(this, async (DateTime? v) => await OnFilterToChanged(fieldName, v));
|
||||
template = BuildDateFilterTemplate(fieldName);
|
||||
_dateFilterTemplates[fieldName] = template;
|
||||
}
|
||||
@@ -330,19 +330,19 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
||||
else if (op.OperatorType == BinaryOperatorType.Less) to = dt.AddDays(-1);
|
||||
}
|
||||
|
||||
private void OnFilterFromChanged(string fieldName, DateTime? value)
|
||||
private async Task OnFilterFromChanged(string fieldName, DateTime? value)
|
||||
{
|
||||
_filterFrom[fieldName] = value;
|
||||
ApplyDateFilter(fieldName);
|
||||
await ApplyDateFilter(fieldName);
|
||||
}
|
||||
|
||||
private void OnFilterToChanged(string fieldName, DateTime? value)
|
||||
private async Task OnFilterToChanged(string fieldName, DateTime? value)
|
||||
{
|
||||
_filterTo[fieldName] = value;
|
||||
ApplyDateFilter(fieldName);
|
||||
await ApplyDateFilter(fieldName);
|
||||
}
|
||||
|
||||
private void ApplyDateFilter(string fieldName)
|
||||
private async Task ApplyDateFilter(string fieldName)
|
||||
{
|
||||
var ops = new List<CriteriaOperator>();
|
||||
if (_filterFrom.TryGetValue(fieldName, out var from) && from.HasValue)
|
||||
@@ -360,7 +360,7 @@ public abstract class BandGridBase<TItem> : ComponentBase
|
||||
gridRef?.SetFieldFilterCriteria(fieldName, criteria);
|
||||
if (_filterContexts.TryGetValue(fieldName, out var ctx))
|
||||
ctx.FilterCriteria = criteria;
|
||||
_ = InvokeAsync(StateHasChanged);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
protected void SetEditContext(EditContext context)
|
||||
|
||||
@@ -117,7 +117,8 @@ else
|
||||
</Columns>
|
||||
<EditFormTemplate Context="editFormContext">
|
||||
@{
|
||||
SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew);
|
||||
SetEditContext(editFormContext.EditContext);
|
||||
var editModel = (CatalogEditModel)editFormContext.EditModel;
|
||||
}
|
||||
<DxFormLayout ColCount="2">
|
||||
<DxFormLayoutItem Caption="Titel">
|
||||
@@ -173,12 +174,16 @@ else
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await InitializeBandLayoutAsync();
|
||||
await LoadCatalogs();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await InitializeBandLayoutAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
await ApplyGridLayoutAfterRenderAsync();
|
||||
}
|
||||
|
||||
|
||||
@@ -50,13 +50,14 @@
|
||||
await ApplyDxDarkOverrideAsync();
|
||||
}
|
||||
|
||||
private async void OnThemeChanged()
|
||||
private void OnThemeChanged()
|
||||
{
|
||||
StateHasChanged();
|
||||
if (_isInteractive)
|
||||
InvokeAsync(async () =>
|
||||
{
|
||||
await ApplyDxDarkOverrideAsync();
|
||||
}
|
||||
StateHasChanged();
|
||||
if (_isInteractive)
|
||||
await ApplyDxDarkOverrideAsync();
|
||||
});
|
||||
}
|
||||
|
||||
private async Task ApplyDxDarkOverrideAsync()
|
||||
|
||||
@@ -137,7 +137,7 @@ else
|
||||
<DxTextBox @bind-Text="editModel.CustomerName" Width="100%" />
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Amount">
|
||||
<DxTextBox @bind-Text="editModel.AmountText" Width="100%" />
|
||||
<DxSpinEdit @bind-Value="editModel.Amount" MinValue="0" DisplayFormat="c2" Width="100%" />
|
||||
</DxFormLayoutItem>
|
||||
<DxFormLayoutItem Caption="Category">
|
||||
<DxTextBox @bind-Text="editModel.Category" Width="100%" ReadOnly="@(!editModel.IsNew)" />
|
||||
@@ -210,12 +210,16 @@ else
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await InitializeBandLayoutAsync();
|
||||
await LoadPage(0);
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await InitializeBandLayoutAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
await ApplyGridLayoutAfterRenderAsync();
|
||||
}
|
||||
|
||||
@@ -281,7 +285,7 @@ else
|
||||
{
|
||||
Id = item.Id,
|
||||
CustomerName = item.CustomerName,
|
||||
AmountText = item.Amount.ToString("0.00"),
|
||||
Amount = item.Amount,
|
||||
Category = item.Category,
|
||||
StatusFlag = item.StatusFlag,
|
||||
UpdateProcedure = procedureOptions[0].Value,
|
||||
@@ -298,12 +302,6 @@ else
|
||||
validationMessageStore?.Clear();
|
||||
editContext?.NotifyValidationStateChanged();
|
||||
var editModel = (MassDataEditModel)e.EditModel;
|
||||
if (!decimal.TryParse(editModel.AmountText, out var amount))
|
||||
{
|
||||
AddValidationError(editModel, nameof(MassDataEditModel.AmountText), "Amount ist ungültig.");
|
||||
e.Cancel = true;
|
||||
return;
|
||||
}
|
||||
if (editModel.IsNew)
|
||||
{
|
||||
var existing = await Api.GetByCustomerNameAsync(editModel.CustomerName);
|
||||
@@ -317,7 +315,7 @@ else
|
||||
var dto = new MassDataWriteDto
|
||||
{
|
||||
CustomerName = editModel.CustomerName,
|
||||
Amount = amount,
|
||||
Amount = editModel.Amount,
|
||||
Category = editModel.Category,
|
||||
StatusFlag = editModel.StatusFlag
|
||||
};
|
||||
@@ -353,7 +351,7 @@ else
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string CustomerName { get; set; } = string.Empty;
|
||||
public string AmountText { get; set; } = string.Empty;
|
||||
public decimal Amount { get; set; }
|
||||
public string Category { get; set; } = string.Empty;
|
||||
public bool StatusFlag { get; set; }
|
||||
public int UpdateProcedure { get; set; }
|
||||
|
||||
@@ -13,12 +13,12 @@ builder.Services.AddDevExpressBlazor(options => options.BootstrapVersion = Boots
|
||||
builder.Services.AddScoped<ThemeState>();
|
||||
builder.Services.AddScoped<BandLayoutService>();
|
||||
|
||||
var apiBaseUrl = builder.Configuration["ApiBaseUrl"];
|
||||
builder.Services.Configure<AppSettings>(builder.Configuration);
|
||||
var appSettings = builder.Configuration.Get<AppSettings>() ?? new AppSettings();
|
||||
void ConfigureClient(HttpClient client)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(apiBaseUrl))
|
||||
client.BaseAddress = new Uri(apiBaseUrl);
|
||||
if (!string.IsNullOrWhiteSpace(appSettings.ApiBaseUrl))
|
||||
client.BaseAddress = new Uri(appSettings.ApiBaseUrl);
|
||||
}
|
||||
|
||||
builder.Services.AddHttpClient<ICatalogApiClient, CatalogApiClient>(ConfigureClient);
|
||||
@@ -44,4 +44,4 @@ app.UseAntiforgery();
|
||||
app.MapRazorComponents<App>()
|
||||
.AddInteractiveServerRenderMode();
|
||||
|
||||
app.Run();
|
||||
app.Run();
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DbFirst.BlazorWebApp.Services;
|
||||
|
||||
@@ -25,7 +26,14 @@ internal static class ApiClientHelper
|
||||
problemDetail = problem.Detail ?? problem.Type;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
catch (JsonException)
|
||||
{
|
||||
// Ignoriere Fehler beim Lesen der Problem-Details, da sie optional sind
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
// Ignoriere Fehler beim Lesen der Problem-Details, da sie optional sind
|
||||
}
|
||||
|
||||
var status = response.StatusCode;
|
||||
var reason = response.ReasonPhrase;
|
||||
|
||||
@@ -3,30 +3,24 @@ using DbFirst.Contracts.Catalogs;
|
||||
|
||||
namespace DbFirst.BlazorWebApp.Services;
|
||||
|
||||
public class CatalogApiClient : ICatalogApiClient
|
||||
public class CatalogApiClient(HttpClient httpClient) : ICatalogApiClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private const string Endpoint = "api/catalogs";
|
||||
|
||||
public CatalogApiClient(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task<List<CatalogReadDto>> GetAllAsync(CancellationToken ct = default)
|
||||
{
|
||||
var result = await _httpClient.GetFromJsonAsync<List<CatalogReadDto>>(Endpoint, ct);
|
||||
var result = await httpClient.GetFromJsonAsync<List<CatalogReadDto>>(Endpoint, ct);
|
||||
return result ?? [];
|
||||
}
|
||||
|
||||
public async Task<CatalogReadDto?> GetByIdAsync(int id, CancellationToken ct = default)
|
||||
{
|
||||
return await _httpClient.GetFromJsonAsync<CatalogReadDto>($"{Endpoint}/{id}", ct);
|
||||
return await httpClient.GetFromJsonAsync<CatalogReadDto>($"{Endpoint}/{id}", ct);
|
||||
}
|
||||
|
||||
public async Task<ApiResult<CatalogReadDto?>> CreateAsync(CatalogWriteDto dto, CancellationToken ct = default)
|
||||
{
|
||||
var response = await _httpClient.PostAsJsonAsync(Endpoint, dto, ct);
|
||||
var response = await httpClient.PostAsJsonAsync(Endpoint, dto, ct);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var payload = await response.Content.ReadFromJsonAsync<CatalogReadDto>();
|
||||
@@ -39,7 +33,7 @@ public class CatalogApiClient : ICatalogApiClient
|
||||
|
||||
public async Task<ApiResult<bool>> UpdateAsync(int id, CatalogWriteDto dto, CancellationToken ct = default)
|
||||
{
|
||||
var response = await _httpClient.PutAsJsonAsync($"{Endpoint}/{id}", dto, ct);
|
||||
var response = await httpClient.PutAsJsonAsync($"{Endpoint}/{id}", dto, ct);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return ApiResult<bool>.Ok(true);
|
||||
@@ -51,7 +45,7 @@ public class CatalogApiClient : ICatalogApiClient
|
||||
|
||||
public async Task<ApiResult<bool>> DeleteAsync(int id, CancellationToken ct = default)
|
||||
{
|
||||
var response = await _httpClient.DeleteAsync($"{Endpoint}/{id}", ct);
|
||||
var response = await httpClient.DeleteAsync($"{Endpoint}/{id}", ct);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return ApiResult<bool>.Ok(true);
|
||||
|
||||
@@ -2,19 +2,13 @@ using DbFirst.Contracts.Dashboards;
|
||||
|
||||
namespace DbFirst.BlazorWebApp.Services;
|
||||
|
||||
public class DashboardApiClient : IDashboardApiClient
|
||||
public class DashboardApiClient(HttpClient httpClient) : IDashboardApiClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private const string Endpoint = "api/dashboard/dashboards";
|
||||
|
||||
public DashboardApiClient(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task<List<DashboardInfoDto>> GetAllAsync(CancellationToken ct = default)
|
||||
{
|
||||
var result = await _httpClient.GetFromJsonAsync<List<DashboardInfoDto>>(Endpoint, ct);
|
||||
var result = await httpClient.GetFromJsonAsync<List<DashboardInfoDto>>(Endpoint, ct);
|
||||
return result ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,14 @@ using DbFirst.Contracts.Layouts;
|
||||
|
||||
namespace DbFirst.BlazorWebApp.Services;
|
||||
|
||||
public class LayoutApiClient : ILayoutApiClient
|
||||
public class LayoutApiClient(HttpClient httpClient) : ILayoutApiClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private const string Endpoint = "api/layouts";
|
||||
|
||||
public LayoutApiClient(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
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 response = await _httpClient.GetAsync(url, ct);
|
||||
var response = await httpClient.GetAsync(url, ct);
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
return null;
|
||||
@@ -27,7 +21,7 @@ public class LayoutApiClient : ILayoutApiClient
|
||||
|
||||
public async Task<LayoutDto> UpsertAsync(LayoutDto dto, CancellationToken ct = default)
|
||||
{
|
||||
var response = await _httpClient.PostAsJsonAsync(Endpoint, dto, ct);
|
||||
var response = await httpClient.PostAsJsonAsync(Endpoint, dto, ct);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var detail = await ApiClientHelper.ReadErrorAsync(response);
|
||||
@@ -41,7 +35,7 @@ public class LayoutApiClient : ILayoutApiClient
|
||||
public async Task DeleteAsync(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 response = await _httpClient.DeleteAsync(url, ct);
|
||||
var response = await httpClient.DeleteAsync(url, ct);
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -1,44 +1,33 @@
|
||||
using DbFirst.BlazorWebApp.Models;
|
||||
using DbFirst.Contracts.MassData;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
|
||||
namespace DbFirst.BlazorWebApp.Services;
|
||||
|
||||
public class MassDataApiClient : IMassDataApiClient
|
||||
public class MassDataApiClient(HttpClient httpClient) : IMassDataApiClient
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private const string Endpoint = "api/massdata";
|
||||
|
||||
public MassDataApiClient(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task<int> GetCountAsync(CancellationToken ct = default)
|
||||
{
|
||||
var result = await _httpClient.GetFromJsonAsync<int?>("api/massdata/count", ct);
|
||||
var result = await httpClient.GetFromJsonAsync<int?>("api/massdata/count", ct);
|
||||
return result ?? 0;
|
||||
}
|
||||
|
||||
public async Task<List<MassDataReadDto>> GetAllAsync(int? skip, int? take, CancellationToken ct = default)
|
||||
{
|
||||
var query = new List<string>();
|
||||
if (skip.HasValue)
|
||||
{
|
||||
query.Add($"skip={skip.Value}");
|
||||
}
|
||||
if (take.HasValue)
|
||||
{
|
||||
query.Add($"take={take.Value}");
|
||||
}
|
||||
var query = new Dictionary<string, string?>();
|
||||
if (skip.HasValue) query["skip"] = skip.Value.ToString();
|
||||
if (take.HasValue) query["take"] = take.Value.ToString();
|
||||
|
||||
var url = query.Count == 0 ? Endpoint : $"{Endpoint}?{string.Join("&", query)}";
|
||||
var result = await _httpClient.GetFromJsonAsync<List<MassDataReadDto>>(url, ct);
|
||||
var url = QueryHelpers.AddQueryString(Endpoint, query);
|
||||
var result = await httpClient.GetFromJsonAsync<List<MassDataReadDto>>(url, ct);
|
||||
return result ?? [];
|
||||
}
|
||||
|
||||
public async Task<ApiResult<MassDataReadDto?>> UpsertAsync(MassDataWriteDto dto, CancellationToken ct = default)
|
||||
{
|
||||
var response = await _httpClient.PostAsJsonAsync($"{Endpoint}/upsert", dto, ct);
|
||||
var response = await httpClient.PostAsJsonAsync($"{Endpoint}/upsert", dto, ct);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var payload = await response.Content.ReadFromJsonAsync<MassDataReadDto>();
|
||||
@@ -56,7 +45,7 @@ public class MassDataApiClient : IMassDataApiClient
|
||||
return null;
|
||||
}
|
||||
|
||||
var response = await _httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}", ct);
|
||||
var response = await httpClient.GetAsync($"{Endpoint}/{Uri.EscapeDataString(customerName)}", ct);
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user