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/CRUD.js |   66 +++++++++++++++++----------------
 1 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/assets/js/concise/CRUD.js b/assets/js/concise/CRUD.js
index 6eee959..8d92f41 100644
--- a/assets/js/concise/CRUD.js
+++ b/assets/js/concise/CRUD.js
@@ -42,8 +42,8 @@
 
 		const baseSetup = (el, refs, data) => {
 			el.dataset.itemId = data.id;
-
-			window.prefixInput(refs.checkbox, `select-${data.id}`, true);
+			let wrapper = refs.checkbox.closest('.preview');
+			window.prefixInput(refs.checkbox, `select-${data.id}`, wrapper, true);
 			refs.checkbox.value = data.id;
 			refs.checkbox.checked = crud.selected.has(parseInt(data.id));
 			if (refs.selectLabel) refs.selectLabel.htmlFor = `select-${data.id}`;
@@ -131,7 +131,8 @@
 				baseSetup(el, refs, data);
 
 				manyRefs?.inputs?.forEach(el => {
-					window.prefixInput(el, `${data.id}-`);
+					let wrapper = el.closest('[data-field]');
+					window.prefixInput(el, `${data.id}-`, wrapper);
 				});
 
 				manyRefs?.status?.forEach(el => {
@@ -143,7 +144,8 @@
 				if (crud.isTimeline) {
 					if (refs.sharedRow) {
 						refs.sharedRow.querySelectorAll('input,select,textarea').forEach(input => {
-							window.prefixInput(input, `${data.id}-`);
+							let wrapper = input.closest('[data-field]');
+							window.prefixInput(input, `${data.id}-`, wrapper);
 						});
 
 						crud.populate.populate(refs.sharedRow, data);
@@ -164,7 +166,8 @@
 							point.dataset.itemId = timeline.id;
 
 							point.querySelectorAll('input,select,textarea').forEach(input => {
-								window.prefixInput(input, `${timeline.id}-`);
+								let wrapper = input.closest('[data-field]');
+								window.prefixInput(input, `${timeline.id}-`, wrapper);
 							});
 
 							crud.populate.populate(point, {
@@ -185,7 +188,8 @@
 					if (crud.ui.table.form?.dataset.edit !== undefined) {
 						// Non-timeline: prefix all inputs normally
 						manyRefs?.inputs?.forEach(input => {
-							window.prefixInput(input, `${data.id}-`);
+							let wrapper = input.closest('[data-field]');
+							window.prefixInput(input, `${data.id}-`, wrapper);
 						});
 
 						manyRefs?.status?.forEach(el => {
@@ -480,37 +484,35 @@
 			}
 			if (event === 'operation-status'
 				&& data.status === 'completed'
-				&& data.endpoint === 'content'
-				&& Object.keys(data.data?.posts??{}).length > 0) {
+				&& data.endpoint === 'uploads/groups') {
 
+				console.log('Cleared local cache. Refresh to see changes');
 				this.store.clearCache();
-				let ids = Object.keys(data.data.posts);
-				let storedChanges = this.changesStore.getMany(ids);
+			}
+			if (event === 'operation-status'
+				&& data.status === 'completed'
+				&& data.type === 'content_update') {
+				console.log('Cleared local cache. Refresh to see changes');
+				this.store.clearCache();
 
-				this.changesStore.deleteMany(ids);
-
-				for (let id of ids) {
-					let stored = storedChanges.filter(change => change.id === id)[0]??false;
-
-					let sentChanges = data.data.posts[id];
-					let remainingChanges = {};
-
-					for (let [key, value] of Object.entries(sentChanges)) {
-						if (stored && !Object.hasOwn(stored, key)) continue;
-						if (stored[key] === value) {
-							delete stored[key];
-						}
-						remainingChanges[key] = value;
-					}
-					if (Object.keys(remainingChanges).length > 0) {
-						remainingChanges['id'] = id;
-						remainingChanges['content'] = this.content;
-						this.changes.set(id, remainingChanges);
-					}
+				// Check for result data (from ContentExecutor)
+				if (!data.result || !data.result.posts) {
+					console.warn('Content update completed but no result.posts', data);
+					return;
 				}
-				if (Object.values(this.changes).length > 0) {
-					this.scheduleBackup();
+
+				// Get successfully processed post IDs
+				const successfulIds = Object.keys(data.result.posts).filter(id => {
+					return data.result.posts[id]?.success === true;
+				});
+
+				if (successfulIds.length === 0) {
+					return;
 				}
+
+				// Clear from both persistent and in-memory storage
+				this.changesStore.deleteMany(successfulIds);
+				successfulIds.forEach(id => this.changes.delete(id));
 			}
 
 		});

--
Gitblit v1.10.0