fix: move test modal to view body, wire button via addEventListener

Razor section forwarding across nested layouts is unreliable.
Modal div and script are now directly in Edit.cshtml body (not in
any section) so they are always in the DOM when the page renders.
Button uses addEventListener instead of inline onclick to decouple
from layout rendering order.

Ref: IT-628

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Anatolii Grynchuk
2026-05-02 03:43:25 +03:00
parent c9f776de80
commit 7587e7fd17
2 changed files with 56 additions and 58 deletions
@@ -123,7 +123,7 @@
</button>
@if (!Model.IsNew)
{
<button type="button" class="btn btn-success" onclick="new bootstrap.Modal(document.getElementById('testModal')).show()">
<button type="button" class="btn btn-success" id="testModalBtn">
<i class="bi bi-send me-1"></i> Test
</button>
}
@@ -135,64 +135,66 @@
@if (!Model.IsNew)
{
@section Scripts {
<div class="modal fade" id="testModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="bi bi-send me-2"></i>Send Test Email</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<label for="testToEmail" class="form-label fw-semibold">Recipient Email</label>
<input type="email" id="testToEmail" class="form-control" placeholder="you@example.com" />
<div id="testResult" class="mt-3" style="display:none"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-success" id="testSendBtn" onclick="sendTestEmail('@Model.Id')">
<i class="bi bi-send me-1"></i> Send
</button>
</div>
<div class="modal fade" id="testModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="bi bi-send me-2"></i>Send Test Email</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<label for="testToEmail" class="form-label fw-semibold">Recipient Email</label>
<input type="email" id="testToEmail" class="form-control" placeholder="you@example.com" />
<div id="testResult" class="mt-3" style="display:none"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-success" id="testSendBtn" onclick="sendTestEmail('@Model.Id')">
<i class="bi bi-send me-1"></i> Send
</button>
</div>
</div>
</div>
</div>
<script>
async function sendTestEmail(channelId) {
const toEmail = document.getElementById('testToEmail').value.trim();
const resultDiv = document.getElementById('testResult');
const sendBtn = document.getElementById('testSendBtn');
<script>
document.getElementById('testModalBtn').addEventListener('click', function () {
bootstrap.Modal.getOrCreateInstance(document.getElementById('testModal')).show();
});
if (!toEmail) {
resultDiv.style.display = 'block';
resultDiv.innerHTML = '<div class="alert alert-warning mb-0">Please enter a recipient email.</div>';
return;
}
async function sendTestEmail(channelId) {
const toEmail = document.getElementById('testToEmail').value.trim();
const resultDiv = document.getElementById('testResult');
const sendBtn = document.getElementById('testSendBtn');
sendBtn.disabled = true;
sendBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span> Sending…';
resultDiv.style.display = 'none';
try {
const resp = await fetch(`/admin/channels/${channelId}/test`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ toEmail })
});
const data = await resp.json();
resultDiv.style.display = 'block';
resultDiv.innerHTML = data.success
? `<div class="alert alert-success mb-0"><i class="bi bi-check-circle me-1"></i>${data.message}</div>`
: `<div class="alert alert-danger mb-0"><i class="bi bi-x-circle me-1"></i>${data.message}</div>`;
} catch (e) {
resultDiv.style.display = 'block';
resultDiv.innerHTML = `<div class="alert alert-danger mb-0">Request failed: ${e.message}</div>`;
} finally {
sendBtn.disabled = false;
sendBtn.innerHTML = '<i class="bi bi-send me-1"></i> Send';
}
if (!toEmail) {
resultDiv.style.display = 'block';
resultDiv.innerHTML = '<div class="alert alert-warning mb-0">Please enter a recipient email.</div>';
return;
}
</script>
}
sendBtn.disabled = true;
sendBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span> Sending…';
resultDiv.style.display = 'none';
try {
const resp = await fetch(`/admin/channels/${channelId}/test`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ toEmail })
});
const data = await resp.json();
resultDiv.style.display = 'block';
resultDiv.innerHTML = data.success
? `<div class="alert alert-success mb-0"><i class="bi bi-check-circle me-1"></i>${data.message}</div>`
: `<div class="alert alert-danger mb-0"><i class="bi bi-x-circle me-1"></i>${data.message}</div>`;
} catch (e) {
resultDiv.style.display = 'block';
resultDiv.innerHTML = `<div class="alert alert-danger mb-0">Request failed: ${e.message}</div>`;
} finally {
sendBtn.disabled = false;
sendBtn.innerHTML = '<i class="bi bi-send me-1"></i> Send';
}
}
</script>
}