From 2127b1bdd73ecd2423e443992da4b442f5a3c1a3 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 04 Feb 2026 21:19:25 +0000
Subject: [PATCH] =Major overhaul of MetaManager.php -> Meta.php and RestRouteManager.php -> Rest.php. Seems to work for JakeVan

---
 assets/js/concise/FormController.js |   90 +++++++++++++++++++++++++++++++++++---------
 1 files changed, 71 insertions(+), 19 deletions(-)

diff --git a/assets/js/concise/FormController.js b/assets/js/concise/FormController.js
index 9a3f632..07185b6 100644
--- a/assets/js/concise/FormController.js
+++ b/assets/js/concise/FormController.js
@@ -73,7 +73,7 @@
 			},
 			tagList: {
 				tagList: '.field.tag-list',			//querySelectorAll
-				input: '.tag-input-row',
+				input: '.row',
 				add: '.add-tag',
 				remove: '.remove-tag',
 				label: '.tag-label',
@@ -325,6 +325,7 @@
 		if (e.target.closest('[data-ignore]') || this.isRestoring) return;
 
 		let field = this.getField(e.target);
+
 		//Dependencies
 		if (this.dependencies.has(field.dataset.field)) {
 			let dependency = this.dependencies.get(field.dataset.field);
@@ -333,6 +334,11 @@
 			});
 		}
 
+		if (Object.hasOwn(field.dataset, 'repeater-id') || Object.hasOwn(field.dataset,'tag-list-id')) {
+			this.updateCollectionField(field);
+			return;
+		}
+
 		let form = this.getForm(e.target);
 		this.updateItem(field.dataset.field, this.getFieldValue(e.target), form);
 	}
@@ -377,12 +383,12 @@
 
 		if (this.subscribers.size > 0) {
 			e.preventDefault();
-			console.log('Cancelling scheduled backup and manually backing up');
-			this.cancelBackup();
-			await this.backup();
-			const storedData = await this.store.get(form.id);
 
 			if (form.options.cache) {
+				this.cancelBackup();
+				await this.backup();
+				const storedData = await this.store.get(form.id);
+
 				this.notify('form-submit', {
 					config: form,
 					data: storedData.changes
@@ -605,8 +611,11 @@
 								this.removeQuantityListeners(item.element);
 								break;
 						}
+
+						if (check.has(item.id)) {
+							check.delete(item.id);
+						}
 					});
-					check.delete(item.id);
 				}
 			}
 
@@ -787,6 +796,7 @@
 					}
 				}
 			checkForRepeaters(form) {
+
 				if (!form.querySelector(this.selectors.repeater.repeater)) return;
 
 				form.querySelectorAll(this.selectors.repeater.repeater).forEach(repeater => {
@@ -799,7 +809,7 @@
 						sortable: false,
 					};
 
-					if (!config.ui.addButton) return;
+					if (!config.ui.add) return;
 
 					let template = repeater.querySelector('template');
 					this.templates.define(
@@ -811,8 +821,10 @@
 							setup({el, refs, manyRefs, data}) {
 								let index = config.ui.items?.children?.length??0;
 								el.dataset.index = index;
+
+
 								manyRefs.inputs?.forEach(input => {
-									window.prefixInput(input, `${el.dataset.fieldName}:${index}:`)
+									window.prefixInput(input, `${data.repeater.dataset.fieldName}:${index}:`, el);
 								});
 							}
 						},
@@ -841,13 +853,18 @@
 				}
 				handleRepeaterClick(e) {
 					if (e.target.matches(this.selectors.repeater.add)) {
+						console.log('Add Repeater Row');
 						this.addRepeaterRow(e.target.closest('[data-repeater-id]'));
 					} else if (e.target.matches(this.selectors.repeater.remove)) {
-						this.removeRepeaterRow(e.target);
+						console.log('Remove Repeater Row');
+						this.removeRepeaterRow(e.target.closest('[data-index]'));
 					}
 				}
 				addRepeaterRow(repeater) {
-					repeater.append(this.templates.create(repeater.dataset.repeaterId));
+					let data = {};
+					data.repeater = repeater;
+					repeater.append(this.templates.create(repeater.dataset.repeaterId, data));
+					this.initializeFields(repeater, this.getField(repeater).config??{});
 					this.a11y.announce('Row added');
 				}
 				removeRepeaterRow(row) {
@@ -883,7 +900,8 @@
 								let index = config.ui.items?.children?.length??0;
 								el.dataset.index = index;
 								manyRefs.inputs?.forEach(input => {
-									window.prefixInput(input, `${el.dataset.fieldName}:${index}:`)
+									let wrapper = window.closest('.tag-item');
+									window.prefixInput(input, `${el.dataset.fieldName}:${index}:`, wrapper)
 								});
 
 								if (refs.label) {
@@ -977,6 +995,8 @@
 						config.ui.items.append(newItem);
 						config.ui.inputs[0]?.focus();
 
+						this.updateCollectionField(tagList);
+
 						this.a11y.announce('Item added');
 					}
 					removeTagListItem(tag) {
@@ -1179,19 +1199,51 @@
 	 * @param {HTMLElement} container
 	 */
 	reindexList(container) {
+		const fieldName = container.dataset.field || container.dataset.repeaterId || container.dataset.tagListId;
+
 		Array.from(container.children).forEach((item, index) => {
 			item.dataset.index = `${index}`;
-			Array.from(item.children).forEach(child => {
-				if (child.type === 'hidden') {
-					window.prefixInput(
-						child,
-						`${container.dataset.field}:${index}:${child.dataset.field}`
-					);
-				}
+
+			// Find ALL inputs within this item, not just direct children
+			const inputs = item.querySelectorAll('input, select, textarea');
+
+			inputs.forEach(input => {
+				// Skip inputs that shouldn't be re-indexed (like file inputs)
+				if (input.type === 'file') return;
+
+				// Get the field name from the input's data-field or name
+				const inputField = input.dataset.field || input.name.split(':').pop();
+
+				// Re-prefix with the new index, passing item as wrapper
+				window.prefixInput(
+					input,
+					`${fieldName}:${index}:`,
+					item  // Pass the item as wrapper for label lookup
+				);
 			});
 		});
 
-		//schedule save
+
+		this.updateCollectionField(container);
+	}
+
+	/**
+	 * Update the entire repeater/tagList field data
+	 * Call this whenever rows are added, removed, or reordered
+	 */
+	updateCollectionField(element) {
+		const field = element.closest('[data-field]');
+		if (!field) return;
+
+		const fieldType = field.dataset.fieldType;
+		if (!['repeater', 'tag-list'].includes(fieldType)) return;
+
+		const form = this.getForm(element);
+		if (!form) return;
+
+		// Get all current data for the collection
+		const value = this.getFieldValue(field.querySelector('input, select, textarea'));
+		this.updateItem(field.dataset.field, value, form);
 	}
 	/**********************************************************************
 	 VALIDATION

--
Gitblit v1.10.0