From 58e8ae0759ccfa97c478ccae4e0778bdce70966f Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Thu, 22 Jan 2026 22:40:02 +0000
Subject: [PATCH] =DirectoryManager.php updates, some javascript tweaks for CRUD.js, and minor style changes

---
 assets/js/concise/CRUD.js |  109 +++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 74 insertions(+), 35 deletions(-)

diff --git a/assets/js/concise/CRUD.js b/assets/js/concise/CRUD.js
index e3adbea..6eee959 100644
--- a/assets/js/concise/CRUD.js
+++ b/assets/js/concise/CRUD.js
@@ -362,7 +362,7 @@
 								this.forms.clearForm(formId);
 							}
 
-							this.ui.modals[name].form.reset();
+							this.resetForm(this.ui.modals[name].form);
 
 							if (name === 'date') {
 								this.handleCustomDateSelection()
@@ -626,7 +626,9 @@
 		} else if (modal.classList.contains('create')) {
 			title = `Creating your new ${this.singular}`;
 		}
-		this.savePosts(title,false);
+		this.cancelBackup();
+		this.handleBackup().then(()=>{});
+		this.savePosts(title,false).then(()=>{});
 	}
 	handleChange(e) {
 		// Early bailout - target must be in an item or be a filter
@@ -706,11 +708,8 @@
 	handleBulkTaxonomy(result) {
 		if (!result.termIds.length || !this.selected.size) return;
 
-		const changes = {};
-		const taxonomyField = `tax_${result.taxonomy}`;
-
 		this.selected.forEach(itemID => {
-			const item = this.store.get(parseInt(itemID));
+			const item = this.store.get(itemID);
 			if (!item) return;
 
 			// Merge existing terms with new ones
@@ -718,18 +717,10 @@
 			const existingIds = existingTerms.map(t => t.id);
 			const newIds = [...new Set([...existingIds, ...result.termIds])];
 
-			changes[itemID] = {
-				[taxonomyField]: newIds.join(','),
-				content: this.content
-			};
+			this.updateItem(itemID, result.taxonomy, newIds);
 		});
 
-		if (Object.keys(changes).length > 0) {
-			this.savePosts(
-				`Adding ${result.terms.length} ${result.taxonomy} to ${this.selected.size} ${this.plural}...`,
-				false
-			).then(()=>{});
-		}
+		this.savePosts(`Adding ${result.terms.length} ${result.taxonomy} to ${this.selected.size} ${this.plural}...`,).then(()=> {});
 
 		this.selectionHandler.clearSelection();
 	}
@@ -759,13 +750,20 @@
 			`changes-${this.content}`,
 			async () => {
 				if (this.changes.size > 0) {
-					await this.changesStore.saveMany(this.changes);
-					this.changes.clear();
+					await this.handleBackup();
 				}
 			},
 			2000
 		);
 	}
+
+	cancelBackup() {
+		window.debouncer.cancel(`changes-${this.content}`);
+	}
+	async handleBackup() {
+		await this.changesStore.saveMany(this.changes);
+		this.changes.clear();
+	}
 	handleFilterChange(target) {
 		let filter = target.dataset.filter;
 
@@ -875,7 +873,6 @@
 		}
 	}
 		openCreateModal(){
-			this.ui.modals.create.form.reset();
 			this.forms.registerForm(this.ui.modals.create.form,{
 				cache: false,
 			});
@@ -899,9 +896,18 @@
 					}
 					break;
 				case 'trash':
-					this.updateItem(itemID, 'post_status', 'trash');
-					window.fade(button.closest('.item'), false);
-					this.savePosts(`Sending ${this.singular} to trash...`).then(()=>{});
+					if (this.status === 'trash') {
+						if (confirm('Delete this item? This cannot be undone')) {
+							this.updateItem(itemID, 'post_status', 'delete');
+							window.fade(button.closest('.item'), false);
+							this.savePosts(`Permanently deleting ${this.singular}...`).then(()=>{});
+							this.store.delete(itemID);
+						}
+					} else {
+						this.updateItem(itemID, 'post_status', 'trash');
+						window.fade(button.closest('.item'), false);
+						this.savePosts(`Sending ${this.singular} to trash...`).then(()=>{});
+					}
 					break;
 				case 'bulk-edit':
 					if (this.selected.size > 0) {
@@ -921,7 +927,7 @@
 			}
 		}
 		handleBulkDelete() {
-			let isTrash = this.store.filters.status === 'trash';
+			let isTrash = this.status === 'trash';
 			if (this.selected.size > 0 && confirm(`${isTrash ? 'Permanently delete' : 'Send'} ${this.selected.size} ${this.selected.size === 1 ? this.singular : this.plural}${isTrash ? '' : 'to trash'}?`)) {
 				this.selected.forEach(id => {
 					this.store.delete(id);
@@ -1082,8 +1088,6 @@
 		this.ui.modals.edit.h2.textContent = `Editing ${item.fields.post_title === '' ? this.singular : item.fields.post_title}`;
 		this.ui.modals.edit.form.dataset.formId = `edit-${itemID}`;
 
-		this.ui.modals.edit.form.reset();
-
 		this.forms.registerForm(this.ui.modals.edit.form, {cache: false});
 
 		this.isPopulating = true;
@@ -1118,9 +1122,9 @@
 
 		this.forms.registerForm(this.ui.modals.bulkEdit.form, {cache:false});
 
-		// this.isPopulating = true;
-		// this.populate.populate(this.ui.modals.edit.form, item);
-		// this.isPopulating = false;
+		this.isPopulating = true;
+		this.populate.populate(this.ui.modals.edit.form, item);
+		this.isPopulating = false;
 	}
 
 	/*****************************************************************
@@ -1128,9 +1132,12 @@
 	*****************************************************************/
 
 	async savePosts(title = '', delay = false) {
-		const memoryChanges = Array.from(this.changes.values());
-		const storedChanges = await this.changesStore.getAll();
-		const changes = window.deepMerge(storedChanges, memoryChanges);
+		if (this.changes.size > 0) {
+			this.cancelBackup();
+			await this.handleBackup();
+		}
+		const changes = await this.changesStore.getAll();
+
 		if (changes.length === 0) return;
 
 		if (title === '') {
@@ -1221,11 +1228,13 @@
 	updateUI() {
 		if (this.ui.bulk.action) {
 			let options = false;
-			let hasEdit =this.ui.bulk.action.querySelector('[value="edit"]');
-			if (this.status === 'trash' && hasEdit) {
+			let hasEdit = this.ui.bulk.action.querySelector('[value="edit"]');
+			let currentStatus = this.status;
+
+			if (currentStatus === 'trash' && hasEdit) {
 				window.removeChildren(this.ui.bulk.action);
 				options = window.jvbTemplates.create('trashOptions');
-			} else if (this.status !== 'trash' && !hasEdit) {
+			} else if (currentStatus !== 'trash' && !hasEdit) {
 				window.removeChildren(this.ui.bulk.action);
 				options = window.jvbTemplates.create('notTrashOptions');
 			}
@@ -1387,9 +1396,13 @@
 	setFilter(name, value) {
 		if (!this.allowedFilters.includes(name)) return;
 		this.cache.set(name, value);
+
+		if (name === 'status') this.status = value;
+		if (name === 'orderby') this.orderby = value;
+		if (name === 'order') this.order = value;
+
 		let el = this.findFilterEl(name, value);
 		this.setElValue(el, value);
-		//TODO: If we set the element to checked, does that automatically call the change listener, which then also sets the store filter and cache?
 		this.store.setFilter(name, value);
 	}
 
@@ -1461,6 +1474,32 @@
 	/***************************************************************
 	 CLEANUP
 	***************************************************************/
+	resetForm(form) {
+		// Clear text inputs, textareas
+		form.querySelectorAll('input[type="hidden"], input[type="text"], input[type="number"], input[type="email"], input[type="url"], textarea').forEach(input => {
+			input.value = '';
+		});
+
+		// Uncheck checkboxes and radios
+		form.querySelectorAll('input[type="checkbox"], input[type="radio"]').forEach(input => {
+			input.checked = false;
+		});
+
+		// Reset selects to first option
+		form.querySelectorAll('select').forEach(select => {
+			select.selectedIndex = 0;
+		});
+
+		// Clear any selected items displays
+		form.querySelectorAll('.selected-items').forEach(container => {
+			window.removeChildren(container);
+		});
+
+		// Clear upload previews
+		form.querySelectorAll('.item-grid.preview').forEach(grid => {
+			window.removeChildren(grid);
+		});
+	}
 	destroy() {
 		window.debouncer.cancel(`changes-${this.content}`);
 		if (this.changes.size > 0) {

--
Gitblit v1.10.0