diff --git a/innovedus_cms/home/templatetags/home_tags.py b/innovedus_cms/home/templatetags/home_tags.py index d347e30..664cea7 100644 --- a/innovedus_cms/home/templatetags/home_tags.py +++ b/innovedus_cms/home/templatetags/home_tags.py @@ -14,3 +14,26 @@ def random_default_cover(): "img/default_cover_3.jpg", ) return static(random.choice(choices)) + + +@register.simple_tag(takes_context=True) +def idle_recommendations(context, limit=4): + from home.models import ArticlePage + + current_page = context.get("page") + exclude_ids = [] + current_id = getattr(current_page, "id", None) + if current_id: + exclude_ids.append(current_id) + + base_qs = ArticlePage.objects.live().filter(not_news=False).exclude(id__in=exclude_ids) + articles = list(base_qs.filter(trending=True).order_by("-date", "-id")[:limit]) + if len(articles) < limit: + used_ids = [article.id for article in articles] + articles.extend( + list( + base_qs.exclude(id__in=used_ids) + .order_by("-date", "-id")[: limit - len(articles)] + ) + ) + return articles diff --git a/innovedus_cms/mysite/static/css/idle_modal.css b/innovedus_cms/mysite/static/css/idle_modal.css new file mode 100644 index 0000000..e6ffa2e --- /dev/null +++ b/innovedus_cms/mysite/static/css/idle_modal.css @@ -0,0 +1,315 @@ +.idle-modal[hidden] { + display: none; +} + +.idle-modal, +.idle-modal * { + box-sizing: border-box; +} + +.idle-modal { + position: fixed; + inset: 0; + z-index: 2100; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + color: #ffffff; +} + +.idle-modal__backdrop { + position: absolute; + inset: 0; + background: rgba(14, 27, 66, 0.35); +} + +.idle-modal__dialog { + position: relative; + z-index: 1; + width: 1024px; + min-height: 618px; + max-width: 100vw; + overflow: visible; + padding: 82px 92px 48px 76px; + background: #0e1b42; + border: 1pt solid #ffffff; +} + +.idle-modal__close { + position: absolute; + top: 14px; + right: 18px; + display: inline-flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + border: 0; + background: transparent; + color: #ffffff; + font-size: 30px; + line-height: 1; + cursor: pointer; +} + +.idle-modal__title { + margin: 0; + color: #ffffff; + font-family: "Inter", "Noto Sans JP", sans-serif; + font-style: normal; + font-weight: 500; + font-size: 24px; + line-height: 29px; + letter-spacing: 0.12em; + text-align: center; +} + +.idle-modal__cup { + display: block; + width: 88px; + height: 98px; + margin: 23px auto 22px; +} + +.idle-modal__section-head { + display: flex; + align-items: center; + height: 60px; +} + +.idle-modal__section-label { + display: inline-flex; + align-items: center; + justify-content: flex-start; + flex: 0 0 197px; + width: 197px; + height: 60px; + padding-left: 21px; + background: #ffffff; + color: #0e1b42; + font-family: "Inter", "Noto Sans JP", sans-serif; + font-size: 20px; + font-weight: 700; + line-height: 60px; + letter-spacing: 0; +} + +.idle-modal__rule { + display: block; + flex: 1 1 auto; + height: 1px; + background: #ffffff; +} + +.idle-modal__grid { + display: grid; + grid-template-columns: repeat(4, 194px); + gap: 0 26px; + margin-top: 31px; +} + +.idle-modal__card { + width: 194px; + min-width: 0; +} + +.idle-modal__card-link { + display: block; + color: inherit; + text-decoration: none; +} + +.idle-modal__thumb { + display: block; + width: 194px; + height: 133px; + overflow: hidden; + border-radius: 8px; + background: #d9d9d9; +} + +.idle-modal__thumb img { + display: block; + width: 100%; + height: 100%; + object-fit: cover; +} + +.idle-modal__article-title { + display: -webkit-box; + margin-top: 20px; + overflow: hidden; + color: #ffffff; + font-family: "Inter", "Noto Sans JP", sans-serif; + font-style: normal; + font-weight: 400; + font-size: 20px; + line-height: 32px; + letter-spacing: 0.06em; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; +} + +@media (min-width: 768px) and (max-width: 1023px) { + .idle-modal { + padding: 0; + } + + .idle-modal__dialog { + width: 768px; + min-height: 0; + max-width: 100vw; + padding: 56px 48px 44px; + } + + .idle-modal__grid { + grid-template-columns: repeat(4, 145px); + gap: 0 16px; + } + + .idle-modal__card { + width: 145px; + } + + .idle-modal__thumb { + width: 139px; + height: 110px; + } + + .idle-modal__article-title { + margin-top: 12px; + font-size: 20px; + line-height: 32px; + } +} + +@media (min-width: 575px) and (max-width: 767px) { + .idle-modal { + padding: 0; + } + + .idle-modal__dialog { + width: 575px; + min-height: 0; + max-width: 100vw; + padding: 16px 28px; + } + + .idle-modal__title { + font-size: 20px; + line-height: 29px; + } + + .idle-modal__cup { + width: 58px; + height: 65px; + margin: 6px auto; + } + + .idle-modal__section-head { + height: 60px; + } + + .idle-modal__section-label { + flex-basis: 197px; + width: 197px; + height: 60px; + padding-left: 21px; + font-size: 20px; + line-height: 60px; + } + + .idle-modal__grid { + display: grid; + grid-template-columns: repeat(2, 194px); + gap: 8px 16px; + justify-content: center; + margin-top: 10px; + } + + .idle-modal__card { + width: 194px; + } + + .idle-modal__thumb { + width: 194px; + height: 133px; + } + + .idle-modal__article-title { + margin-top: 8px; + font-size: 20px; + line-height: 32px; + letter-spacing: 0.06em; + -webkit-line-clamp: 2; + } +} + +@media (max-width: 574px) { + .idle-modal { + padding: 12px; + } + + .idle-modal__dialog { + width: min(300px, calc(100vw - 24px)); + min-height: 0; + padding: 28px 16px 24px; + } + + .idle-modal__close { + top: 4px; + right: 6px; + width: 32px; + height: 32px; + font-size: 26px; + } + + .idle-modal__title { + font-size: 16px; + line-height: 24px; + letter-spacing: 0.08em; + } + + .idle-modal__cup { + width: 58px; + height: 65px; + margin: 12px auto 12px; + } + + .idle-modal__section-head { + height: 55px; + } + + .idle-modal__section-label { + flex-basis: 139px; + width: 139px; + height: 55px; + padding-left: 14px; + font-size: 14px; + line-height: 55px; + } + + .idle-modal__grid { + grid-template-columns: repeat(2, 139px); + justify-content: center; + gap: 16px 10px; + margin-top: 18px; + } + + .idle-modal__thumb { + width: 139px; + height: 110px; + } + + .idle-modal__card { + width: 139px; + } + + .idle-modal__article-title { + margin-top: 8px; + font-size: 16px; + line-height: 24px; + letter-spacing: 0.04em; + } +} diff --git a/innovedus_cms/mysite/static/js/idle_modal.js b/innovedus_cms/mysite/static/js/idle_modal.js new file mode 100644 index 0000000..38ad310 --- /dev/null +++ b/innovedus_cms/mysite/static/js/idle_modal.js @@ -0,0 +1,70 @@ +(function () { + const modal = document.querySelector("[data-idle-modal]"); + if (!modal) return; + + const delay = Number.parseInt(modal.getAttribute("data-idle-delay") || "120000", 10); + const closeTargets = modal.querySelectorAll("[data-idle-close]"); + const articleLinks = modal.querySelectorAll(".idle-modal__card-link"); + let timer = null; + let lastActive = null; + + const isOpen = () => !modal.hidden; + + const clearIdleTimer = () => { + if (timer) { + window.clearTimeout(timer); + timer = null; + } + }; + + const scheduleIdleTimer = () => { + clearIdleTimer(); + if (document.hidden || isOpen()) return; + timer = window.setTimeout(() => { + lastActive = document.activeElement instanceof HTMLElement ? document.activeElement : null; + modal.hidden = false; + document.body.style.overflow = "hidden"; + const closeButton = modal.querySelector(".idle-modal__close"); + if (closeButton) closeButton.focus(); + }, delay); + }; + + const closeModal = () => { + if (!isOpen()) return; + modal.hidden = true; + document.body.style.overflow = ""; + if (lastActive && typeof lastActive.focus === "function") { + lastActive.focus(); + } + scheduleIdleTimer(); + }; + + ["pointermove", "keydown", "scroll", "touchstart", "click"].forEach((eventName) => { + document.addEventListener( + eventName, + () => { + if (!isOpen()) scheduleIdleTimer(); + }, + { passive: true } + ); + }); + + closeTargets.forEach((target) => { + target.addEventListener("click", closeModal); + }); + + articleLinks.forEach((link) => { + link.addEventListener("click", () => { + document.body.style.overflow = ""; + }); + }); + + document.addEventListener("keydown", (event) => { + if (event.key === "Escape") { + closeModal(); + } + }); + + document.addEventListener("visibilitychange", scheduleIdleTimer); + scheduleIdleTimer(); +})(); diff --git a/innovedus_cms/mysite/templates/base.html b/innovedus_cms/mysite/templates/base.html index 605e70e..40cc338 100644 --- a/innovedus_cms/mysite/templates/base.html +++ b/innovedus_cms/mysite/templates/base.html @@ -47,6 +47,7 @@ + {% block extra_css %} {# Override this in templates to add extra stylesheets #} @@ -67,12 +68,14 @@ {% include "includes/footer.html" %} {% include "includes/contact_form.html" %} {% include "includes/subscribe_fab.html" %} + {% include "includes/idle_modal.html" %} {# Global javascript #} + {# Instagram embed script to render IG oEmbeds #} diff --git a/innovedus_cms/mysite/templates/includes/idle_modal.html b/innovedus_cms/mysite/templates/includes/idle_modal.html new file mode 100644 index 0000000..61ead31 --- /dev/null +++ b/innovedus_cms/mysite/templates/includes/idle_modal.html @@ -0,0 +1,40 @@ +{% load home_tags wagtailimages_tags %} +{% idle_recommendations as idle_articles %} +{% if idle_articles %} + +{% endif %}