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

---
 src/feed/view.js |  147 +++++++++++++++++++++++++++----------------------
 1 files changed, 81 insertions(+), 66 deletions(-)

diff --git a/src/feed/view.js b/src/feed/view.js
index 8066082..103423b 100644
--- a/src/feed/view.js
+++ b/src/feed/view.js
@@ -6,6 +6,7 @@
 		this.a11y = window.jvbA11y;
 		this.error = window.jvbError;
 		this.cache = new window.jvbCache('feed');
+		this.templates = window.jvbTemplates;
 
 		this.config = {
 			source: '',
@@ -20,6 +21,7 @@
 	}
 	init() {
 		this.initElements();
+		this.defineTemplates();
 		this.initListeners();
 		this.initFilters();
 
@@ -64,10 +66,12 @@
 			buttons: {
 				loadMore: 		'button.load-more',
 				remove:			'.remove-term',
-				clearFilters: 	'button.clear-filters'
+				clearFilters: 	'button.clear-filters',
+				refresh:		'button[data-action="refresh"]'
 			}
 		};
 		this.ui = window.uiFromSelectors(this.selectors, this.container);
+		this.ui.buttons.refresh = document.querySelector(this.selectors.buttons.refresh);
 
 		//Add content and taxonomies
 		this.ui.content = this.ui.filters.container.querySelectorAll('[name="content"]');
@@ -169,6 +173,12 @@
 		if (remove) {
 			this.removeSelectedTerm(remove);
 		}
+
+		let refresh = window.targetCheck(e, this.selectors.buttons.refresh);
+		if (refresh) {
+			this.store.clearCache();
+			this.store.fetch();
+		}
 	}
 
 	nextPage() {
@@ -326,17 +336,9 @@
 		const term = this.selector.store.get(termId);
 		if (!term) return;
 		if (this.ui.selected.querySelector(`[data-id="${termId}"]`)) return;
-		let icon = this.getTaxonomyIcon(term.taxonomy);
-		let template = window.getTemplate('feedTerm');
-		if (!template) return;
-		let [iconEl,span] = [template.querySelector('.icon'), template.querySelector('span')];
-		if (!iconEl || !span) return;
-		template.dataset.id = term.id;
-		template.dataset.taxonomy = term.taxonomy;
-		iconEl.className = `icon icon-${icon}`;
-		span.textContent = term.name;
 
-		this.ui.selected.append(template);
+		term.icon = this.getTaxonomyIcon(term.taxonomy);
+		this.ui.selected.append(this.templates.create('feedTerm', term));
 	}
 
 	processCachedFilters() {
@@ -478,26 +480,18 @@
 			this.showEmptyState();
 			this.a11y.announceItems(0, this.isFirstPage());
 		} else {
-			const fragment = document.createDocumentFragment();
-			const processBatch = (startIndex) => {
-				const endIndex = Math.min(startIndex + 10, items.length);
-				for (let i = startIndex; i < endIndex; i++) {
-					const item = items[i];
-					const element = this.createItemElement(item);
-					fragment.append(element);
-				}
-				if (endIndex < items.length) {
-					requestAnimationFrame(() => processBatch(endIndex));
-				} else {
+			window.chunkIt(
+				items,
+				(item) => this.createItemElement(item),
+				(fragment) => {
 					this.removePlaceholders();
 					this.ui.grid.append(fragment);
-
 					if (this.config.gallery) this.gallery.buildGalleryItems('.item img');
 					this.a11y.makeNavigable(this.ui.grid.querySelectorAll('.item:not([data-keyboard-nav])'));
 					this.a11y.announceItems(items.length, !this.isFirstPage(), this.store.lastResponse?.has_more??false);
-				}
-			};
-			processBatch(0);
+				},
+				5
+			).then(()=>{});
 		}
 
 		this.updateFilterControls();
@@ -505,48 +499,11 @@
 
 	showEmptyState() {
 		window.removeChildren(this.ui.grid);
-		let template = window.getTemplate('emptyState');
-		if (!template) return;
-		this.ui.grid.append(template);
-
+		this.ui.grid.append(this.templates.create('emptyState'));
 	}
 
 	createItemElement(item) {
-		let template = window.getTemplate(`feedItem${window.uppercaseFirst(item.content)}`);
-		const isTimeline = Object.hasOwn(template.dataset, 'timeline');
-
-		for (let [fieldName, value] of Object.entries(item.fields)) {
-			if (isTimeline && ['timeline', 'number'].includes(fieldName)) continue;
-
-			let el = template.querySelector(`[data-field="${fieldName}"]`);
-			if (!el) continue;
-			if (value === '') {
-				el.remove();
-				continue;
-			}
-
-			if (this.isImageField(item, value)) {
-				this.formatImageField(el, value, item);
-			} else if (this.isTaxonomyField(item, fieldName)) {
-				this.formatTaxonomyField(el, item, fieldName, value);
-			} else if (this.isTimeField(el)) {
-				this.formatTimeField(el, value);
-			} else {
-				this.formatField(el, value);
-			}
-		}
-
-		let link = template.querySelector('a');
-		if (link && item.url !== '') {
-			[link.href, link.title] =
-				[item.url, `View ${item.fields['post_title']??'Item'}`];
-		}
-
-		if (isTimeline) {
-			this.addTimelineElements(item, template);
-		}
-
-		return template;
+		return this.templates.create(`feedItem${window.uppercaseFirst(item.content)}`, item);
 	}
 	splitIDs(value) {
 		return String(value).split(',').map((value) => parseInt(value.trim())).filter(value=>value);
@@ -659,7 +616,7 @@
 		];
 
 		if (afterEl) {
-			afterEl.textContent = `After ${item.fields.number} Tx`;
+			afterEl.textContent = `After ${item.fields.number - 1} Tx`;
 		}
 		if (number) {
 			number.textContent = item.fields.number;
@@ -679,6 +636,64 @@
 		}
 	}
 
+	defineTemplates() {
+		const T = this.templates;
+		const f = this;
+
+		T.define('feedTerm', {
+			refs: {
+				icon: '.icon',
+				span: 'span'
+			},
+			setup({el, refs, manyRefs, data}) {
+				el.dataset.id = data.id;
+				el.dataset.taxonomy = data.taxonomy;
+				if (refs.icon) refs.icon.className = `icon icon=${data.icon}`;
+				if (refs.span) refs.span.textContent = data.name;
+			}
+		});
+		T.define('emptyState');
+
+		this.contentTypes.forEach(content => {
+			T.define(`feedItem${window.uppercaseFirst(content)}`, {
+				refs: {
+					link: 'a',
+				},
+				manyRefs: {
+					fields: '[data-field]',
+				},
+				setup({el, refs, manyRefs, data}) {
+					const isTimeline = Object.hasOwn(el.dataset, 'timeline');
+					if (manyRefs.fields) {
+						for (let field of manyRefs.fields) {
+							if (isTimeline && ['timeline','number'].includes(field.dataset.field)) continue;
+
+							const value = Object.hasOwn(data.fields, field.dataset.field)? data.fields[field.dataset.field] : false;
+							if (!value) {
+								field.remove();
+								continue;
+							}
+							if (f.isImageField(data, value)) {
+								f.formatImageField(field, value, data);
+							} else if (f.isTaxonomyField(data, field.dataset.field)) {
+								f.formatTaxonomyField(field, data, field.dataset.field, value);
+							} else if (f.isTimeField(field)) {
+								f.formatTimeField(field, value);
+							} else {
+								f.formatField(field, value);
+							}
+						}
+						if (refs.link && data.url !== '') {
+							refs.link.href = data.url;
+							refs.link.title = `View ${data.fields['post_title']??'Item'}`;
+						}
+						if (isTimeline ) f.addTimelineElements(data, el);
+					}
+				}
+			})
+		});
+	}
+
 	// addPlaceholders() {
 	// 	let total = this.contentTypes.length;
 	// 	const fragment = document.createDocumentFragment();

--
Gitblit v1.10.0