From a81f7043fc44382775f9afac48e4c7a651e7ac6c Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 04 Jan 2026 18:29:10 +0000
Subject: [PATCH] =PopulateForm.js and ContentRoutes.php minor changes

---
 assets/js/concise/PopulateForm.js |  225 +++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 174 insertions(+), 51 deletions(-)

diff --git a/assets/js/concise/PopulateForm.js b/assets/js/concise/PopulateForm.js
index ec60ffc..f9335db 100644
--- a/assets/js/concise/PopulateForm.js
+++ b/assets/js/concise/PopulateForm.js
@@ -28,12 +28,10 @@
 		const fieldType = this.getFieldType(fieldWrapper);
 
 		switch (fieldType) {
-			case 'image':
-				this.populateImageField(fieldWrapper, fieldName, fieldValue, imagesData);
-				break;
-
+			case 'upload':
 			case 'gallery':
-				this.populateGalleryField(fieldWrapper, fieldName, fieldValue, imagesData);
+			case 'image':
+				this.populateUploadField(fieldWrapper, fieldName, fieldValue, imagesData);
 				break;
 
 			case 'repeater':
@@ -100,9 +98,18 @@
 	 * @returns {string} Field type
 	 */
 	getFieldType(fieldWrapper) {
+		// Check dataset first (most reliable for our use case)
+		if (fieldWrapper.dataset.fieldType) {
+			return fieldWrapper.dataset.fieldType;
+		}
+
+		if (fieldWrapper.dataset.type) {
+			return fieldWrapper.dataset.type;
+		}
+
 		// Check for specific field classes
 		const typeClasses = [
-			'image', 'gallery', 'repeater', 'taxonomy', 'user', 'location',
+			'upload', 'repeater', 'taxonomy', 'user', 'location',
 			'set', 'checkbox', 'select', 'radio', 'true_false', 'date',
 			'time', 'datetime', 'editor', 'number', 'text', 'textarea',
 			'email', 'url', 'tel', 'phone'
@@ -114,11 +121,6 @@
 			}
 		}
 
-		// Check for data attribute
-		if (fieldWrapper.dataset.type) {
-			return fieldWrapper.dataset.type;
-		}
-
 		// Check input type
 		const input = fieldWrapper.querySelector('input, select, textarea');
 		if (input) {
@@ -138,7 +140,12 @@
 	 */
 	populateTextField(fieldWrapper, fieldName, fieldValue) {
 		const input = fieldWrapper.querySelector(`[name="${fieldName}"], input, textarea`);
+		// Skip file inputs - browsers don't allow setting their values programmatically
+		if (input && input.type === 'file') {
+			return;
+		}
 		if (input) {
+
 			input.value = String(fieldValue || '');
 
 			// Update character counter if present
@@ -159,7 +166,6 @@
 			fieldWrapper.querySelector('textarea:not([data-editor="true"])');
 
 		if (textarea) {
-			const oldValue = textarea.value;
 			textarea.value = String(fieldValue || '');
 
 			// Trigger change event to update any dependencies
@@ -385,7 +391,8 @@
 		} else if (typeof fieldValue === 'string') {
 			try {
 				const parsed = JSON.parse(fieldValue);
-				termIds = Array.isArray(parsed) ? parsed.map(v => String(v)) : [String(parsed)];
+				termIds = Array.isArray(parsed) ?
+					parsed.map(v => String(v)) : [String(parsed)];
 			} catch (e) {
 				termIds = fieldValue.split(',').map(v => v.trim());
 			}
@@ -401,6 +408,12 @@
 		const hiddenInput = fieldWrapper.querySelector(`input[type="hidden"][name="${fieldName}"]`);
 		if (hiddenInput) {
 			hiddenInput.value = termIds.join(',');
+
+			// Trigger TaxonomySelector to update visual display
+			const toggle = fieldWrapper.querySelector('.taxonomy-toggle');
+			if (toggle && toggle.dataset.fieldId && window.jvbTaxonomy) {
+				window.jvbTaxonomy.updateFieldFromInput(toggle.dataset.fieldId);
+			}
 		}
 	}
 
@@ -413,76 +426,186 @@
 	}
 
 	/**
-	 * Populate image fields
+	 * Populate upload fields (images, videos, files)
 	 */
-	populateImageField(fieldWrapper, fieldName, fieldValue, imagesData = {}) {
+	populateUploadField(fieldWrapper, fieldName, fieldValue, imagesData = {}) {
+		// Check if this is a timeline gallery
+		const isTimeline = fieldWrapper.dataset.subtype === 'timeline' || fieldName === 'timeline';
+
+		if (isTimeline) {
+			this.populateTimelineGallery(fieldWrapper, fieldName, fieldValue, imagesData);
+			return;
+		}
+
 		if (!fieldValue) {
 			return;
 		}
 
 		// Handle comma-separated IDs or single ID
-		const imageIds = String(fieldValue).split(',').filter(id => parseInt(id.trim()));
-		if (imageIds.length === 0) {
+		const itemIds = String(fieldValue).split(',').filter(id => parseInt(id.trim()));
+		if (itemIds.length === 0) {
 			return;
 		}
 
 		// Update hidden input
 		const hiddenInput = fieldWrapper.querySelector(`input[type="hidden"][name="${fieldName}"]`);
 		if (hiddenInput) {
-			hiddenInput.value = imageIds.join(',');
+			hiddenInput.value = itemIds.join(',');
 		}
 
-		// Update image display
+		// Update display grid
 		const grid = fieldWrapper.querySelector('.item-grid');
 		const uploadContainer = fieldWrapper.querySelector('.file-upload-container');
 
+		// Clear existing items first
 		if (grid) {
 			window.removeChildren(grid);
-			imageIds.forEach(imageId => {
-				let image = window.getTemplate('uploadItem');
-				let img = image.querySelector('img');
+		}
 
-				let details = image.querySelector('details');
-				let meta = window.getTemplate('uploadMeta')
-				details.append(meta);
-				[
-					img.src,
-					img.alt,
-					image.querySelector('[name="image-title"]').value,
-					image.querySelector('[name="image-alt-text"]').value,
-					image.querySelector('[name="image-caption"]').value,
-				] = [
-					imagesData[imageId].medium,
-					imagesData[imageId].alt,
-					imagesData[imageId].title,
-					imagesData[imageId].alt,
-					imagesData[imageId].caption,
-				];
+		fieldWrapper.querySelector('.progress')?.remove();
 
-				details.querySelector('.upload-meta > .hint')?.remove();
+		if (grid) {
+			itemIds.forEach(itemId => {
+				const template = window.getTemplate('uploadItem');
 
-				grid.append(image);
+				if (!template) {
+					console.warn('uploadItem template not found');
+					return;
+				}
+
+				let input = template.querySelector('input[name="select-item"]');
+				let label = template.querySelector('label[for="select-item"]');
+
+				template.dataset.id = itemId;
+				input.name = input.name + `-${itemId}`;
+				input.id = input.name;
+				label.htmlFor = input.name;
+
+				const img = template.querySelector('img');
+				template.querySelector('video')?.remove();
+				const details = template.querySelector('details');
+
+				// Populate with data
+				if (imagesData[itemId]) {
+					const data = imagesData[itemId];
+					if (img) {
+						img.src = data.medium || data.small || data.large || '';
+						img.alt = data['image-alt-text'] || data.alt || '';
+					}
+
+					// Populate metadata fields
+					const titleInput = template.querySelector('[name="image-title"]');
+					const altInput = template.querySelector('[name="image-alt-text"]');
+					const captionInput = template.querySelector('[name="image-caption"]');
+
+					if (titleInput) titleInput.value = data['image-title'] || data.title || '';
+					if (altInput) altInput.value = data['image-alt-text'] || data.alt || '';
+					if (captionInput) captionInput.value = data['image-caption'] || data.caption || '';
+				} else {
+					console.warn('No image data found for ID:', itemId, 'Available data:', Object.keys(imagesData));
+				}
+
+				// Remove hint if present
+				details?.querySelector('.upload-meta > .hint')?.remove();
+
+				grid.append(template);
 			});
 
-			if (imageIds.length > 0) {
-				if (uploadContainer) {
-					uploadContainer.hidden = true;
+			// Hide upload container if items exist
+			if (itemIds.length > 0 && uploadContainer) {
+				uploadContainer.hidden = true;
+			}
+		}
+	}
+
+	populateTimelineGallery(fieldWrapper, fieldName, fieldValue, imagesData) {
+		console.log('populating Timeline Gallery');
+		if (!fieldValue || typeof fieldValue !== 'object') {
+			return;
+		}
+
+		const imageIds = Object.values(fieldValue);
+		if (imageIds.length === 0) {
+			return;
+		}
+
+		// Update display
+		const grid = fieldWrapper.querySelector('.item-grid');
+		const uploadContainer = fieldWrapper.querySelector('.file-upload-container');
+		fieldWrapper.querySelector('.progress')?.remove();
+
+		if (grid) {
+			window.removeChildren(grid);
+			console.log(imageIds);
+			for (let data of Object.entries(fieldValue)) {
+				let imageId = data['post_thumbnail'];
+				const template = window.getTemplate('timelineItem');
+				if (!template) return;
+
+				const img = template.querySelector('img');
+
+				// Remove unnecessary elements
+				template.querySelector('video')?.remove();
+				template.querySelector('.select-item span')?.remove();
+
+				let input = template.querySelector('input[name="select-item"]');
+				let label = template.querySelector('label[for="select-item"]');
+				template.dataset.id = imageId;
+				template.dataset.postId = data.id;
+				input.name = input.name + `-${imageId}`;
+				input.id = input.name;
+				label.htmlFor = input.name;
+
+				const imgData = imagesData[imageId];
+
+				// Set image source
+				if (img && imgData) {
+					img.src = imgData.medium || imgData.small || imgData.large || '';
+					img.title = imgData['image-title'];
 				}
+
+				// Merge data
+				const mergedData = { ...data, ...imgData };
+
+				// Populate fields
+				const fields = template.querySelectorAll('.field');
+				fields.forEach(field => {
+					if (field.classList.contains('group')) {
+						return;
+					}
+
+					const input = field.querySelector('input:not([type="file"]), textarea');
+					if (!input) return;
+
+					const label = field.querySelector('label');
+					const name = input.name.replace('upload_data::', '');
+					const value = mergedData[name];
+
+					// Populate the field
+					this.populateField(field, name, value, imagesData);
+
+					// Update field identifiers
+					const id = data.id;
+					const newName = `[${id}]${name}`;
+					input.name = newName;
+					input.id = newName;
+					if (label) label.htmlFor = newName;
+				});
+
+				grid.append(template);
+			}
+
+			// Hide upload container if items exist
+			if (imageIds.length > 0 && uploadContainer) {
+				uploadContainer.hidden = true;
 			}
 		}
 	}
 
 	/**
-	 * Populate gallery fields
-	 */
-	populateGalleryField(fieldWrapper, fieldName, fieldValue, imagesData = {}) {
-		this.populateImageField(fieldWrapper, fieldName, fieldValue, imagesData);
-	}
-
-	/**
 	 * Populate repeater fields
 	 */
-	populateRepeaterField(fieldWrapper, fieldName, fieldValue, options = {}) {
+	populateRepeaterField(fieldWrapper, fieldName, fieldValue) {
 		if (!fieldValue || !Array.isArray(fieldValue)) {
 			return;
 		}

--
Gitblit v1.10.0