fix: channel save tracking conflict and test modal rendering

- Use AsNoTracking() on all EmailChannelRepository read methods to prevent
  EF identity conflict when Update() attaches a new entity with same key
- Move test modal to @section Scripts rendered at end of <body> so
  bootstrap.Modal is available and modal is not nested inside card DOM
- Add @RenderSection('Scripts') forwarding in _EditorLayout to bubble
  child scripts sections up to _Layout
- Switch Test button to programmatic bootstrap.Modal() open instead of
  data-bs-toggle (more reliable across layout section boundaries)

Ref: IT-628

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Anatolii Grynchuk
2026-05-02 03:29:54 +03:00
parent b5214973ce
commit 215285d3c0
4 changed files with 63 additions and 54 deletions
@@ -16,6 +16,7 @@ internal sealed class EmailChannelRepository : EfRepository<EmailChannelEntity>,
public async Task<IReadOnlyList<EmailChannel>> GetAllAsync(CancellationToken ct = default)
{
var entities = await DbSet
.AsNoTracking()
.OrderBy(x => x.ServiceName)
.ThenBy(x => x.Priority)
.ToListAsync(ct);
@@ -26,6 +27,7 @@ internal sealed class EmailChannelRepository : EfRepository<EmailChannelEntity>,
public async Task<IReadOnlyList<EmailChannel>> GetByServiceAsync(string serviceName, CancellationToken ct = default)
{
var entities = await DbSet
.AsNoTracking()
.Where(x => x.ServiceName == serviceName)
.OrderBy(x => x.Priority)
.ToListAsync(ct);
@@ -35,7 +37,7 @@ internal sealed class EmailChannelRepository : EfRepository<EmailChannelEntity>,
public async Task<EmailChannel?> GetByIdAsync(Guid id, CancellationToken ct = default)
{
EmailChannelEntity? entity = await DbSet.FindAsync([id], ct);
EmailChannelEntity? entity = await DbSet.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, ct);
return entity is null ? null : MapToDomain(entity);
}