Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4fd2c7ce7d | ||
|
|
2ff7345a73 | ||
|
|
1de04d4908 |
@@ -241,6 +241,11 @@
|
|||||||
trigger.focus();
|
trigger.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Announce the close so whoever opened the modal can undo optimistic UI or
|
||||||
|
// clean up a dynamically-inserted overlay. A modal can be dismissed four
|
||||||
|
// ways — the ✕ button, a Cancel button, a backdrop click, and Escape — and
|
||||||
|
// the last two are handled globally here, so button-only listeners miss them.
|
||||||
|
el.dispatchEvent(new CustomEvent('lt:modalclose', { bubbles: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeAllModals() {
|
function closeAllModals() {
|
||||||
@@ -2774,6 +2779,9 @@
|
|||||||
setTimeout(() => { if (modalEl && modalEl.parentNode) modalEl.remove(); }, 300);
|
setTimeout(() => { if (modalEl && modalEl.parentNode) modalEl.remove(); }, 300);
|
||||||
resolve(value);
|
resolve(value);
|
||||||
};
|
};
|
||||||
|
// Any dismissal counts as "no comment given", including a backdrop click or
|
||||||
|
// Escape, which close the overlay through the global handlers above.
|
||||||
|
modalEl.addEventListener('lt:modalclose', () => finish(null));
|
||||||
modalEl.querySelector('[data-modal-close]').addEventListener('click', () => finish(null));
|
modalEl.querySelector('[data-modal-close]').addEventListener('click', () => finish(null));
|
||||||
document.getElementById(modalId + '_cancel').addEventListener('click', () => finish(null));
|
document.getElementById(modalId + '_cancel').addEventListener('click', () => finish(null));
|
||||||
document.getElementById(modalId + '_confirm').addEventListener('click', () => {
|
document.getElementById(modalId + '_confirm').addEventListener('click', () => {
|
||||||
|
|||||||
+23
-7
@@ -550,7 +550,7 @@ function bulkClose() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
lt.modal.open('bulkCloseModal');
|
openModalWithDismiss('bulkCloseModal', closeBulkCloseModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeBulkCloseModal() {
|
function closeBulkCloseModal() {
|
||||||
@@ -633,7 +633,7 @@ function showBulkAssignModal() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
lt.modal.open('bulkAssignModal');
|
openModalWithDismiss('bulkAssignModal', closeBulkAssignModal);
|
||||||
setTimeout(() => { const inp = document.getElementById('bulkAssignUserInput'); if (inp) inp.focus(); }, 120);
|
setTimeout(() => { const inp = document.getElementById('bulkAssignUserInput'); if (inp) inp.focus(); }, 120);
|
||||||
|
|
||||||
lt.api.get('/api/get_users.php')
|
lt.api.get('/api/get_users.php')
|
||||||
@@ -731,7 +731,7 @@ function showBulkPriorityModal() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
lt.modal.open('bulkPriorityModal');
|
openModalWithDismiss('bulkPriorityModal', closeBulkPriorityModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeBulkPriorityModal() {
|
function closeBulkPriorityModal() {
|
||||||
@@ -845,7 +845,7 @@ function showBulkStatusModal() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
lt.modal.open('bulkStatusModal');
|
openModalWithDismiss('bulkStatusModal', closeBulkStatusModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeBulkStatusModal() {
|
function closeBulkStatusModal() {
|
||||||
@@ -942,7 +942,7 @@ function showBulkDeleteModal() {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
lt.modal.open('bulkDeleteModal');
|
openModalWithDismiss('bulkDeleteModal', closeBulkDeleteModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeBulkDeleteModal() {
|
function closeBulkDeleteModal() {
|
||||||
@@ -1032,6 +1032,22 @@ function showInputModal(title, label, placeholder = '', onSubmit, onCancel = nul
|
|||||||
input.addEventListener('keypress', (e) => { if (e.key === 'Enter') handleSubmit(); });
|
input.addEventListener('keypress', (e) => { if (e.key === 'Enter') handleSubmit(); });
|
||||||
document.getElementById(`${modalId}_cancel`).addEventListener('click', () => cleanup(onCancel));
|
document.getElementById(`${modalId}_cancel`).addEventListener('click', () => cleanup(onCancel));
|
||||||
modal.querySelector('[data-modal-close]').addEventListener('click', () => cleanup(onCancel));
|
modal.querySelector('[data-modal-close]').addEventListener('click', () => cleanup(onCancel));
|
||||||
|
// Backdrop click / Escape close the overlay via base.js's global handlers.
|
||||||
|
modal.addEventListener('lt:modalclose', () => cleanup(onCancel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a dynamically-inserted modal and make sure it tears itself down however it
|
||||||
|
* is dismissed. base.js handles backdrop clicks and Escape globally, so wiring
|
||||||
|
* only the ✕/Cancel buttons leaves the overlay in the DOM — and the next open
|
||||||
|
* inserts a second element with the same id, which then shadows the live one.
|
||||||
|
*/
|
||||||
|
function openModalWithDismiss(modalId, onDismiss) {
|
||||||
|
lt.modal.open(modalId);
|
||||||
|
const el = document.getElementById(modalId);
|
||||||
|
// lt.modal.close() early-returns once .is-open is gone, so the close call
|
||||||
|
// inside onDismiss cannot re-enter this listener.
|
||||||
|
if (el) el.addEventListener('lt:modalclose', onDismiss);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
@@ -1069,7 +1085,7 @@ function quickStatusChange(ticketId, currentStatus) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
lt.modal.open('quickStatusModal');
|
openModalWithDismiss('quickStatusModal', closeQuickStatusModal);
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeQuickStatusModal() {
|
function closeQuickStatusModal() {
|
||||||
@@ -1136,7 +1152,7 @@ function quickAssign(ticketId) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
||||||
lt.modal.open('quickAssignModal');
|
openModalWithDismiss('quickAssignModal', closeQuickAssignModal);
|
||||||
|
|
||||||
lt.api.get('/api/get_users.php')
|
lt.api.get('/api/get_users.php')
|
||||||
.then(data => {
|
.then(data => {
|
||||||
|
|||||||
+22
-2
@@ -284,7 +284,15 @@ function addComment() {
|
|||||||
// Clear the comment box
|
// Clear the comment box
|
||||||
const nc = document.getElementById('newComment');
|
const nc = document.getElementById('newComment');
|
||||||
if (nc) nc.value = '';
|
if (nc) nc.value = '';
|
||||||
|
|
||||||
|
// Clear the live preview — clearing the textarea programmatically
|
||||||
|
// does not fire 'input', so updatePreview() never runs
|
||||||
|
const previewDiv = document.getElementById('markdownPreview');
|
||||||
|
if (previewDiv) {
|
||||||
|
previewDiv.innerHTML = '';
|
||||||
|
previewDiv.classList.add('is-hidden');
|
||||||
|
}
|
||||||
|
|
||||||
// Format the comment text for display
|
// Format the comment text for display
|
||||||
let displayText;
|
let displayText;
|
||||||
if (isMarkdownEnabled) {
|
if (isMarkdownEnabled) {
|
||||||
@@ -521,7 +529,19 @@ function updateTicketStatus() {
|
|||||||
`);
|
`);
|
||||||
const modal = document.getElementById(modalId);
|
const modal = document.getElementById(modalId);
|
||||||
lt.modal.open(modalId);
|
lt.modal.open(modalId);
|
||||||
const cleanup = (ok) => { lt.modal.close(modalId); setTimeout(() => modal.remove(), 300); if (!ok) statusSelect.selectedIndex = 0; };
|
let settled = false;
|
||||||
|
const cleanup = (ok) => {
|
||||||
|
if (settled) return; // lt.modal.close() below re-enters via lt:modalclose
|
||||||
|
settled = true;
|
||||||
|
lt.modal.close(modalId);
|
||||||
|
setTimeout(() => modal.remove(), 300);
|
||||||
|
if (!ok) statusSelect.selectedIndex = 0;
|
||||||
|
};
|
||||||
|
// Backdrop click and Escape close the overlay through base.js's global
|
||||||
|
// handlers. Without this the dropdown kept displaying the new status
|
||||||
|
// while the server was never called, so the ticket looked closed until
|
||||||
|
// a reload revealed it was still open.
|
||||||
|
modal.addEventListener('lt:modalclose', () => cleanup(false));
|
||||||
modal.querySelector('[data-modal-close]').addEventListener('click', () => cleanup(false));
|
modal.querySelector('[data-modal-close]').addEventListener('click', () => cleanup(false));
|
||||||
document.getElementById(`${modalId}_cancel`).addEventListener('click', () => cleanup(false));
|
document.getElementById(`${modalId}_cancel`).addEventListener('click', () => cleanup(false));
|
||||||
document.getElementById(`${modalId}_confirm`).addEventListener('click', () => {
|
document.getElementById(`${modalId}_confirm`).addEventListener('click', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user