Refactor nav_entries_oob into composable shared macro with caller block
Replace the shared fallback template with a Jinja macro that each domain (blog, events, market) can call with its own domain-specific nav items. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
34
blog/templates/_types/post/admin/_nav_entries_oob.html
Normal file
34
blog/templates/_types/post/admin/_nav_entries_oob.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{# OOB swap for nav entries and calendars — blog's version using shared macro #}
|
||||||
|
{% from 'macros/nav_entries.html' import nav_entries_oob %}
|
||||||
|
|
||||||
|
{% set has_items = (associated_entries and associated_entries.entries) or calendars %}
|
||||||
|
{% call nav_entries_oob(has_items) %}
|
||||||
|
{% if associated_entries and associated_entries.entries %}
|
||||||
|
{% for entry in associated_entries.entries %}
|
||||||
|
{% set _entry_path = '/' + post.slug + '/calendars/' + entry.calendar_slug + '/' + entry.start_at.year|string + '/' + entry.start_at.month|string + '/' + entry.start_at.day|string + '/entries/' + entry.id|string + '/' %}
|
||||||
|
<a
|
||||||
|
href="{{ events_url(_entry_path) }}"
|
||||||
|
class="{{styles.nav_button_less_pad}}">
|
||||||
|
<div class="w-8 h-8 rounded bg-stone-200 flex-shrink-0"></div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<div class="font-medium truncate">{{ entry.name }}</div>
|
||||||
|
<div class="text-xs text-stone-600 truncate">
|
||||||
|
{{ entry.start_at.strftime('%b %d, %Y at %H:%M') }}
|
||||||
|
{% if entry.end_at %} – {{ entry.end_at.strftime('%H:%M') }}{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if calendars %}
|
||||||
|
{% for calendar in calendars %}
|
||||||
|
{% set local_href=events_url('/' + post.slug + '/calendars/' + calendar.slug + '/') %}
|
||||||
|
<a
|
||||||
|
href="{{ local_href }}"
|
||||||
|
class="{{styles.nav_button_less_pad}}">
|
||||||
|
<i class="fa fa-calendar" aria-hidden="true"></i>
|
||||||
|
<div>{{calendar.name}}</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endcall %}
|
||||||
34
events/templates/_types/post/admin/_nav_entries_oob.html
Normal file
34
events/templates/_types/post/admin/_nav_entries_oob.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{# OOB swap for nav entries and calendars when toggling associations or editing calendars #}
|
||||||
|
{% from 'macros/nav_entries.html' import nav_entries_oob %}
|
||||||
|
|
||||||
|
{% set has_items = (associated_entries and associated_entries.entries) or calendars %}
|
||||||
|
{% call nav_entries_oob(has_items) %}
|
||||||
|
{% if associated_entries and associated_entries.entries %}
|
||||||
|
{% for entry in associated_entries.entries %}
|
||||||
|
{% set _entry_path = '/' + post.slug + '/calendars/' + entry.calendar_slug + '/' + entry.start_at.year|string + '/' + entry.start_at.month|string + '/' + entry.start_at.day|string + '/entries/' + entry.id|string + '/' %}
|
||||||
|
<a
|
||||||
|
href="{{ events_url(_entry_path) }}"
|
||||||
|
class="{{styles.nav_button_less_pad}}">
|
||||||
|
<div class="w-8 h-8 rounded bg-stone-200 flex-shrink-0"></div>
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<div class="font-medium truncate">{{ entry.name }}</div>
|
||||||
|
<div class="text-xs text-stone-600 truncate">
|
||||||
|
{{ entry.start_at.strftime('%b %d, %Y at %H:%M') }}
|
||||||
|
{% if entry.end_at %} – {{ entry.end_at.strftime('%H:%M') }}{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if calendars %}
|
||||||
|
{% for calendar in calendars %}
|
||||||
|
{% set local_href=events_url('/' + post.slug + '/calendars/' + calendar.slug + '/') %}
|
||||||
|
<a
|
||||||
|
href="{{ local_href }}"
|
||||||
|
class="{{styles.nav_button_less_pad}}">
|
||||||
|
<i class="fa fa-calendar" aria-hidden="true"></i>
|
||||||
|
<div>{{calendar.name}}</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endcall %}
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
{# OOB swap for nav entries and calendars when toggling associations or editing calendars #}
|
|
||||||
{% import 'macros/links.html' as links %}
|
|
||||||
|
|
||||||
{# Associated Entries and Calendars - vertical on mobile, horizontal with arrows on desktop #}
|
|
||||||
{% if (associated_entries and associated_entries.entries) or calendars %}
|
|
||||||
<div class="flex flex-col sm:flex-row sm:items-center gap-2 border-r border-stone-200 mr-2 sm:max-w-2xl"
|
|
||||||
id="entries-calendars-nav-wrapper"
|
|
||||||
hx-swap-oob="true">
|
|
||||||
{# Left scroll arrow - desktop only #}
|
|
||||||
<button
|
|
||||||
class="entries-nav-arrow hidden flex-shrink-0 p-2 hover:bg-stone-200 rounded"
|
|
||||||
aria-label="Scroll left"
|
|
||||||
_="on click
|
|
||||||
set #associated-items-container.scrollLeft to #associated-items-container.scrollLeft - 200">
|
|
||||||
<i class="fa fa-chevron-left"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div id="associated-items-container"
|
|
||||||
class="overflow-y-auto sm:overflow-x-auto sm:overflow-y-visible scrollbar-hide max-h-[50vh] sm:max-h-none"
|
|
||||||
style="scroll-behavior: smooth;"
|
|
||||||
_="on load or scroll
|
|
||||||
if window.innerWidth >= 640 and my.scrollWidth > my.clientWidth
|
|
||||||
remove .hidden from .entries-nav-arrow
|
|
||||||
add .flex to .entries-nav-arrow
|
|
||||||
else
|
|
||||||
add .hidden to .entries-nav-arrow
|
|
||||||
remove .flex from .entries-nav-arrow
|
|
||||||
end">
|
|
||||||
<div class="flex flex-col sm:flex-row gap-1">
|
|
||||||
{# Calendar entries #}
|
|
||||||
{% if associated_entries and associated_entries.entries %}
|
|
||||||
{% for entry in associated_entries.entries %}
|
|
||||||
{% set _entry_path = '/' + post.slug + '/calendars/' + entry.calendar_slug + '/' + entry.start_at.year|string + '/' + entry.start_at.month|string + '/' + entry.start_at.day|string + '/entries/' + entry.id|string + '/' %}
|
|
||||||
<a
|
|
||||||
href="{{ events_url(_entry_path) }}"
|
|
||||||
class="{{styles.nav_button_less_pad}}">
|
|
||||||
<div class="w-8 h-8 rounded bg-stone-200 flex-shrink-0"></div>
|
|
||||||
<div class="flex-1 min-w-0">
|
|
||||||
<div class="font-medium truncate">{{ entry.name }}</div>
|
|
||||||
<div class="text-xs text-stone-600 truncate">
|
|
||||||
{{ entry.start_at.strftime('%b %d, %Y at %H:%M') }}
|
|
||||||
{% if entry.end_at %} – {{ entry.end_at.strftime('%H:%M') }}{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{# Calendar links #}
|
|
||||||
{% if calendars %}
|
|
||||||
{% for calendar in calendars %}
|
|
||||||
{% set local_href=events_url('/' + post.slug + '/calendars/' + calendar.slug + '/') %}
|
|
||||||
<a
|
|
||||||
href="{{ local_href }}"
|
|
||||||
class="{{styles.nav_button_less_pad}}">
|
|
||||||
<i class="fa fa-calendar" aria-hidden="true"></i>
|
|
||||||
<div>{{calendar.name}}</div>
|
|
||||||
</a>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.scrollbar-hide::-webkit-scrollbar { display: none; }
|
|
||||||
.scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{# Right scroll arrow - desktop only #}
|
|
||||||
<button
|
|
||||||
class="entries-nav-arrow hidden flex-shrink-0 p-2 hover:bg-stone-200 rounded"
|
|
||||||
aria-label="Scroll right"
|
|
||||||
_="on click
|
|
||||||
set #associated-items-container.scrollLeft to #associated-items-container.scrollLeft + 200">
|
|
||||||
<i class="fa fa-chevron-right"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
{# Empty placeholder to remove nav items when all are disassociated/deleted #}
|
|
||||||
<div id="entries-calendars-nav-wrapper" hx-swap-oob="true"></div>
|
|
||||||
{% endif %}
|
|
||||||
58
shared/browser/templates/macros/nav_entries.html
Normal file
58
shared/browser/templates/macros/nav_entries.html
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{#
|
||||||
|
Composable scrollable nav entries container.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
{% call nav_entries_oob(has_items=True) %}
|
||||||
|
<a href="..." class="{{styles.nav_button_less_pad}}">...</a>
|
||||||
|
<a href="..." class="{{styles.nav_button_less_pad}}">...</a>
|
||||||
|
{% endcall %}
|
||||||
|
|
||||||
|
Each domain (events, blog, market) provides its own items via the caller block.
|
||||||
|
#}
|
||||||
|
|
||||||
|
{% macro nav_entries_oob(has_items) %}
|
||||||
|
{% if has_items %}
|
||||||
|
<div class="flex flex-col sm:flex-row sm:items-center gap-2 border-r border-stone-200 mr-2 sm:max-w-2xl"
|
||||||
|
id="entries-calendars-nav-wrapper"
|
||||||
|
hx-swap-oob="true">
|
||||||
|
<button
|
||||||
|
class="entries-nav-arrow hidden flex-shrink-0 p-2 hover:bg-stone-200 rounded"
|
||||||
|
aria-label="Scroll left"
|
||||||
|
_="on click
|
||||||
|
set #associated-items-container.scrollLeft to #associated-items-container.scrollLeft - 200">
|
||||||
|
<i class="fa fa-chevron-left"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div id="associated-items-container"
|
||||||
|
class="overflow-y-auto sm:overflow-x-auto sm:overflow-y-visible scrollbar-hide max-h-[50vh] sm:max-h-none"
|
||||||
|
style="scroll-behavior: smooth;"
|
||||||
|
_="on load or scroll
|
||||||
|
if window.innerWidth >= 640 and my.scrollWidth > my.clientWidth
|
||||||
|
remove .hidden from .entries-nav-arrow
|
||||||
|
add .flex to .entries-nav-arrow
|
||||||
|
else
|
||||||
|
add .hidden to .entries-nav-arrow
|
||||||
|
remove .flex from .entries-nav-arrow
|
||||||
|
end">
|
||||||
|
<div class="flex flex-col sm:flex-row gap-1">
|
||||||
|
{{ caller() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.scrollbar-hide::-webkit-scrollbar { display: none; }
|
||||||
|
.scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="entries-nav-arrow hidden flex-shrink-0 p-2 hover:bg-stone-200 rounded"
|
||||||
|
aria-label="Scroll right"
|
||||||
|
_="on click
|
||||||
|
set #associated-items-container.scrollLeft to #associated-items-container.scrollLeft + 200">
|
||||||
|
<i class="fa fa-chevron-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div id="entries-calendars-nav-wrapper" hx-swap-oob="true"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
Reference in New Issue
Block a user