fix batch
This commit is contained in:
@@ -373,8 +373,94 @@
|
|||||||
let tempBatchCounter = -1;
|
let tempBatchCounter = -1;
|
||||||
|
|
||||||
let csrfValue = cfg.csrfHash || '';
|
let csrfValue = cfg.csrfHash || '';
|
||||||
|
const csrfCookieName = <?= json_encode(config('Security')->csrfCookieName ?? (config('Security')->cookieName ?? 'csrf_cookie_name')) ?>;
|
||||||
|
let csrfRequestQueue = Promise.resolve();
|
||||||
let dragPayload = null;
|
let dragPayload = null;
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
const parts = document.cookie.split(';');
|
||||||
|
for (let i = 0; i < parts.length; i += 1) {
|
||||||
|
const part = parts[i].trim();
|
||||||
|
if (part.startsWith(`${name}=`)) {
|
||||||
|
return decodeURIComponent(part.slice(name.length + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncCsrfFromCookie() {
|
||||||
|
if (!csrfCookieName) {
|
||||||
|
return csrfValue;
|
||||||
|
}
|
||||||
|
const cookieValue = getCookie(csrfCookieName);
|
||||||
|
if (cookieValue) {
|
||||||
|
csrfValue = cookieValue;
|
||||||
|
}
|
||||||
|
return csrfValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCsrfToken(response, data = null) {
|
||||||
|
const headerValue = response?.headers?.get?.('X-CSRF-HASH') || '';
|
||||||
|
if (headerValue) {
|
||||||
|
csrfValue = headerValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bodyValue = data && typeof data === 'object' ? (data.csrf_hash || data.csrfHash || '') : '';
|
||||||
|
if (bodyValue) {
|
||||||
|
csrfValue = bodyValue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
syncCsrfFromCookie();
|
||||||
|
}
|
||||||
|
|
||||||
|
function withSerializedCsrfRequest(task) {
|
||||||
|
const run = csrfRequestQueue
|
||||||
|
.catch(() => undefined)
|
||||||
|
.then(() => task());
|
||||||
|
csrfRequestQueue = run.then(() => undefined, () => undefined);
|
||||||
|
return run;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function postJson(url, form, fallbackError) {
|
||||||
|
return withSerializedCsrfRequest(async () => {
|
||||||
|
syncCsrfFromCookie();
|
||||||
|
if (cfg.csrfToken) {
|
||||||
|
form.set(cfg.csrfToken, csrfValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = { 'X-Requested-With': 'XMLHttpRequest' };
|
||||||
|
if (csrfValue) {
|
||||||
|
headers['X-CSRF-TOKEN'] = csrfValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: form,
|
||||||
|
});
|
||||||
|
|
||||||
|
const text = await response.text();
|
||||||
|
let data = null;
|
||||||
|
try {
|
||||||
|
data = text ? JSON.parse(text) : {};
|
||||||
|
} catch (_) {
|
||||||
|
data = {
|
||||||
|
success: false,
|
||||||
|
error: text || fallbackError || 'Unexpected response',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCsrfToken(response, data);
|
||||||
|
|
||||||
|
if (!response.ok || !data.success) {
|
||||||
|
throw new Error(data.error || fallbackError || 'Request failed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function openReceiptModal(url) {
|
function openReceiptModal(url) {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return;
|
return;
|
||||||
@@ -470,23 +556,8 @@
|
|||||||
}
|
}
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
form.append('expense_id', itemId);
|
form.append('expense_id', itemId);
|
||||||
if (cfg.csrfToken) {
|
|
||||||
form.append(cfg.csrfToken, csrfValue);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(cfg.markDonationUrl, {
|
await postJson(cfg.markDonationUrl, form, 'Unable to mark donation right now.');
|
||||||
method: 'POST',
|
|
||||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
|
||||||
body: form,
|
|
||||||
});
|
|
||||||
const data = await response.json().catch(() => ({ success: false, error: 'Unexpected response' }));
|
|
||||||
const newHash = response.headers.get('X-CSRF-HASH') || data.csrf_hash;
|
|
||||||
if (newHash) {
|
|
||||||
csrfValue = newHash;
|
|
||||||
}
|
|
||||||
if (!response.ok || !data.success) {
|
|
||||||
throw new Error(data.error || 'Unable to mark donation right now.');
|
|
||||||
}
|
|
||||||
removeItemFromUI(itemId);
|
removeItemFromUI(itemId);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -737,23 +808,7 @@
|
|||||||
} else {
|
} else {
|
||||||
form.append('admin_id', '');
|
form.append('admin_id', '');
|
||||||
}
|
}
|
||||||
if (cfg.csrfToken) {
|
postJson(cfg.updateUrl, form, 'Unable to update batch assignment.').then((data) => {
|
||||||
form.append(cfg.csrfToken, csrfValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch(cfg.updateUrl, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
|
||||||
body: form,
|
|
||||||
}).then(async (response) => {
|
|
||||||
const data = await response.json().catch(() => ({ success: false, error: 'Unexpected response' }));
|
|
||||||
const newHash = response.headers.get('X-CSRF-HASH') || data.csrf_hash;
|
|
||||||
if (newHash) {
|
|
||||||
csrfValue = newHash;
|
|
||||||
}
|
|
||||||
if (!response.ok || !data.success) {
|
|
||||||
throw new Error(data.error || 'Unable to update batch assignment.');
|
|
||||||
}
|
|
||||||
entry.batch_number = batchId;
|
entry.batch_number = batchId;
|
||||||
entry.batchId = batchId;
|
entry.batchId = batchId;
|
||||||
entry.admin_id = (adminId || adminId === 0) ? adminId : null;
|
entry.admin_id = (adminId || adminId === 0) ? adminId : null;
|
||||||
@@ -791,25 +846,7 @@
|
|||||||
throw new Error('Batch creation endpoint is not configured.');
|
throw new Error('Batch creation endpoint is not configured.');
|
||||||
}
|
}
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
if (cfg.csrfToken) {
|
return postJson(cfg.createBatchUrl, form, 'Unable to create a new batch right now.');
|
||||||
form.append(cfg.csrfToken, csrfValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(cfg.createBatchUrl, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
|
||||||
body: form,
|
|
||||||
});
|
|
||||||
const data = await response.json().catch(() => ({ success: false, error: 'Unexpected response when creating batch.' }));
|
|
||||||
const newHash = response.headers.get('X-CSRF-HASH') || data.csrf_hash;
|
|
||||||
if (newHash) {
|
|
||||||
csrfValue = newHash;
|
|
||||||
}
|
|
||||||
if (!response.ok || !data.success) {
|
|
||||||
throw new Error(data.error || 'Unable to create a new batch right now.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadAdminCheckFile(batchId, adminId, input, statusEl, linkEl) {
|
async function uploadAdminCheckFile(batchId, adminId, input, statusEl, linkEl) {
|
||||||
@@ -827,28 +864,13 @@
|
|||||||
form.append('batch_id', batchId);
|
form.append('batch_id', batchId);
|
||||||
form.append('admin_id', adminId ?? 0);
|
form.append('admin_id', adminId ?? 0);
|
||||||
form.append('check_file', file);
|
form.append('check_file', file);
|
||||||
if (cfg.csrfToken) {
|
|
||||||
form.append(cfg.csrfToken, csrfValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
input.disabled = true;
|
input.disabled = true;
|
||||||
const previous = statusEl.textContent;
|
const previous = statusEl.textContent;
|
||||||
statusEl.textContent = 'Uploading...';
|
statusEl.textContent = 'Uploading...';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(cfg.checkUploadUrl, {
|
const data = await postJson(cfg.checkUploadUrl, form, 'Unable to upload check file right now.');
|
||||||
method: 'POST',
|
|
||||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
|
||||||
body: form,
|
|
||||||
});
|
|
||||||
const data = await response.json().catch(() => ({ success: false, error: 'Unexpected response' }));
|
|
||||||
const newHash = response.headers.get('X-CSRF-HASH') || data.csrf_hash;
|
|
||||||
if (newHash) {
|
|
||||||
csrfValue = newHash;
|
|
||||||
}
|
|
||||||
if (!response.ok || !data.success) {
|
|
||||||
throw new Error(data.error || 'Unable to upload check file right now.');
|
|
||||||
}
|
|
||||||
const label = data.original_filename || 'View check';
|
const label = data.original_filename || 'View check';
|
||||||
statusEl.textContent = `Uploaded: ${data.original_filename || 'file'}`;
|
statusEl.textContent = `Uploaded: ${data.original_filename || 'file'}`;
|
||||||
if (linkEl && data.url) {
|
if (linkEl && data.url) {
|
||||||
@@ -979,34 +1001,19 @@
|
|||||||
}
|
}
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
form.append('batch_id', batchId);
|
form.append('batch_id', batchId);
|
||||||
if (cfg.csrfToken) {
|
|
||||||
form.append(cfg.csrfToken, csrfValue);
|
|
||||||
}
|
|
||||||
if (button) {
|
if (button) {
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
button.textContent = 'Locking...';
|
button.textContent = 'Locking...';
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(cfg.lockBatchUrl, {
|
await postJson(cfg.lockBatchUrl, form, 'Unable to lock batch at the moment.');
|
||||||
method: 'POST',
|
|
||||||
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
|
||||||
body: form,
|
|
||||||
});
|
|
||||||
const data = await response.json().catch(() => ({ success: false, error: 'Unexpected response' }));
|
|
||||||
const newHash = response.headers.get('X-CSRF-HASH') || data.csrf_hash;
|
|
||||||
if (newHash) {
|
|
||||||
csrfValue = newHash;
|
|
||||||
}
|
|
||||||
if (!response.ok || !data.success) {
|
|
||||||
throw new Error(data.error || 'Unable to lock batch at the moment.');
|
|
||||||
}
|
|
||||||
markBatchCardLocked(card);
|
markBatchCardLocked(card);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
alert(err.message || 'Unable to lock the batch. Please try again.');
|
alert(err.message || 'Unable to lock the batch. Please try again.');
|
||||||
if (button) {
|
if (button) {
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
button.textContent = 'Lock Batch';
|
button.textContent = 'Submit Batch';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user