diff --git a/assets/ac_qr_logo.png b/assets/ac_qr_logo.png index d95f9cb..c8c2e3a 100644 Binary files a/assets/ac_qr_logo.png and b/assets/ac_qr_logo.png differ diff --git a/assets/js/app.js b/assets/js/app.js index 9ce9c3e..cc7b557 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1812,19 +1812,33 @@ } if (fileForm) { + const maxAttachmentBytes = 16 * 1024 * 1024; fileForm.addEventListener('submit', function (e) { e.preventDefault(); const fd = new FormData(fileForm); fd.append('ticket_id', id); + const fileInput = fileForm.querySelector('input[type="file"]'); + const picked = fileInput && fileInput.files && fileInput.files[0]; + if (picked && picked.size > maxAttachmentBytes) { + if (fileStatus) fileStatus.textContent = 'File too large (max 16 MiB)'; + return; + } if (fileStatus) fileStatus.textContent = 'Uploading…'; const xhr = new XMLHttpRequest(); xhr.open('POST', basePath() + '/api/ticket_attachments.php', true); xhr.onload = function () { + if (xhr.status === 413) { + if (fileStatus) fileStatus.textContent = 'File too large (max 16 MiB)'; + return; + } let data; try { data = JSON.parse(xhr.responseText); } catch { - if (fileStatus) fileStatus.textContent = 'Invalid response'; + if (fileStatus) { + fileStatus.textContent = + xhr.status >= 400 ? 'Upload failed (HTTP ' + xhr.status + ')' : 'Invalid response'; + } return; } if (!data.ok) { @@ -1838,7 +1852,12 @@ if (fileStatus) fileStatus.textContent = 'Uploaded'; }; xhr.onerror = function () { - if (fileStatus) fileStatus.textContent = t('reports.network_error'); + if (fileStatus) { + fileStatus.textContent = + picked && picked.size > 1024 * 1024 + ? 'Upload failed — file may exceed server limit (max 16 MiB)' + : t('reports.network_error'); + } }; xhr.send(fd); });