From 3416ee171c3727f378c29046d0c9c963b2253ab1 Mon Sep 17 00:00:00 2001 From: giteaadmin Date: Sun, 24 Aug 2025 23:36:11 -0400 Subject: [PATCH] feat: enhance blog post view counter with individual tracking and display --- src/blog.njk | 13 ++++-- src/blog/8.14.25.md | 4 +- src/js/view-counter.js | 101 +++++++++++++++++++++++++++-------------- 3 files changed, 78 insertions(+), 40 deletions(-) diff --git a/src/blog.njk b/src/blog.njk index fb6da22..60bff37 100644 --- a/src/blog.njk +++ b/src/blog.njk @@ -9,15 +9,20 @@ eleventyExcludeFromCollections: true
{%- for post in collections.general | reverse -%}
-

+

{{ post.data.title }}

-

- {{ post.date | readableDate }} -

+
+ +

{{ post.date | readableDate }}

+ | + + ... +
{% if post.data.excerpt %}

{{ post.data.excerpt }}

{% endif %}
{%- endfor -%}
+ diff --git a/src/blog/8.14.25.md b/src/blog/8.14.25.md index 6aa8bb3..317a1d9 100644 --- a/src/blog/8.14.25.md +++ b/src/blog/8.14.25.md @@ -3,8 +3,8 @@ title: "Junos ZTP with Dnsmasq DHCP in OPNsense" date: "2025-08-14" layout: "post.njk" tags: "general" -description: "Stop configuring your new lab devices manually!" -excerpt: "Stop configuring your new lab devices manually! This guide will show you how to 'Zero Touch' provision Junos devices!" +description: "Stop configuring your new lab devices manually! This guide will show you how to 'Zero Touch' provision Junos devices!" +excerpt: "Stop configuring your new lab devices manually!" sitemapPriority: 0.8 sitemapChangefreq: "weekly" image: "/assets/images/8.14.25/junos+opnsense.jpg" diff --git a/src/js/view-counter.js b/src/js/view-counter.js index c990cc8..9e8329d 100644 --- a/src/js/view-counter.js +++ b/src/js/view-counter.js @@ -1,37 +1,70 @@ document.addEventListener('DOMContentLoaded', () => { - const viewCountElement = document.querySelector('[data-view-count]'); + // Select all elements that are designated to display view counts. + const viewCountElements = document.querySelectorAll('[data-view-count]'); - if (viewCountElement) { - const slug = viewCountElement.dataset.slug; - - // Function to fetch and display the view count - const getViews = async () => { - try { - const response = await fetch(`/api/views/${slug}`); - if (!response.ok) throw new Error('Failed to fetch views'); - const data = await response.json(); - viewCountElement.textContent = `${data.count} views`; - } catch (error) { - console.error('Error getting views:', error); - viewCountElement.textContent = 'Could not load views'; - } - }; - - // Function to increment the view count - const incrementView = async () => { - try { - // Use a flag in localStorage to prevent incrementing on every refresh - const viewed = localStorage.getItem(`viewed-${slug}`); - if (!viewed) { - await fetch(`/api/views/${slug}`, { method: 'POST' }); - localStorage.setItem(`viewed-${slug}`, 'true'); - } - } catch (error) { - console.error('Error incrementing view:', error); - } - }; - - // Run the functions - incrementView().then(getViews); + // If no such elements are found, do nothing. + if (viewCountElements.length === 0) { + return; } -}); + + // Process each view count element found on the page. + viewCountElements.forEach(element => { + const slug = element.dataset.slug; + if (!slug) { + // Skip if the element is missing the data-slug attribute. + return; + } + + // Check if the element is on a single post page by looking for a `.post-meta` parent. + // This distinguishes a single post view (which should be counted) from a list view. + const isSinglePost = element.closest('.post-meta'); + + if (isSinglePost) { + // On a single post page, increment the view count. + const viewed = localStorage.getItem(`viewed-${slug}`); + + // Only increment if the user hasn't viewed this post in the current session. + if (!viewed) { + fetch(`/api/views/${slug}`, { method: 'POST' }) + .then(response => { + if (!response.ok) throw new Error('Network response was not ok'); + return response.json(); + }) + .then(data => { + element.textContent = data.count ?? 'Error'; + // Mark as viewed to prevent re-counting on refresh. + localStorage.setItem(`viewed-${slug}`, 'true'); + }) + .catch(error => { + console.error(`Error incrementing view count for slug ${slug}:`, error); + element.textContent = 'N/A'; + }); + } else { + // If already viewed in this session, just fetch the count without incrementing. + fetch(`/api/views/${slug}`) + .then(response => { + if (!response.ok) throw new Error('Network response was not ok'); + return response.json(); + }) + .then(data => { + element.textContent = data.count ?? 0; + }) + .catch(error => { + console.error(`Error fetching view count for slug ${slug}:`, error); + element.textContent = 'N/A'; + }); + } + } else { + // On a list page (like the main blog page), just fetch and display the count. + fetch(`/api/views/${slug}`) + .then(response => response.json()) + .then(data => { + element.textContent = data.count ?? 0; + }) + .catch(error => { + console.error(`Error fetching view count for slug ${slug}:`, error); + element.textContent = 'N/A'; + }); + } + }); +}); \ No newline at end of file