From b38f03c0e7218762d90fa5092696b127f24f36db Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 25 Jan 2026 07:07:26 +0000
Subject: [PATCH] =Some logical flaws in Queue.php, Queue.js, ContentExecutor.php, UploadExecutor.php - particularly with timeline ordering, frontend queue updates, etc

---
 assets/js/concise/UploadManager.js |   46 ++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/assets/js/concise/UploadManager.js b/assets/js/concise/UploadManager.js
index e5f8643..0d57012 100644
--- a/assets/js/concise/UploadManager.js
+++ b/assets/js/concise/UploadManager.js
@@ -10,6 +10,7 @@
 		this.initStores();
 		this.initWorker();
 
+
 		//Maps for DOM references
 		this.fields = new Map();
 		this.uploads = new Map();
@@ -138,7 +139,8 @@
 
 				if (manyRefs.inputs) {
 					for (let input of manyRefs.inputs) {
-						window.prefixInput(input, `${data.id??data.uploadId}-`);
+						let wrapper = input.closest('[data-field]')??el;
+						window.prefixInput(input, `${data.id??data.uploadId}-`, wrapper);
 					}
 				}
 			}
@@ -154,7 +156,8 @@
 			setup({el, refs, manyRefs, data}) {
 				el.dataset.groupId = data.groupId;
 				if (refs.selectAll) {
-					window.prefixInput(refs.selectAll, `select-all-${data.groupId}`, true);
+					let wrapper = refs.selectAll.closest('.field');
+					window.prefixInput(refs.selectAll, `select-all-${data.groupId}`, wrapper,true);
 				}
 				let fields = T.create('groupMetadata', {groupId: data.groupId});
 				if (fields) {
@@ -175,7 +178,8 @@
 			setup({el, refs, manyRefs, data}) {
 				if (refs.inputs) {
 					refs.inputs.forEach(input => {
-						window.prefixInput(input, `${data.groupId}-`);
+						let wrapper = input.closest('[data-field]');
+						window.prefixInput(input, `${data.groupId}-`, wrapper);
 					});
 				}
 			}
@@ -535,6 +539,7 @@
 
 		// Capture values immediately (before debouncer)
 		const inputName = input.name;
+		if (!inputName) return;
 		const inputValue = input.value;
 
 		// Extract the field name from the input name
@@ -663,10 +668,15 @@
 			await this.setBulkUpload(uploads, 'status', 'uploading');
 			await this.setBulkGroup(fieldId, 'operationId', operationId);
 			this.fields.set(field.id, field);
+
+
+			this.notify('sent-to-queue', {
+				field: field,
+				operation: operationId,
+			});
 		} else {
 			await this.setBulkUpload(uploads, 'status', 'failed');
 		}
-		this.notify('sent-to-queue', fieldId);
 		return operationId;
 	}
 
@@ -707,7 +717,12 @@
 		let uploadMap = [];
 		let files = [];
 
-		for (const group of groups) {
+		const validGroups = groups.filter(group => {
+			const groupUploads = this.getGroupUploadsInOrder(group);
+			return groupUploads.length > 0 && groupUploads.some(u => this.formatFile(u));
+		});
+
+		for (const group of validGroups) {
 			const groupElement = this.groups.get(group.id)?.element;
 			const fields = this.collectGroupFieldsFromDOM(groupElement, group.id);
 
@@ -716,7 +731,6 @@
 				fields: fields
 			};
 
-			// Use helper to get uploads in stored order
 			const groupUploads = this.getGroupUploadsInOrder(group);
 
 			for (const upload of groupUploads) {
@@ -738,7 +752,10 @@
 					uploadMap.push(upload.id);
 				}
 			}
-			posts.push(post);
+
+			if (post.images.length > 0) {
+				posts.push(post);
+			}
 		}
 
 		// Handle remaining uploads not in any group
@@ -759,7 +776,10 @@
 				post.images.push(imageData);
 				uploadMap.push(upload.id);
 			}
-			posts.push(post);
+
+			if (post.images.length > 0) {
+				posts.push(post);
+			}
 		}
 
 		return {posts, uploadMap, files};
@@ -1167,6 +1187,13 @@
 	*************************************************************/
 	async checkRecovery() {
 		const pendingUploads = this.stores.uploads.filterByIndex({status: ['local_processing', 'queued', 'uploading']});
+		const allGroups = Array.from(this.stores.groups.data.values());
+		for (const group of allGroups) {
+			const hasUploads = this.stores.uploads.filterByIndex({group: group.id}).length > 0;
+			if (!hasUploads) {
+				await this.stores.groups.delete(group.id);
+			}
+		}
 		if (pendingUploads.length === 0) return;
 
 		// Group by source page
@@ -1746,6 +1773,7 @@
 			avoidImplicitDeselect: true,
 			group: { name: fieldId, pull: true, put: true },
 			dragClass: 'dragging',
+			ignore: '.empty-group',
 
 			onStart: (evt) => {
 				// Get the dragged item's ID
@@ -1777,6 +1805,7 @@
 
 		emptyZone.addEventListener('dragover', (e) => {
 			e.preventDefault();
+			e.stopPropagation();
 			e.dataTransfer.dropEffect = 'move';
 			emptyZone.classList.add('drag-over');
 		});
@@ -1789,6 +1818,7 @@
 
 		emptyZone.addEventListener('drop', async (e) => {
 			e.preventDefault();
+			e.stopPropagation();
 			emptyZone.classList.remove('drag-over');
 
 			// Get selected items from our tracking

--
Gitblit v1.10.0