From b5abd615697146beeca6dba4acd057d049554a30 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 02 Jan 2026 00:16:00 +0000
Subject: [PATCH] Merge branch 'main' of https://github.com/jakevdwerf/jvb
---
src/feed/view.js | 213 ++++++++++++++++++++++++++++++++++------------------
1 files changed, 139 insertions(+), 74 deletions(-)
diff --git a/src/feed/view.js b/src/feed/view.js
index fdec017..7110cad 100644
--- a/src/feed/view.js
+++ b/src/feed/view.js
@@ -394,35 +394,32 @@
*/
createItemElement(item) {
let template = window.getTemplate(`feedItem${window.uppercaseFirst(item.content)}`);
- if (Object.hasOwn(template.dataset, 'timeline')) {
- return this.createTimelineElement(item, template);
- }
- //fields
+
+ const isTimeline = Object.hasOwn(template.dataset, 'timeline');
+
+ // Format fields using helpers
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 (Object.keys(item.images).map((img)=> parseInt(img)).includes(value)) {
- [
- el.src,
- el.srcset,
- el.alt
- ] = [
- item.images[value].tiny,
- `${item.images[value].tiny} 50w, ${item.images[value].small} 300w, ${item.images[value].medium} 1024w`,
- item.images[value]['image-alt-text']
- ];
- } else if (el.tagName === 'TIME') {
- el.setAttribute('datetime', value);
- el.textContent = window.formatTimeAgo(value);
- } else {
- el.textContent = value;
- }
+ if (!el) continue;
+
if (value === '') {
el.remove();
+ continue;
+ }
+
+ if (this.isImageField(item, value)) {
+ this.formatImageFields(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);
}
}
+
+ // Handle link
let link = template.querySelector('a');
if (link && item.url !== '') {
[
@@ -433,66 +430,134 @@
`View ${item.fields['post_title']??'Item'}`
];
}
+
+ if (isTimeline) {
+ this.addTimelineElements(item, template);
+ }
+
return template;
}
+ splitIDs(value) {
+ return String(value).split(',').map((value) => parseInt(value.trim())).filter(value=>value);
+ }
+ isImageField(item, value) {
+ if (!Object.hasOwn(item, 'images') || Object.keys(item.images).length === 0) {
+ return false;
+ }
+ let values = this.splitIDs(value);
+ return values.some(v =>
+ Object.keys(item.images).map(k => parseInt(k)).includes(parseInt(v))
+ );
+ }
+ formatImageFields(element, value, item) {
+ let values = this.splitIDs(value); // Convert string to array first
+ if (values.length === 0) return;
- createTimelineElement(item, template) {
+ if (values.length > 1) {
+ let image = element.querySelector('img');
+ if (!image) return;
+ values.forEach(imgID => {
+ let img = image.cloneNode(true);
+ this.formatImageField(img, imgID, item);
+ element.append(img);
+ });
+ image.remove();
+ } else {
+ if (element.tagName !== 'IMG') {
+ element = element.querySelector('img');
+ if (!element) return;
+ }
+ this.formatImageField(element, values[0], item);
+ }
+ }
+ formatImageField(element, value, item) {
+ let imgData = item.images[value]??false;
+ if (!imgData) return;
+ [
+ element.src,
+ element.srcset,
+ element.alt
+ ] = [
+ imgData.tiny,
+ `${imgData.tiny} 50w, ${imgData.small} 300w, ${imgData.medium} 1024w`,
+ imgData['image-alt-text']
+ ]
+ }
+ isTaxonomyField(item, field) {
+ if (!Object.hasOwn(item, 'taxonomies') || Object.keys(item.taxonomies).length === 0) {
+ return false;
+ }
+
+ return Object.keys(item.taxonomies).includes(field);
+ }
+ formatTaxonomyField(element, item, field, value) {
+ if (element.tagName !== 'UL' || !element.querySelector('li')) return;
+ let values = this.splitIDs(value);
+ if (values.length === 0) {
+ element.remove();
+ }
+ let listItem = element.querySelector('li');
+ for (let termID of values) {
+ let term = item.taxonomies[field][termID]??false;
+ if (!term) continue;
+ let termItem = listItem.cloneNode(true);
+ let link = termItem.querySelector('a');
+ if (!link) continue;
+
+ [
+ link.href,
+ link.title,
+ link.textContent
+ ] = [
+ term.url,
+ `See more ${term.title}`,
+ term.title
+ ];
+ element.append(termItem);
+ }
+ listItem.remove();
+ }
+ isTimeField(el) {
+ return el.tagName === 'TIME' || el.querySelector('time') !== null;
+ }
+ formatTimeField(element, value) {
+ if (element.tagName !== 'TIME') {
+ element = element.querySelector('time');
+ if (!element) return;
+ }
+ element.setAttribute('datetime', value);
+ element.textContent = window.formatTimeAgo(value, 'F Y');
+ }
+ formatField(element, value) {
+ element.textContent = value;
+ }
+
+ addTimelineElements(item, template) {
let [
- main,
- link,
- beforeImg,
- afterImg,
- afterText,
+ afterEl,
+ number,
started,
- lastTreated,
- total,
- termList,
- timeline
+ last
] = [
- template,
- template.querySelector('a'),
- template.querySelector('img.before'),
- template.querySelector('img.after'),
- template.querySelector('summary span:last-of-type'),
- template.querySelector('p.started time'),
- template.querySelector('p.updated time'),
- template.querySelector('p.total b'),
- template.querySelector('.term-list'),
- Object.values(item.fields.order)
+ template.querySelector('span.after-text'),
+ template.querySelector('[data-field="number"] b'),
+ template.querySelector('[data-field="started"] time'),
+ template.querySelector('[data-field="updated"] time')
];
- let numberTreatments = timeline.length - 1;
- let beforeImgData = item.images[timeline[0]['post_thumbnail']];
- let afterImgData = item.images[timeline[numberTreatments]['post_thumbnail']];
- [
- main.dataset.id,
- link.href,
- beforeImg.src,
- beforeImg.dataset.small,
- beforeImg.dataset.medium,
- afterImg.src,
- afterImg.dataset.small,
- afterImg.dataset.medium,
- afterText.textContent,
- started.textContent,
- lastTreated.textContent,
- total.textContent
- ] = [
- item.id,
- item.url,
- beforeImgData['tiny'],
- beforeImgData.small,
- beforeImgData.medium,
- afterImgData['tiny'],
- afterImgData.small,
- afterImgData.medium,
- `${afterText.textContent} ${numberTreatments} Tx`,
- timeline[0].date??item.date,
- timeline[numberTreatments].date??'',
- `${numberTreatments} Treatments`
- ];
- return template;
+ if (afterEl) {
+ afterEl.textContent = `After ${item.fields.number} Tx`;
+ }
+ if (number) {
+ number.textContent = item.fields.number;
+ }
+ if (started) {
+ this.formatTimeField(started, item.fields.timeline[0]['post_date']);
+ }
+ if (last) {
+ this.formatTimeField(last, item.fields.timeline[item.fields.timeline.length - 1]['post_date']);
+ }
}
removePlaceholders() {
--
Gitblit v1.10.0