fix: replace native dialog element with div-based modal to fix stuck dialogs

This commit is contained in:
SW 2026-10-01 14:28:17 +02:00
parent b4a89dd13e
commit d59de720c5
3 changed files with 38 additions and 33 deletions

View file

@ -108,19 +108,19 @@
</section> </section>
{% endif %} {% endif %}
<dialog id="release-modal" class="modal-overlay" style="display:none;"> <div id="release-modal" class="modal-overlay" style="display:none;" onclick="if (event.target === this) this.style.display='none';">
<div class="modal"> <div class="modal" onclick="event.stopPropagation();">
<h2 class="modal-title">Release subnet {{ allocation.cidr }}</h2> <h2 class="modal-title">Release subnet {{ allocation.cidr }}</h2>
<form method="post" action="/allocations/{{ allocation.id }}/release" class="modal-body" id="release-form"> <form method="post" action="/allocations/{{ allocation.id }}/release" class="modal-body" id="release-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}"> <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<p class="small">The subnet will be marked as <span class="status released">released</span> and its address space will become available again via the first-fit algorithm. The record remains in history.</p> <p class="small">The subnet will be marked as <span class="status released">released</span> and its address space will become available again via the first-fit algorithm. The record remains in history.</p>
<label for="release-note">Release note *</label> <label for="release-note">Release note *</label>
<textarea id="release-note" name="release_note" rows="3" required minlength="3" maxlength="500"></textarea> <textarea id="release-note" name="release_note" rows="3" required minlength="3" maxlength="500"></textarea>
</form>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" onclick="document.getElementById('release-modal').style.display='none'">Cancel</button> <button type="button" class="btn btn-secondary" onclick="document.getElementById('release-modal').style.display='none'">Cancel</button>
<button type="submit" class="btn btn-danger" form="release-form">Release</button> <button type="submit" class="btn btn-danger">Release</button>
</div>
</form>
</div> </div>
</div> </div>
</dialog>
{% endblock %} {% endblock %}

View file

@ -38,21 +38,21 @@
{% for a in allocations %} {% for a in allocations %}
{% if a.status == "active" || a.status == "reserved" %} {% if a.status == "active" || a.status == "reserved" %}
<dialog id="release-modal-{{ a.id }}" class="modal-overlay" style="display:none;"> <div id="release-modal-{{ a.id }}" class="modal-overlay" style="display:none;" onclick="if (event.target === this) this.style.display='none';">
<div class="modal"> <div class="modal" onclick="event.stopPropagation();">
<h2 class="modal-title">Release subnet {{ a.cidr }}</h2> <h2 class="modal-title">Release subnet {{ a.cidr }}</h2>
<form method="post" action="/allocations/{{ a.id }}/release" class="modal-body" id="release-form-{{ a.id }}"> <form method="post" action="/allocations/{{ a.id }}/release" class="modal-body" id="release-form-{{ a.id }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}"> <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<p class="small">The subnet will be marked as <span class="status released">released</span> and its address space will become available again. The record remains in history.</p> <p class="small">The subnet will be marked as <span class="status released">released</span> and its address space will become available again. The record remains in history.</p>
<label for="release-note-{{ a.id }}">Release note *</label> <label for="release-note-{{ a.id }}">Release note *</label>
<textarea id="release-note-{{ a.id }}" name="release_note" rows="3" required minlength="3" maxlength="500"></textarea> <textarea id="release-note-{{ a.id }}" name="release_note" rows="3" required minlength="3" maxlength="500"></textarea>
</form>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" onclick="document.getElementById('release-modal-{{ a.id }}').style.display='none'">Cancel</button> <button type="button" class="btn btn-secondary" onclick="document.getElementById('release-modal-{{ a.id }}').style.display='none'">Cancel</button>
<button type="submit" class="btn btn-danger" form="release-form-{{ a.id }}">Release</button> <button type="submit" class="btn btn-danger">Release</button>
</div>
</form>
</div> </div>
</div> </div>
</dialog>
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View file

@ -85,8 +85,8 @@
</div> </div>
</section> </section>
<dialog id="allocate-modal" class="modal-overlay" style="display:none;"> <div id="allocate-modal" class="modal-overlay" style="display:none;" onclick="if (event.target === this) closeAllocateModal();">
<div class="modal"> <div class="modal" onclick="event.stopPropagation();">
<h2 class="modal-title">Confirm subnet allocation</h2> <h2 class="modal-title">Confirm subnet allocation</h2>
<form method="post" action="/allocations" class="modal-body" id="allocate-form"> <form method="post" action="/allocations" class="modal-body" id="allocate-form">
<input type="hidden" name="pool_slug" id="modal-pool-slug"> <input type="hidden" name="pool_slug" id="modal-pool-slug">
@ -123,13 +123,14 @@
<label for="ticket">Ticket / reference</label> <label for="ticket">Ticket / reference</label>
<input type="text" id="ticket" name="ticket" maxlength="100"> <input type="text" id="ticket" name="ticket" maxlength="100">
</form>
<div class="modal-actions"> <div class="modal-actions">
<button type="button" class="btn btn-secondary" onclick="closeAllocateModal()">Cancel</button> <button type="button" class="btn btn-secondary" onclick="closeAllocateModal()">Cancel</button>
<button type="submit" class="btn" form="allocate-form">Confirm allocation</button> <button type="submit" class="btn">Confirm allocation</button>
</div>
</form>
</div> </div>
</div> </div>
</dialog>
<script> <script>
const poolData = { const poolData = {
@ -155,6 +156,7 @@
document.getElementById('modal-pool-name').textContent = poolData[slug].name; document.getElementById('modal-pool-name').textContent = poolData[slug].name;
document.getElementById('modal-prefix-display').textContent = '/' + prefixLength; document.getElementById('modal-prefix-display').textContent = '/' + prefixLength;
try {
const resp = await fetch('/partials/pools/' + slug + '/preview?prefix_length=' + prefixLength); const resp = await fetch('/partials/pools/' + slug + '/preview?prefix_length=' + prefixLength);
const html = await resp.text(); const html = await resp.text();
const parser = new DOMParser(); const parser = new DOMParser();
@ -169,6 +171,9 @@
document.getElementById('modal-address-count').textContent = addressCount; document.getElementById('modal-address-count').textContent = addressCount;
document.getElementById('modal-usable-hosts').textContent = usableHosts; document.getElementById('modal-usable-hosts').textContent = usableHosts;
document.getElementById('modal-warning').textContent = warning; document.getElementById('modal-warning').textContent = warning;
} catch (e) {
document.getElementById('modal-warning').textContent = 'Could not load preview.';
}
modal.style.display = 'flex'; modal.style.display = 'flex';
} }