1
0
mirror of https://github.com/akpaevj/onecmonitor.git synced 2026-06-13 21:18:17 +02:00
Files

174 lines
4.9 KiB
Plaintext

@inject NavigationManager NavigationManager
@inject IDbContextFactory<AppDbContext> ContextFactory
@inject ISnackbar SnackBar
@implements IDisposable
@attribute [CascadingTypeParameter(nameof(T))]
@using Microsoft.EntityFrameworkCore
@using OneSwiss.Server.Components.Layout
@using OneSwiss.Server.Extensions
@typeparam T where T : class, OneSwiss.Server.Models.IHasId, new()
<MudStack>
<MudForm @ref="Form" Model="Model!" Validation="Validation" Disabled="@(!Editable)">
@ChildContent
</MudForm>
<MudStack Row AlignItems="AlignItems.End" Class="mb-3" Breakpoint="Breakpoint.SmAndDown">
@if (Editable)
{
<MudSpacer/>
<MudButton Variant="Variant.Outlined" Size="Size.Small" Color="Color.Primary" OnClick="Save">Сохранить
</MudButton>
}
</MudStack>
</MudStack>
@code
{
private MudForm Form { get; set; } = null!;
public AppDbContext? Context { get; private set; }
public T? Model { get; set; }
/// <summary>
/// Идентификатор элемента
/// </summary>
[Parameter]
public Guid Id { get; set; }
/// <summary>
/// Объект может быть отредактирован и записан
/// </summary>
[Parameter]
public bool Editable { get; set; } = true;
/// <summary>
/// Содержимое формы редактирования
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }
/// <summary>
/// Используется при получении сложной модели со связями
/// </summary>
[Parameter]
public Func<IQueryable<T>, IQueryable<T>>? ModelSelector { get; set; }
/// <summary>
/// Дополнительные действия перед проверкой модели
/// </summary>
[Parameter]
public EventCallback<T> BeforeValidation { get; set; }
/// <summary>
/// Дополнительные действия после проверки модели
/// </summary>
[Parameter]
public EventCallback<T> AfterValidation { get; set; }
/// <summary>
/// Дополнительные действия при сохранении модели, которая уже существует в БД
/// </summary>
[Parameter]
public EventCallback<T> OnUpdate { get; set; }
/// <summary>
/// Дополнительные действия после сохранения модели
/// </summary>
[Parameter]
public EventCallback<T> AfterSave { get; set; }
/// <summary>
/// Дополнительные действия при инициализации
/// </summary>
[Parameter]
public EventCallback<(T Model, AppDbContext Context)> OnInitialize { get; set; }
/// <summary>
/// Дополнительные действия при инициализации
/// </summary>
[Parameter]
public Func<object, string, Task<IEnumerable<string>>>? Validation { get; set; }
[CascadingParameter(Name = "NavMenu")] public NavMenu NavMenu { get; set; }
protected override async Task OnInitializedAsync()
{
try
{
Context = await ContextFactory.CreateDbContextAsync();
Model = await GetSingleObject();
await OnInitialize.InvokeAsync((Model!, Context));
}
catch (Exception e)
{
SnackBar.ShowError(e);
}
}
private async Task Save()
{
await BeforeValidation.InvokeAsync(Model);
await Form.Validate();
if (!Form.IsValid)
{
SnackBar.ShowError("Объект не записан");
return;
}
await AfterValidation.InvokeAsync(Model);
try
{
var model = await GetSingleObject(false);
if (model != null)
{
Context!.Entry(model).CurrentValues.SetValues(Model!);
await OnUpdate.InvokeAsync(model);
}
else
Context!.Entry(Model!).State = EntityState.Added;
await Context!.SaveChangesAsync();
await AfterSave.InvokeAsync(model ?? Model!);
SnackBar.ShowSuccess("Объект записан", false);
await NavMenu.NotifyStateHasChanged();
}
catch (Exception e)
{
SnackBar.ShowError(e);
}
}
private async Task<T?> GetSingleObject(bool createNew = true)
{
var item = await (ModelSelector == null
? Context!.Set<T>()
: ModelSelector
.Invoke(Context!.Set<T>()))
.SingleOrDefaultAsync();
if (item != null)
return item;
if (!createNew)
return null;
item = new T();
Context.Set<T>().Add(item);
return item;
}
public void Dispose()
{
Context?.Dispose();
}
}