You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
8.4 KiB
212 lines
8.4 KiB
{{define "content"}} |
|
<!-- Mobile Dropdown Selector --> |
|
{{if .BlogItems}} |
|
{{template "mobile-dropdown" (dict "Id" "mobile-blog-selector" "Items" .BlogItems "Profiles" $.Profiles "Type" "blog")}} |
|
{{end}} |
|
|
|
<div class="blog-layout"> |
|
<!-- Left Sidebar --> |
|
<aside class="blog-sidebar"> |
|
<div class="blog-header"> |
|
{{if .BlogIndexImage}} |
|
<div class="blog-image"> |
|
<img src="{{.BlogIndexImage}}" alt="{{.BlogIndexTitle}}" /> |
|
</div> |
|
{{end}} |
|
<h1 class="blog-title">{{if .BlogIndexTitle}}{{.BlogIndexTitle}}{{else}}Blog{{end}}</h1> |
|
{{if .BlogIndexSummary}} |
|
<p class="blog-description">{{.BlogIndexSummary}}</p> |
|
{{end}} |
|
<div class="blog-tags"> |
|
<span class="tag">#company</span> |
|
<span class="tag">#GitCitadel</span> |
|
</div> |
|
</div> |
|
|
|
<nav class="blog-nav" aria-label="Blog articles"> |
|
<ul class="article-menu"> |
|
{{range $index, $item := .BlogItems}} |
|
<li> |
|
<a href="#" class="article-link" data-dtag="{{$item.DTag}}" data-index="{{$index}}"{{if eq $index 0}} data-active="true"{{end}}> |
|
<div class="article-link-title"><span class="icon-inline">{{icon "file-text"}}</span> {{$item.Title}}</div> |
|
</a> |
|
</li> |
|
{{end}} |
|
</ul> |
|
</nav> |
|
</aside> |
|
|
|
<!-- Right Content Pane --> |
|
<main class="blog-content"> |
|
{{range $index, $item := .BlogItems}} |
|
<article class="blog-article{{if eq $index 0}} active{{end}}" data-dtag="{{$item.DTag}}" id="article-{{$item.DTag}}"> |
|
<header class="article-header"> |
|
<h1 class="article-title">{{$item.Title}}</h1> |
|
{{if or $item.Time $item.Author}} |
|
<div class="article-meta"> |
|
{{if $item.Time}} |
|
<span class="article-date"><span class="icon-inline">{{icon "clock"}}</span> {{$item.Time}}</span> |
|
{{end}} |
|
{{if $item.Author}} |
|
<span class="article-author"><span class="icon-inline">{{icon "user"}}</span> {{template "user-badge-simple" (dict "Pubkey" $item.Author "Profiles" $.Profiles)}}</span> |
|
{{end}} |
|
</div> |
|
{{end}} |
|
</header> |
|
{{if and $item.Image (ne $item.Image "")}} |
|
<div class="article-image"> |
|
<img src="{{$item.Image}}" alt="{{$item.Title}}" /> |
|
</div> |
|
{{end}} |
|
{{if $item.Summary}}<p class="article-summary">{{$item.Summary}}</p>{{end}} |
|
<div class="article-content"> |
|
{{$item.Content}} |
|
</div> |
|
</article> |
|
{{else}} |
|
<article class="blog-article active"> |
|
<header class="article-header"> |
|
<h1 class="article-title"><span class="icon-inline">{{icon "file-x"}}</span> No Articles</h1> |
|
</header> |
|
<div class="article-content"> |
|
<p><span class="icon-inline">{{icon "inbox"}}</span> No blog articles available yet.</p> |
|
</div> |
|
</article> |
|
{{end}} |
|
</main> |
|
</div> |
|
|
|
<script> |
|
(function() { |
|
const articleLinks = document.querySelectorAll('.article-link'); |
|
const articles = document.querySelectorAll('.blog-article'); |
|
|
|
function showArticle(dtag) { |
|
// Hide all articles |
|
articles.forEach(article => { |
|
article.classList.remove('active'); |
|
}); |
|
|
|
// Show selected article |
|
const targetArticle = document.querySelector(`.blog-article[data-dtag="${dtag}"]`); |
|
if (targetArticle) { |
|
targetArticle.classList.add('active'); |
|
} |
|
|
|
// Update active link |
|
articleLinks.forEach(link => { |
|
if (link.dataset.dtag === dtag) { |
|
link.setAttribute('data-active', 'true'); |
|
} else { |
|
link.removeAttribute('data-active'); |
|
} |
|
}); |
|
|
|
// Update URL hash without scrolling |
|
if (history.pushState) { |
|
history.pushState(null, null, `#${dtag}`); |
|
} else { |
|
window.location.hash = dtag; |
|
} |
|
} |
|
|
|
// Handle link clicks |
|
articleLinks.forEach(link => { |
|
link.addEventListener('click', function(e) { |
|
e.preventDefault(); |
|
const dtag = this.dataset.dtag; |
|
showArticle(dtag); |
|
}); |
|
}); |
|
|
|
// Handle initial hash on page load |
|
if (window.location.hash) { |
|
const hash = window.location.hash.substring(1); |
|
const targetLink = document.querySelector(`.article-link[data-dtag="${hash}"]`); |
|
if (targetLink) { |
|
showArticle(hash); |
|
} |
|
} |
|
|
|
// Handle browser back/forward |
|
window.addEventListener('popstate', function() { |
|
const hash = window.location.hash.substring(1); |
|
if (hash) { |
|
showArticle(hash); |
|
} else { |
|
// Show first article if no hash |
|
const firstLink = document.querySelector('.article-link'); |
|
if (firstLink) { |
|
showArticle(firstLink.dataset.dtag); |
|
} |
|
} |
|
}); |
|
|
|
// Handle mobile custom dropdown |
|
const mobileToggle = document.getElementById('mobile-blog-selector-toggle'); |
|
const mobileMenu = document.getElementById('mobile-blog-selector-menu'); |
|
if (mobileToggle && mobileMenu) { |
|
mobileToggle.addEventListener('click', function(e) { |
|
e.stopPropagation(); |
|
const isExpanded = this.getAttribute('aria-expanded') === 'true'; |
|
this.setAttribute('aria-expanded', !isExpanded); |
|
mobileMenu.classList.toggle('active'); |
|
}); |
|
|
|
// Close dropdown when clicking outside |
|
document.addEventListener('click', function(e) { |
|
if (!mobileToggle.contains(e.target) && !mobileMenu.contains(e.target)) { |
|
mobileToggle.setAttribute('aria-expanded', 'false'); |
|
mobileMenu.classList.remove('active'); |
|
} |
|
}); |
|
|
|
// Handle option selection |
|
mobileMenu.querySelectorAll('li[role="option"]').forEach(function(option) { |
|
option.addEventListener('click', function() { |
|
const dtag = this.dataset.value; |
|
showArticle(dtag); |
|
|
|
// Update selected state |
|
mobileMenu.querySelectorAll('li').forEach(li => li.classList.remove('selected')); |
|
this.classList.add('selected'); |
|
this.setAttribute('aria-selected', 'true'); |
|
|
|
// Update toggle button |
|
const avatar = this.querySelector('.mobile-dropdown-avatar, .mobile-dropdown-avatar-placeholder'); |
|
const title = this.querySelector('.mobile-dropdown-title').textContent; |
|
const selected = mobileToggle.querySelector('.mobile-dropdown-selected'); |
|
selected.innerHTML = avatar.outerHTML + '<span class="mobile-dropdown-title">' + title + '</span>'; |
|
|
|
// Close dropdown |
|
mobileToggle.setAttribute('aria-expanded', 'false'); |
|
mobileMenu.classList.remove('active'); |
|
}); |
|
}); |
|
|
|
// Update dropdown when article changes |
|
const originalShowArticle = showArticle; |
|
showArticle = function(dtag) { |
|
originalShowArticle(dtag); |
|
const selectedOption = mobileMenu.querySelector(`li[data-value="${dtag}"]`); |
|
if (selectedOption) { |
|
mobileMenu.querySelectorAll('li').forEach(li => { |
|
li.classList.remove('selected'); |
|
li.setAttribute('aria-selected', 'false'); |
|
}); |
|
selectedOption.classList.add('selected'); |
|
selectedOption.setAttribute('aria-selected', 'true'); |
|
|
|
// Update toggle button |
|
const avatar = selectedOption.querySelector('.mobile-dropdown-avatar, .mobile-dropdown-avatar-placeholder'); |
|
const title = selectedOption.querySelector('.mobile-dropdown-title').textContent; |
|
const selected = mobileToggle.querySelector('.mobile-dropdown-selected'); |
|
selected.innerHTML = avatar.outerHTML + '<span class="mobile-dropdown-title">' + title + '</span>'; |
|
} |
|
}; |
|
} |
|
})(); |
|
</script> |
|
{{end}} |
|
|
|
{{/* Feed is defined in components.html */}}
|
|
|