From 358afc73aa13450fce04ac65c319dafd90c78fe3 Mon Sep 17 00:00:00 2001 From: Quincy Morgan <2046746+quincylvania@users.noreply.github.com> Date: Thu, 18 Jan 2024 18:13:26 -0500 Subject: [PATCH] Add notification system for events, e.g. mapping usa --- _includes/scripts.html | 1 + _includes/scripts/realtime_updater.js | 90 +++++++++++++++++++++ _includes/scripts/smooth_anchor_scroller.js | 7 +- _includes/scripts/time_localizer.js | 24 +----- _includes/site_meta.html | 28 +++++++ _sass/dogwood/_layout.scss | 40 +++++++-- 6 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 _includes/scripts/realtime_updater.js diff --git a/_includes/scripts.html b/_includes/scripts.html index 636f67e..1c5198d 100644 --- a/_includes/scripts.html +++ b/_includes/scripts.html @@ -2,4 +2,5 @@ {% include scripts/icon_loader.js %} {% include scripts/time_localizer.js %} {% include scripts/smooth_anchor_scroller.js %} + {% include scripts/realtime_updater.js %} \ No newline at end of file diff --git a/_includes/scripts/realtime_updater.js b/_includes/scripts/realtime_updater.js new file mode 100644 index 0000000..d139929 --- /dev/null +++ b/_includes/scripts/realtime_updater.js @@ -0,0 +1,90 @@ +document.addEventListener("DOMContentLoaded", function() { + + var scheduleRowsToCheck = document.querySelectorAll('table.schedule tr[start][end]'); + + if (scheduleRowsToCheck.length > 0) { + setInterval(checkScheduleRows, 1000); + checkScheduleRows(); + } + + function checkScheduleRows() { + var now = new Date(); + scheduleRowsToCheck.forEach(function(el) { + var start = new Date(parseInt(el.getAttribute('start') + '000')); + var end = new Date(parseInt(el.getAttribute('end') + '000')); + if (now >= start && now < end) { + if (!el.classList.contains('ongoing')) { + el.classList.add('ongoing'); + } + } else if (el.classList.contains('ongoing')) { + el.classList.remove('ongoing'); + } + }); + } + + var homepageUrl = document.querySelector('meta[name="homepage"]').getAttribute('content'); + var nextEventEl = document.querySelector('meta[name="dogwood-next-event"]'); + if (nextEventEl) createRealtimeMessage(); + + function createRealtimeMessage() { + + var title = nextEventEl.getAttribute('content'); + + var noticeInfo = JSON.parse(localStorage.getItem('notice-info')) || null; + if (noticeInfo && noticeInfo.title !== title) { + localStorage.removeItem('notice-info'); + noticeInfo = null; + } + + var end = new Date(parseInt(nextEventEl.getAttribute('end') + '000')); + var now = new Date(); + + // don't show something that's over + if (now > end) return; + + var link = nextEventEl.getAttribute('href'); + + // don't show if we're already on the promoted part of the site + if (window.location.href.startsWith(link) || + // or if we're on the homepage since content is already promoted there + window.location.href === homepageUrl + '/') return; + + var start = new Date(parseInt(nextEventEl.getAttribute('start') + '000')); + + if (now < start && + noticeInfo && + now.getTime() < noticeInfo.clicked + 172800000 + ) { + // don't notify again if event hasn't started yet and it's been under two days since last notified + return; + } + + var tagline = nextEventEl.getAttribute('tagline'); + var logo = nextEventEl.getAttribute('logo'); + + var notice = document.createElement('a'); + notice.setAttribute('href', link); + notice.setAttribute('id', 'notice-overlay'); + notice.classList.add(nextEventEl.getAttribute('noticeclass')); + var html = ''; + + if (logo) { + html += ''; + } + html += '
'; + var status = start > now ? 'Upcoming' : 'Happening Now'; + html += '
' + status + '
'; + html += '

' + title + '
' + tagline + '

' + html += ''; + + notice.innerHTML = html; + document.body.appendChild(notice); + + notice.addEventListener('click', function() { + localStorage.setItem('notice-info', JSON.stringify({ + title: title, + clicked: now.getTime() + })); + }); + } +}); \ No newline at end of file diff --git a/_includes/scripts/smooth_anchor_scroller.js b/_includes/scripts/smooth_anchor_scroller.js index c43c935..91f344a 100644 --- a/_includes/scripts/smooth_anchor_scroller.js +++ b/_includes/scripts/smooth_anchor_scroller.js @@ -1,16 +1,15 @@ // do smooth scroll when clicking an #anchor link instead of jumping -document.addEventListener(`click`, e => { +document.addEventListener('click', function(e) { const origin = e.target.closest(`a`); if (!origin || !origin.href) return; var parts = origin.href.match(/^([^#]*)#(.+)/); - var hash = parts[2]; - if (parts[1] === (window.location.origin + location.pathname) && hash) { + if (parts && parts.length >=3 && parts[1] === (window.location.origin + location.pathname) && parts[2]) { // cancel jump e.preventDefault(); - var elmntToView = document.getElementById(hash); + var elmntToView = document.getElementById(parts[2]); elmntToView.scrollIntoView({behavior: "smooth"}); } }); diff --git a/_includes/scripts/time_localizer.js b/_includes/scripts/time_localizer.js index 8ba6a63..fe0f55c 100644 --- a/_includes/scripts/time_localizer.js +++ b/_includes/scripts/time_localizer.js @@ -1,4 +1,4 @@ -document.addEventListener("DOMContentLoaded", function(event) { +document.addEventListener("DOMContentLoaded", function() { document.querySelectorAll('.time').forEach(function(el) { var targetTimeZone = el.getAttribute('totimezone') || undefined; var sourceTime = el.getAttribute('time') && parseInt(el.getAttribute('time') + '000'); @@ -36,28 +36,6 @@ document.addEventListener("DOMContentLoaded", function(event) { el.textContent = date.toLocaleDateString(undefined, {day:'2-digit',timeZoneName: 'long' }).substring(4); }); - var scheduleRowsToCheck = document.querySelectorAll('table.schedule tr[start][end]'); - - if (scheduleRowsToCheck.length > 0) { - setInterval(checkScheduleRows, 1000); - checkScheduleRows(); - } - - function checkScheduleRows() { - var now = new Date(); - scheduleRowsToCheck.forEach(function(el) { - var start = new Date(parseInt(el.getAttribute('start') + '000')); - var end = new Date(parseInt(el.getAttribute('end') + '000')); - if (now >= start && now < end) { - if (!el.classList.contains('ongoing')) { - el.classList.add('ongoing'); - } - } else if (el.classList.contains('ongoing')) { - el.classList.remove('ongoing'); - } - }); - } - function parseTime(t) { var time = t.match( /(\d+)(?::(\d\d))?\s*([pP]|[aA]?)/ ); var h = parseInt(time[1]); diff --git a/_includes/site_meta.html b/_includes/site_meta.html index c69ab3e..77cc2c3 100644 --- a/_includes/site_meta.html +++ b/_includes/site_meta.html @@ -30,6 +30,34 @@ + +{% assign sessions = site.posts | where_exp: "item", "item.url contains '/events/'" %} +{% assign future_sessions="" | split: ',' -%} +{% assign curDate = site.time | date: '%s' | minus: 86400 %} +{% for session in sessions %} + {% assign page_date = session.date | date: '%s' | minus: 0 %} + {% if page_date >= curDate %} + {% assign future_sessions = future_sessions | push: session %} + {% endif %} +{% endfor %} +{% assign next_session = future_sessions | reverse | first %} +{% if next_session %} + {% assign starttime = next_session.date | date: '%s' %} + {% assign endtime = starttime | plus: 3600 %} + {% if next_session.event %} + {% assign last_in_series = future_sessions | where: 'event', next_session.event | last %} + {% assign endtime = last_in_series.date | date: '%s' | plus: 3600 %} + {% assign next_session = site.pages | find_exp: "item", "item.title==next_session.event or item.temp_title==next_session.event" %} + {% endif %} + +{% endif %} {% for feed in site.feeds %} diff --git a/_sass/dogwood/_layout.scss b/_sass/dogwood/_layout.scss index 388de1c..28c825c 100644 --- a/_sass/dogwood/_layout.scss +++ b/_sass/dogwood/_layout.scss @@ -1439,6 +1439,17 @@ article { } } +.status-bubble { + color: white; + background: $status-color; + border-radius: 20px; + position: absolute; + top: -10px; + font-weight: bold; + font-size: 0.75em; + padding: 0 $sp*0.5; +} + .app-sign { background-position: center; background-size: cover; @@ -1447,15 +1458,8 @@ article { height: 140px; .status-bubble { - color: white; - background: $status-color; - border-radius: 20px; - position: absolute; top: -10px; right: -10px; - font-weight: bold; - font-size: 0.75em; - padding: 0 $sp*0.5; } } .status-symbol { @@ -1514,6 +1518,28 @@ ul.org-members.level-1 li img{ } } +#notice-overlay { + position: fixed; + bottom: $sp*0.5; + right: $sp*0.5; + background: white; + border: 1px solid $grid-color; + border-radius: 4px; + padding: $sp*0.75 $sp*0.5; + box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.12); + + display: flex; + flex-direction: row; + + .logo { + width: 60px; + margin-right: $sp*0.5; + } + .status-bubble { + left: -10px; + } +} + .cond-only { display: none; }