- Split `CatalogDto` into `CatalogReadDto` and `CatalogWriteDto` for clear separation of read/write operations in both backend and frontend. - Updated API controllers, services, and AutoMapper profiles to use new DTOs; ensured audit fields are set in service layer. - Enabled CORS in the API project to support Blazor WASM frontend. - Added new Blazor WebAssembly project (`DbFirst.BlazorWasm`) with catalog management UI, API client, Bootstrap v5.1.0 styling, and configuration-driven API base URL. - Included `bootstrap.min.css` and its source map for frontend styling and easier debugging. - Updated solution file to include new project and support multiple build configurations. - Result: improved API design, clean DTO separation, and a modern interactive frontend for catalog management.
213 lines
5.5 KiB
Plaintext
213 lines
5.5 KiB
Plaintext
@page "/catalogs"
|
|
@inject CatalogApiClient Api
|
|
|
|
<PageTitle>Catalogs</PageTitle>
|
|
|
|
<h1>Catalogs</h1>
|
|
|
|
@if (!string.IsNullOrWhiteSpace(errorMessage))
|
|
{
|
|
<div class="alert alert-danger" role="alert">@errorMessage</div>
|
|
}
|
|
else if (!string.IsNullOrWhiteSpace(infoMessage))
|
|
{
|
|
<div class="alert alert-success" role="alert">@infoMessage</div>
|
|
}
|
|
|
|
<div class="mb-3">
|
|
<button class="btn btn-primary" @onclick="StartCreate">Neuen Eintrag anlegen</button>
|
|
</div>
|
|
|
|
@if (showForm)
|
|
{
|
|
<EditForm Model="formModel" OnValidSubmit="HandleSubmit">
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label">Titel</label>
|
|
<InputText class="form-control" @bind-Value="formModel.CatTitle" />
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">Kennung</label>
|
|
<InputText class="form-control" @bind-Value="formModel.CatString" />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-3 d-flex gap-2">
|
|
<button type="submit" class="btn btn-success">@((isEditing ? "Speichern" : "Anlegen"))</button>
|
|
<button type="button" class="btn btn-secondary" @onclick="CancelEdit">Abbrechen</button>
|
|
</div>
|
|
</EditForm>
|
|
}
|
|
|
|
@if (isLoading)
|
|
{
|
|
<p><em>Lade Daten...</em></p>
|
|
}
|
|
else if (items.Count == 0)
|
|
{
|
|
<p>Keine Einträge vorhanden.</p>
|
|
}
|
|
else
|
|
{
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Id</th>
|
|
<th>Titel</th>
|
|
<th>String</th>
|
|
<th>Angelegt von</th>
|
|
<th>Angelegt am</th>
|
|
<th>Geändert von</th>
|
|
<th>Geändert am</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in items)
|
|
{
|
|
<tr>
|
|
<td>@item.Guid</td>
|
|
<td>@item.CatTitle</td>
|
|
<td>@item.CatString</td>
|
|
<td>@item.AddedWho</td>
|
|
<td>@item.AddedWhen.ToString("g")</td>
|
|
<td>@item.ChangedWho</td>
|
|
<td>@(item.ChangedWhen.HasValue ? item.ChangedWhen.Value.ToString("g") : string.Empty)</td>
|
|
<td class="text-end">
|
|
<button class="btn btn-sm btn-outline-primary me-2" @onclick="(() => StartEdit(item))">Bearbeiten</button>
|
|
<button class="btn btn-sm btn-outline-danger" @onclick="(() => DeleteCatalog(item.Guid))">Löschen</button>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
}
|
|
|
|
@code {
|
|
private List<CatalogReadDto> items = new();
|
|
private CatalogWriteDto formModel = new();
|
|
private int editingId;
|
|
private bool isLoading;
|
|
private bool isEditing;
|
|
private bool showForm;
|
|
private string? errorMessage;
|
|
private string? infoMessage;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await LoadCatalogs();
|
|
}
|
|
|
|
private async Task LoadCatalogs()
|
|
{
|
|
isLoading = true;
|
|
errorMessage = null;
|
|
try
|
|
{
|
|
items = await Api.GetAllAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Kataloge konnten nicht geladen werden: {ex.Message}";
|
|
}
|
|
finally
|
|
{
|
|
isLoading = false;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
private void StartCreate()
|
|
{
|
|
formModel = new CatalogWriteDto();
|
|
editingId = 0;
|
|
isEditing = false;
|
|
showForm = true;
|
|
infoMessage = null;
|
|
errorMessage = null;
|
|
}
|
|
|
|
private void StartEdit(CatalogReadDto item)
|
|
{
|
|
formModel = new CatalogWriteDto
|
|
{
|
|
CatTitle = item.CatTitle,
|
|
CatString = item.CatString
|
|
};
|
|
editingId = item.Guid;
|
|
isEditing = true;
|
|
showForm = true;
|
|
infoMessage = null;
|
|
errorMessage = null;
|
|
}
|
|
|
|
private async Task HandleSubmit()
|
|
{
|
|
errorMessage = null;
|
|
infoMessage = null;
|
|
|
|
try
|
|
{
|
|
if (isEditing)
|
|
{
|
|
var updated = await Api.UpdateAsync(editingId, formModel);
|
|
if (!updated)
|
|
{
|
|
errorMessage = "Aktualisierung fehlgeschlagen.";
|
|
return;
|
|
}
|
|
|
|
infoMessage = "Katalog aktualisiert.";
|
|
}
|
|
else
|
|
{
|
|
var created = await Api.CreateAsync(formModel);
|
|
if (created == null)
|
|
{
|
|
errorMessage = "Anlegen fehlgeschlagen.";
|
|
return;
|
|
}
|
|
|
|
infoMessage = "Katalog angelegt.";
|
|
}
|
|
|
|
showForm = false;
|
|
await LoadCatalogs();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Fehler beim Speichern: {ex.Message}";
|
|
}
|
|
}
|
|
|
|
private void CancelEdit()
|
|
{
|
|
showForm = false;
|
|
infoMessage = null;
|
|
errorMessage = null;
|
|
}
|
|
|
|
private async Task DeleteCatalog(int id)
|
|
{
|
|
errorMessage = null;
|
|
infoMessage = null;
|
|
|
|
try
|
|
{
|
|
var deleted = await Api.DeleteAsync(id);
|
|
if (!deleted)
|
|
{
|
|
errorMessage = "Löschen fehlgeschlagen.";
|
|
return;
|
|
}
|
|
|
|
infoMessage = "Katalog gelöscht.";
|
|
await LoadCatalogs();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Fehler beim Löschen: {ex.Message}";
|
|
}
|
|
}
|
|
}
|