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:
@@ -16,6 +16,7 @@ internal sealed class EmailChannelRepository : EfRepository<EmailChannelEntity>,
|
|||||||
public async Task<IReadOnlyList<EmailChannel>> GetAllAsync(CancellationToken ct = default)
|
public async Task<IReadOnlyList<EmailChannel>> GetAllAsync(CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var entities = await DbSet
|
var entities = await DbSet
|
||||||
|
.AsNoTracking()
|
||||||
.OrderBy(x => x.ServiceName)
|
.OrderBy(x => x.ServiceName)
|
||||||
.ThenBy(x => x.Priority)
|
.ThenBy(x => x.Priority)
|
||||||
.ToListAsync(ct);
|
.ToListAsync(ct);
|
||||||
@@ -26,6 +27,7 @@ internal sealed class EmailChannelRepository : EfRepository<EmailChannelEntity>,
|
|||||||
public async Task<IReadOnlyList<EmailChannel>> GetByServiceAsync(string serviceName, CancellationToken ct = default)
|
public async Task<IReadOnlyList<EmailChannel>> GetByServiceAsync(string serviceName, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var entities = await DbSet
|
var entities = await DbSet
|
||||||
|
.AsNoTracking()
|
||||||
.Where(x => x.ServiceName == serviceName)
|
.Where(x => x.ServiceName == serviceName)
|
||||||
.OrderBy(x => x.Priority)
|
.OrderBy(x => x.Priority)
|
||||||
.ToListAsync(ct);
|
.ToListAsync(ct);
|
||||||
@@ -35,7 +37,7 @@ internal sealed class EmailChannelRepository : EfRepository<EmailChannelEntity>,
|
|||||||
|
|
||||||
public async Task<EmailChannel?> GetByIdAsync(Guid id, CancellationToken ct = default)
|
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);
|
return entity is null ? null : MapToDomain(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@
|
|||||||
</button>
|
</button>
|
||||||
@if (!Model.IsNew)
|
@if (!Model.IsNew)
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#testModal">
|
<button type="button" class="btn btn-success" onclick="new bootstrap.Modal(document.getElementById('testModal')).show()">
|
||||||
<i class="bi bi-send me-1"></i> Test
|
<i class="bi bi-send me-1"></i> Test
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
@@ -135,6 +135,7 @@
|
|||||||
|
|
||||||
@if (!Model.IsNew)
|
@if (!Model.IsNew)
|
||||||
{
|
{
|
||||||
|
@section Scripts {
|
||||||
<div class="modal fade" id="testModal" tabindex="-1">
|
<div class="modal fade" id="testModal" tabindex="-1">
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@@ -194,3 +195,4 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,3 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@section Scripts {
|
||||||
|
@RenderSection("Scripts", required: false)
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,5 +51,6 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
|
||||||
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc4s9bIOgUxi8T/jzmGBE+rYG8O9HP+CyEb1BQGE8B8Z"
|
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc4s9bIOgUxi8T/jzmGBE+rYG8O9HP+CyEb1BQGE8B8Z"
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
|
@RenderSection("Scripts", required: false)
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user