From eea4e21d9bd7b89f7124fa1acbe3347d68db6d90 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 04 Jan 2026 19:35:27 +0000
Subject: [PATCH] =further taxonomyCreator.js debugging

---
 assets/js/concise/Queue.js |  153 ++++++++++++++++++++++++--------------------------
 1 files changed, 73 insertions(+), 80 deletions(-)

diff --git a/assets/js/concise/Queue.js b/assets/js/concise/Queue.js
index 4590141..7e3033c 100644
--- a/assets/js/concise/Queue.js
+++ b/assets/js/concise/Queue.js
@@ -87,36 +87,25 @@
 	}
 
 	async initQueue() {
-		const incomplete = this.getOperationsByStatus(['completed', 'failed_permanent'], false)
-
-		if (incomplete.length > 0) {
-			this.startPolling();
-		} else {
+		let polling = this.maybeStartPolling();
+		if (!polling) {
 			this.updateStatusPanel('synced');
 		}
 
+
 		this.store.subscribe((event, data) => {
 			switch (event) {
 				case 'data-loaded':
 				case 'items-saved':
-					// Initial load from IndexedDB
-					const incomplete = this.getOperationsByStatus(['completed', 'failed_permanent'], false);
-					if (incomplete.length > 0) {
-						this.startPolling();
-					}
+					this.maybeStartPolling();
 					this.updateUI();
 					break;
 				case 'item-saved':
-					// Check for status changes
-					if (data.item) {
-						const oldItem = this.store.data.get(data.item.id);
-						if (oldItem && oldItem.status !== data.item.status) {
-							this.handleOperationStatusChange(data.item, oldItem.status);
-						}
+					console.log(data,'Item saved data');
+					if (data.previousItem && data.previousItem.status !== data.item.status) {
+						this.handleOperationStatusChange(data.item, data.previousItem.status);
 					}
-					if (this.hasQueuedOperations()) {
-						this.startPolling();
-					}
+					this.maybeStartPolling();
 					break;
 				default:
 					this.updateUI();
@@ -124,18 +113,27 @@
 			}
 
 		});
-		this.notify('queue-initialized', {operations: incomplete});
+	}
+
+	maybeStartPolling()
+	{
+		const incomplete = this.getOperationsByStatus(['completed', 'failed_permanent'], false);
+		if (incomplete.length > 0) {
+			this.startPolling();
+			return true;
+		}
+		return false;
 	}
 
 	/**
 	 * Handle operation status changes and notify subscribers
 	 */
-	handleOperationStatusChange(operation, oldStatus) {
-		if (!operation || oldStatus === operation.status) return;
+	handleOperationStatusChange(operation) {
 
 		// Notify based on new status
 		switch(operation.status) {
 			case 'completed':
+				console.log(operation);
 				this.notify('operation-completed', operation);
 				break;
 			case 'failed':
@@ -165,6 +163,7 @@
 			method: 'POST',
 			headers: {},
 			data: {},
+			sendNow: false,				// true = process immediately
 			canMerge: true,
 			popup: 'Saving changes...',
 			title: 'Operation',
@@ -185,6 +184,14 @@
 			return null;
 		}
 
+		if (item.sendNow) {
+			this.processOperation(item).then(()=> {});
+			this.store.clearCache();
+			window.debouncer.schedule('fastQueue', this.startPolling.bind(this), 200);
+			this.showQueue();
+			return item.id;
+		}
+
 		const existingOps = Array.from(this.store.data.values()).filter(op=>
 			op.status === 'queued' &&
 			op.endpoint === item.endpoint &&
@@ -203,7 +210,6 @@
 			return existing.id;
 		}
 
-		console.log('Added to Queue: ', item);
 		this.store.clearCache();
 
 		//Add new operation to DataStore
@@ -239,7 +245,6 @@
 	}
 
 	clearQueue(itemID) {
-		const item = this.store.get(itemID);
 		this.store.delete(itemID);
 	}
 
@@ -256,8 +261,6 @@
 	}
 
 	resetActivityTimer() {
-		this.lastActivity = Date.now();
-
 		if (this.activityTimer) {
 			clearTimeout(this.activityTimer);
 		}
@@ -315,21 +318,17 @@
 		this.setProcessing(false);
 		this.stopActivityTracking();
 
-		const pending = this.getOperationsByStatus(['queued', 'completed', 'failed_permanent'], false);
-		if (pending.length > 0) {
-			this.startPolling();
-			this.showQueue();
-		} else {
-			this.hideQueue();
-		}
+		this.maybeStartPolling() ? this.showQueue() : this.hideQueue();
 	}
 
-	async processOperation(operation) {
+	async processOperation(operation, skip = false) {
 		try {
-			this.updateOperationStatus(operation.id, 'uploading');
+			if (!skip) {
+				this.updateOperationStatus(operation.id, 'uploading');
 
-			if (operation.data?._isFormData) {
-				operation.data = await this.store.objectToFormData(operation.data);
+				if (operation.data?._isFormData) {
+					operation.data = await this.store.objectToFormData(operation.data);
+				}
 			}
 
 			const url = `${this.config.apiBase}${operation.endpoint}`;
@@ -347,7 +346,6 @@
 				});
 				operation.headers['Content-Type'] = 'application/json';
 			}
-
 			const response = await fetch(url, {
 				method: operation.method,
 				headers: operation.headers,
@@ -355,43 +353,17 @@
 			});
 
 			const result = await response.json();
-
+			if (skip) {
+				operation.data = {};
+			}
 			if (response.ok && result.success !== false) {
 				// Handle server-side merge
 				if (result.id && operation.id !== result.id) {
-
-					// Check if the returned ID exists locally
-					const existingOp = this.getQueue(result.id);
-
-					if (existingOp) {
-						// Merge data from both operations
-						existingOp.data = window.deepMerge(existingOp.data, operation.data);
-						existingOp.status = result.status || 'pending';
-						existingOp.serverData = result;
-						this.updateOperationStatus(existingOp.id, existingOp.status);
-						// Update the existing operation
-						this.setQueue(existingOp);
-
-						this.removeOperationFromUI(operation.id);
-
-						// Switch reference to the merged operation
-						operation = existingOp;
-					} else {
-						// Server merged with an operation we don't have locally
-						// Update the ID and continue
-						this.clearQueue(operation.id);
-						operation.id = result.id;
-						operation.status = result.status || 'pending';
-						operation.serverData = result;
-						this.updateOperationStatus(operation.id, operation.status);
-						this.setQueue(operation);
-					}
+					operation = await this.handleServerMerge(operation, result);
 				} else {
-					// Normal processing - no merge
 					operation.status = result.status || 'pending';
 					operation.serverData = result;
 					this.updateOperationStatus(operation.id, operation.status);
-					this.setQueue(operation);
 				}
 
 				this.a11y.announce(`${operation.title} sent to server for processing.`);
@@ -417,6 +389,29 @@
 		}
 	}
 
+	async handleServerMerge(operation, result) {
+		const existingOp = this.getQueue(result.id);
+
+		if (existingOp) {
+			// Merge with existing local operation
+			existingOp.data = window.deepMerge(existingOp.data, operation.data);
+			existingOp.status = result.status || 'pending';
+			existingOp.serverData = result;
+			this.updateOperationStatus(existingOp.id, existingOp.status);
+			this.removeOperationFromUI(operation.id);
+			this.clearQueue(operation.id);
+			return existingOp;
+		} else {
+			// Server merged with unknown operation
+			this.clearQueue(operation.id);
+			operation.id = result.id;
+			operation.status = result.status || 'pending';
+			operation.serverData = result;
+			this.updateOperationStatus(operation.id, operation.status);
+			return operation;
+		}
+	}
+
 	startPolling() {
 		if (this.isPolling) return;
 
@@ -428,8 +423,7 @@
 				this.store.clearCache();
 				await this.store.fetch(); // Fetches from server, updates store.data
 
-				const incomplete = this.getOperationsByStatus(['completed', 'failed_permanent'], false);
-				if (incomplete.length === 0) {
+				if (!this.maybeStartPolling()) {
 					this.stopPolling();
 					this.updateStatusPanel('synced');
 				}
@@ -451,7 +445,9 @@
 			this.countdownTimer = null;
 		}
 	}
-
+	getOperationIds(operations) {
+		return operations.map(op => op.id);
+	}
 	/***********************************************************
 	USER ACTIONS
 	 ***********************************************************/
@@ -560,10 +556,9 @@
 		};
 		this.handleOffline = () => this.updateStatusPanel('offline');
 		this.handleBeforeUnload = (e) => {
-			const hasPending = this.getOperationsByStatus(['queued', 'uploading']);
-			if (hasPending.length > 0) {
+			if (this.isPolling || this.isProcessing) {
 				e.preventDefault();
-				return 'You have unsaved changes in the queue.';
+				return 'You have unsaved changes in the queue. Proceed?';
 			}
 		};
 
@@ -580,16 +575,14 @@
 			this.store.clearHttpHeaders(); // Clear cached headers first
 			this.store.fetch();
 		} else if (e.target.closest(this.selectors.clearButton)) {
-			const completedOps = this.getOperationsByStatus('completed');
+			const completedOps = this.getOperationIds(this.getOperationsByStatus('completed'));
 			if (completedOps.length > 0) {
-				const ids = completedOps.map(op => op.id);
-				this.updateServerOperations(ids, 'dismiss');
+				this.updateServerOperations(completedOps, 'dismiss');
 			}
 		} else if (e.target.closest(this.selectors.retryButton)) {
-			const failedOps = this.getOperationsByStatus('failed');
+			const failedOps = this.getOperationIds(this.getOperationsByStatus('failed'));
 			if (failedOps.length > 0) {
-				const ids = failedOps.map(op => op.id);
-				this.updateServerOperations(ids, 'retry');
+				this.updateServerOperations(failedOps, 'retry');
 			}
 		} else if (e.target.closest('[data-action]')) {
 			const button = e.target.closest('[data-action]');

--
Gitblit v1.10.0