Reorganize and deduplicate using directives in _Imports.razor for clarity and maintainability. Explicitly cast UpdateProcedure to CatalogUpdateProcedure in CatalogsGrid.razor to enforce type safety. Restore necessary DevExpress and DbFirst namespaces.
362 lines
14 KiB
Plaintext
362 lines
14 KiB
Plaintext
@inherits BandGridBase<CatalogReadDto>
|
|
@inject ICatalogApiClient Api
|
|
|
|
@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>
|
|
}
|
|
|
|
@if (!hasLoaded || isLoading)
|
|
{
|
|
<div class="loading-container">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Lade...</span>
|
|
</div>
|
|
</div>
|
|
}
|
|
else if (items.Count == 0)
|
|
{
|
|
<p>Keine Einträge vorhanden.</p>
|
|
}
|
|
else
|
|
{
|
|
<BandEditor Bands="@bandLayout.Bands"
|
|
BandOptions="@bandOptions"
|
|
Columns="@ColumnDefinitions"
|
|
GetColumnBand="GetColumnBand"
|
|
CanSave="@CanSaveBandLayout"
|
|
OnAddBand="AddBand"
|
|
OnSaveLayout="SaveLayoutWithFeedbackAsync"
|
|
OnResetLayout="ResetLayoutWithFeedbackAsync"
|
|
OnRemoveBand="RemoveBand"
|
|
OnBandCaptionChanged="@(args => UpdateBandCaption(args.Band, args.Value))"
|
|
OnColumnBandChanged="@(args => UpdateColumnBand(args.FieldName, args.BandId))" />
|
|
|
|
<div class="grid-section">
|
|
<DxGrid Data="@items"
|
|
ColumnChooserButtonDisplayMode="GridColumnChooserButtonDisplayMode.Always"
|
|
TItem="CatalogReadDto"
|
|
KeyFieldName="@nameof(CatalogReadDto.Guid)"
|
|
SizeMode="@_sizeMode"
|
|
ShowGroupPanel="true"
|
|
ShowGroupedColumns="true"
|
|
AllowGroup="true"
|
|
FilterMenuButtonDisplayMode="GridFilterMenuButtonDisplayMode.Always"
|
|
AllowColumnResize="true"
|
|
ColumnResizeMode="GridColumnResizeMode.ColumnsContainer"
|
|
AllowColumnReorder="true"
|
|
PageSize="10"
|
|
CssClass="mb-4 catalog-grid"
|
|
EditMode="GridEditMode.PopupEditForm"
|
|
PopupEditFormCssClass="catalog-edit-popup"
|
|
PopupEditFormHeaderText="@popupHeaderText"
|
|
CustomizeEditModel="OnCustomizeEditModel"
|
|
EditModelSaving="OnEditModelSaving"
|
|
DataItemDeleting="OnDataItemDeleting"
|
|
FocusedRowEnabled="true"
|
|
@bind-FocusedRowKey="focusedRowKey"
|
|
RowClick="@(args => _focusedVisibleIndex = args.VisibleIndex)"
|
|
@ref="gridRef">
|
|
<ToolbarTemplate>
|
|
<DxToolbar>
|
|
<DxToolbarItem Alignment="ToolbarItemAlignment.Left">
|
|
<Template Context="_">
|
|
<DxButton IconCssClass="bi bi-plus-lg"
|
|
RenderStyle="ButtonRenderStyle.Secondary"
|
|
RenderStyleMode="ButtonRenderStyleMode.Text"
|
|
Click="@(() => gridRef!.StartEditNewRowAsync())" />
|
|
</Template>
|
|
</DxToolbarItem>
|
|
<DxToolbarItem Alignment="ToolbarItemAlignment.Left">
|
|
<Template Context="_">
|
|
<DxButton IconCssClass="bi bi-pencil"
|
|
RenderStyle="ButtonRenderStyle.Secondary"
|
|
RenderStyleMode="ButtonRenderStyleMode.Text"
|
|
Click="EditFocusedRow" />
|
|
</Template>
|
|
</DxToolbarItem>
|
|
<DxToolbarItem Alignment="ToolbarItemAlignment.Left">
|
|
<Template Context="_">
|
|
<DxButton IconCssClass="bi bi-trash"
|
|
RenderStyle="ButtonRenderStyle.Secondary"
|
|
RenderStyleMode="ButtonRenderStyleMode.Text"
|
|
Click="DeleteFocusedRow" />
|
|
</Template>
|
|
</DxToolbarItem>
|
|
<DxToolbarItem Alignment="ToolbarItemAlignment.Right">
|
|
<Template Context="_">
|
|
<DxButton Text="Spalten"
|
|
RenderStyle="ButtonRenderStyle.Secondary"
|
|
RenderStyleMode="ButtonRenderStyleMode.Text"
|
|
Click="@(() => gridRef!.ShowColumnChooser())" />
|
|
</Template>
|
|
</DxToolbarItem>
|
|
<DxToolbarItem Alignment="ToolbarItemAlignment.Right">
|
|
<Template Context="_">
|
|
<DxDropDownButton Text="@FormatSizeText(_sizeMode)"
|
|
RenderStyle="ButtonRenderStyle.Secondary"
|
|
RenderStyleMode="ButtonRenderStyleMode.Text"
|
|
ItemClick="OnSizeChange">
|
|
<Items>
|
|
@foreach (var size in _sizeModes)
|
|
{
|
|
<DxDropDownButtonItem Text="@FormatSizeText(size)" Id="@size.ToString()" />
|
|
}
|
|
</Items>
|
|
</DxDropDownButton>
|
|
</Template>
|
|
</DxToolbarItem>
|
|
</DxToolbar>
|
|
</ToolbarTemplate>
|
|
<Columns>
|
|
@RenderColumns()
|
|
</Columns>
|
|
<EditFormTemplate Context="editFormContext">
|
|
@{
|
|
SetEditContext(editFormContext.EditContext); var editModel = (CatalogEditModel)editFormContext.EditModel; SetPopupHeaderText(editModel.IsNew);
|
|
}
|
|
<DxFormLayout ColCount="2">
|
|
<DxFormLayoutItem Caption="Titel">
|
|
<DxTextBox @bind-Text="editModel.CatTitle" Width="100%" />
|
|
</DxFormLayoutItem>
|
|
<DxFormLayoutItem Caption="Kennung">
|
|
<DxTextBox @bind-Text="editModel.CatString" Width="100%" />
|
|
</DxFormLayoutItem>
|
|
@if (!editModel.IsNew)
|
|
{
|
|
<DxFormLayoutItem Caption="Update-Prozedur">
|
|
<DxComboBox Data="@procedureOptions"
|
|
TData="ProcedureOption"
|
|
TValue="int"
|
|
TextFieldName="Text"
|
|
ValueFieldName="Value"
|
|
@bind-Value="editModel.UpdateProcedure"
|
|
Width="100%" />
|
|
</DxFormLayoutItem>
|
|
}
|
|
<DxFormLayoutItem ColSpanMd="12">
|
|
<ValidationSummary />
|
|
</DxFormLayoutItem>
|
|
</DxFormLayout>
|
|
</EditFormTemplate>
|
|
</DxGrid>
|
|
</div>
|
|
}
|
|
|
|
@code {
|
|
private List<CatalogReadDto> items = new();
|
|
private int? focusedRowKey;
|
|
|
|
protected override string LayoutKey => "CatalogsGrid";
|
|
protected override bool ShowCommandColumn => false;
|
|
|
|
protected override List<ColumnDefinition> ColumnDefinitions { get; } = new()
|
|
{
|
|
new() { FieldName = nameof(CatalogReadDto.Guid), Caption = "Id", Width = "140px", FilterType = ColumnFilterType.Text },
|
|
new() { FieldName = nameof(CatalogReadDto.CatTitle), Caption = "Titel", FilterType = ColumnFilterType.Text },
|
|
new() { FieldName = nameof(CatalogReadDto.CatString), Caption = "String", FilterType = ColumnFilterType.Text },
|
|
new() { FieldName = nameof(CatalogReadDto.AddedWho), Caption = "Angelegt von", ReadOnly = true, FilterType = ColumnFilterType.Text },
|
|
new() { FieldName = nameof(CatalogReadDto.AddedWhen), Caption = "Angelegt am", ReadOnly = true, FilterType = ColumnFilterType.Date },
|
|
new() { FieldName = nameof(CatalogReadDto.ChangedWho), Caption = "Geändert von", ReadOnly = true, FilterType = ColumnFilterType.Text },
|
|
new() { FieldName = nameof(CatalogReadDto.ChangedWhen),Caption = "Geändert am", ReadOnly = true, FilterType = ColumnFilterType.Date }
|
|
};
|
|
|
|
private readonly List<ProcedureOption> procedureOptions = new()
|
|
{
|
|
new() { Value = 0, Text = "PRTBMY_CATALOG_UPDATE" },
|
|
new() { Value = 1, Text = "PRTBMY_CATALOG_SAVE" }
|
|
};
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
await InitializeBandLayoutAsync();
|
|
await LoadCatalogs();
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
await ApplyGridLayoutAfterRenderAsync();
|
|
}
|
|
|
|
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;
|
|
hasLoaded = true;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
protected override void OnEditFieldChanged(object? sender, FieldChangedEventArgs e)
|
|
{
|
|
if (validationMessageStore == null || editContext == null) return;
|
|
|
|
if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.UpdateProcedure))
|
|
{
|
|
validationMessageStore.Clear();
|
|
editContext.NotifyValidationStateChanged();
|
|
return;
|
|
}
|
|
|
|
if (e.FieldIdentifier.FieldName == nameof(CatalogEditModel.CatTitle))
|
|
{
|
|
validationMessageStore.Clear(new FieldIdentifier(editContext.Model, nameof(CatalogEditModel.CatTitle)));
|
|
editContext.NotifyValidationStateChanged();
|
|
}
|
|
}
|
|
|
|
private void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e)
|
|
{
|
|
popupHeaderText = e.IsNew ? "Neu" : "Edit";
|
|
if (e.IsNew)
|
|
{
|
|
e.EditModel = new CatalogEditModel { IsNew = true };
|
|
return;
|
|
}
|
|
|
|
var item = (CatalogReadDto)e.DataItem;
|
|
e.EditModel = new CatalogEditModel
|
|
{
|
|
Guid = item.Guid,
|
|
CatTitle = item.CatTitle,
|
|
CatString = item.CatString,
|
|
UpdateProcedure = 0,
|
|
OriginalCatTitle = item.CatTitle,
|
|
IsNew = false
|
|
};
|
|
}
|
|
|
|
private async Task OnEditModelSaving(GridEditModelSavingEventArgs e)
|
|
{
|
|
errorMessage = null;
|
|
infoMessage = null;
|
|
validationMessageStore?.Clear();
|
|
editContext?.NotifyValidationStateChanged();
|
|
|
|
var editModel = (CatalogEditModel)e.EditModel;
|
|
if (!ValidateEditModel(editModel, e.IsNew))
|
|
{
|
|
e.Cancel = true;
|
|
return;
|
|
}
|
|
|
|
var dto = new CatalogWriteDto
|
|
{
|
|
CatTitle = editModel.CatTitle,
|
|
CatString = editModel.CatString,
|
|
UpdateProcedure = (CatalogUpdateProcedure)editModel.UpdateProcedure
|
|
};
|
|
|
|
try
|
|
{
|
|
if (e.IsNew)
|
|
{
|
|
var created = await Api.CreateAsync(dto);
|
|
if (!created.Success || created.Value == null)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(created.Error))
|
|
AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), created.Error);
|
|
else
|
|
errorMessage = "Anlegen fehlgeschlagen.";
|
|
e.Cancel = true;
|
|
return;
|
|
}
|
|
infoMessage = "Katalog angelegt.";
|
|
focusedRowKey = created.Value.Guid;
|
|
}
|
|
else
|
|
{
|
|
var updated = await Api.UpdateAsync(editModel.Guid, dto);
|
|
if (!updated.Success)
|
|
{
|
|
errorMessage = updated.Error ?? "Aktualisierung fehlgeschlagen.";
|
|
e.Cancel = true;
|
|
return;
|
|
}
|
|
infoMessage = "Katalog aktualisiert.";
|
|
focusedRowKey = editModel.Guid;
|
|
}
|
|
|
|
await LoadCatalogs();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Fehler beim Speichern: {ex.Message}";
|
|
e.Cancel = true;
|
|
}
|
|
}
|
|
|
|
private void AddValidationError(CatalogEditModel editModel, string fieldName, string message)
|
|
{
|
|
if (editContext == null || validationMessageStore == null) return;
|
|
validationMessageStore.Add(new FieldIdentifier(editModel, fieldName), message);
|
|
editContext.NotifyValidationStateChanged();
|
|
}
|
|
|
|
private bool ValidateEditModel(CatalogEditModel editModel, bool isNew)
|
|
{
|
|
if (isNew) return true;
|
|
if (editModel.UpdateProcedure == 0 &&
|
|
!string.Equals(editModel.CatTitle, editModel.OriginalCatTitle, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
AddValidationError(editModel, nameof(CatalogEditModel.CatTitle), "Titel kann nicht geändert werden.");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private async Task OnDataItemDeleting(GridDataItemDeletingEventArgs e)
|
|
{
|
|
errorMessage = null;
|
|
infoMessage = null;
|
|
var item = (CatalogReadDto)e.DataItem;
|
|
try
|
|
{
|
|
var deleted = await Api.DeleteAsync(item.Guid);
|
|
if (!deleted.Success)
|
|
{
|
|
errorMessage = deleted.Error ?? "Löschen fehlgeschlagen.";
|
|
e.Cancel = true;
|
|
return;
|
|
}
|
|
infoMessage = "Katalog gelöscht.";
|
|
await LoadCatalogs();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Fehler beim Löschen: {ex.Message}";
|
|
e.Cancel = true;
|
|
}
|
|
}
|
|
|
|
private sealed class CatalogEditModel
|
|
{
|
|
public int Guid { get; set; }
|
|
public string CatTitle { get; set; } = string.Empty;
|
|
public string CatString { get; set; } = string.Empty;
|
|
public int UpdateProcedure { get; set; }
|
|
public string OriginalCatTitle { get; set; } = string.Empty;
|
|
public bool IsNew { get; set; }
|
|
}
|
|
|
|
private sealed class ProcedureOption
|
|
{
|
|
public int Value { get; set; }
|
|
public string Text { get; set; } = string.Empty;
|
|
}
|
|
} |