Improved homepage, added newsletter self-subscription

This commit is contained in:
Bashy 2026-06-11 15:45:56 +03:00
parent e820431d0c
commit 4ac6e74cdc
9 changed files with 348 additions and 36 deletions

View file

@ -113,6 +113,6 @@ feed:
content_limit: 140
content_limit_delim: ' '
order_by: -date
icon: ./source/images/assets/OpenAltRomania.svg
icon: /images/assets/OpenAltRomania.svg
autodiscovery: true
url: https://openalt.ro

38
scripts/event_filter.js Normal file
View file

@ -0,0 +1,38 @@
'use strict';
hexo.extend.filter.register('before_generate', function () {
const today = new Date();
today.setHours(0, 0, 0, 0);
function isEventPost(post) {
return post.tags && post.tags.data &&
post.tags.data.some(function (t) { return t.name === 'Events'; });
}
const allPosts = hexo.locals.get('posts').toArray();
const eventPosts = allPosts
.filter(isEventPost)
.sort(function (a, b) { return a.date.valueOf() - b.date.valueOf(); });
const pastEvents = eventPosts.filter(function (p) {
return p.date.valueOf() < today.getTime();
});
const futureEvents = eventPosts.filter(function (p) {
return p.date.valueOf() >= today.getTime();
});
hexo.locals.set('nextEvent', futureEvents[0] || false);
hexo.locals.set('lastEvent', pastEvents[pastEvents.length - 1] || false);
// Far-future events (all future except the nearest one) are excluded from
// site.posts so they don't appear in archives or RSS.
const hiddenIds = new Set(futureEvents.slice(1).map(function (p) { return p._id; }));
if (hiddenIds.size > 0) {
const filtered = hexo.locals.get('posts').filter(function (p) {
return !hiddenIds.has(p._id);
});
hexo.locals.set('posts', filtered);
}
});

View file

@ -39,4 +39,3 @@ event:
video: '<iframe title="OpenAlt Romania #3 - May 2026" width="560" height="315" src="https://vhsky.cz/videos/embed/f3uXmxAL7K1ZbbnCU35WbQ" allow="fullscreen" sandbox="allow-same-origin allow-scripts allow-popups allow-forms" style="border: 0px;"></iframe>'
attendees: "11"
---

View file

@ -42,9 +42,6 @@
{% for tag in post.tags.toArray() %}
<category domain="{{ url + tag.path | uriencode }}">{{ tag.name }}</category>
{% endfor %}
{% if post.comments %}
<comments>{{ post.permalink | uriencode }}#disqus_thread</comments>
{% endif %}
</item>
{% endfor %}
</channel>

View file

@ -1,23 +1,26 @@
<% if(page.event.video != "TBD") { %>
<% if(page.event.video && page.event.video != "TBD") { %>
<div>
<%- page.event.video %>
</div>
<%} %>
<% } %>
<div>
<h1 class="event">
<%- page.event.date %> at <%- page.event.time %>
</h1>
<div class="event-actions">
<% if (page.event.luma && page.event.luma !== false) { %>
<a href="<%- page.event.luma %>" target="_blank" class="btn-event btn-luma"><i class="fa-solid fa-calendar-check"></i> RSVP on Luma</a>
<% } %>
<a href="http://speakers.openalt.ro/" target="_blank" class="btn-event btn-speaker"><i class="fa-solid fa-microphone"></i> Call for Presentations</a>
</div>
</div>
<% if(page.event.program != "TBD") { %>
<div>
<h2> AGENDA </h2>
<!-- When agenda is public -->
<% page.event.program.forEach(function(item, index) { %>
<h2 class="program"><%- item.name %> by <a href="<%- item.speaker.url %>"><%- item.speaker.name %></a></h2>
<h2 class="program"><%- item.name %> by <% if (item.speaker.url) { %><a href="<%- item.speaker.url %>"><%- item.speaker.name %></a><% } else { %><%- item.speaker.name %><% } %></h2>
<% if (index < page.event.program.length - 1) { %>
<h2 class="program break">B R E A K</h2>
<% } %>
@ -30,21 +33,16 @@
<h3>
<a href='<%- page.event.place.link %>'><i class="fa fa-map-marker-alt"></i> <%- page.event.place.name %></a>
</h3>
<% if(page.event.place.osm != "TBD" || page.event.place.osm != "") { %>
<% if(page.event.place.osm && page.event.place.osm != "TBD" && page.event.place.osm != "") { %>
<span class="osm"><%- page.event.place.osm %></span>
<% } %>
<%} else { %>
<% } else { %>
<h3>
<i class="fa fa-map-marker-alt"></i> TBD
</h3>
<% } %>
</div>
<div class="smoll">
Would you like to speak on this or our next meetup? <br> Submit your talk here: <a href="http://speakers.openalt.ro/">speakers.openalt.ro</a>.
</div>
<div class="post-content">
<%- page.content %>
</div>

View file

@ -1,11 +1,44 @@
<section class="event">
<% counter = 2 %>
<% page.posts.forEach(function(post) { %>
<% post.tags.data.forEach(function(tag) { %>
<% if ( (tag.name == "Events") && (counter != 0) ) { %>
<%- include('post_preview', { post: post, source: "index", event: counter }) %>
<% counter = counter - 1 %>
<% } %>
<% }); %>
<% }); %>
</section>
<section class="event" style="display: block;">
<% if (site.nextEvent) { var e = site.nextEvent; %>
<div class="event-banner">
<img class="event-banner-logo" src="/images/assets/OpenAltRomania.svg" alt="">
<div class="event-banner-inner">
<div class="event-banner-kicker">Next Meetup</div>
<h1 class="event-banner-title"><%= e.title %></h1>
<p class="event-banner-meta">
<strong><%= e.event.date %></strong> &nbsp;·&nbsp; <strong><%= e.event.time %></strong>
<% if (e.event.place && e.event.place !== 'TBD') { %>
&nbsp;·&nbsp; <span class="event-banner-loc"><i class="fa fa-map-marker-alt"></i><a href="<%- e.event.place.link %>"><%= e.event.place.name %></a></span>
<% } %>
</p>
<div class="event-actions" style="margin-bottom: 2.5em;">
<% if (e.event.luma && e.event.luma !== false) { %>
<a href="<%- e.event.luma %>" target="_blank" class="btn-event btn-luma"><i class="fa-solid fa-calendar-check"></i> RSVP on Luma</a>
<% } %>
<a href="http://speakers.openalt.ro/" target="_blank" class="btn-event btn-speaker"><i class="fa-solid fa-microphone"></i> Call for Presentations</a>
</div>
<div class="event-banner-agenda">
<% if (e.event.program && e.event.program !== 'TBD') { %>
<% e.event.program.forEach(function(item) { %>
<div class="event-banner-agenda-item">
<%- item.name %>
<span class="event-banner-spk"><% if (item.speaker.url) { %><a href="<%- item.speaker.url %>" target="_blank"><%- item.speaker.name %></a><% } else { %><%- item.speaker.name %><% } %></span>
</div>
<% }); %>
<% } else { %>
<div class="event-banner-agenda-item">Agenda TBD</div>
<% } %>
</div>
</div>
</div>
<% } %>
<% if (site.lastEvent) { var l = site.lastEvent; %>
<div style="padding-top: 2em;">
<a href="<%- url_for(l.path) %>"><h1>Video of our last event: <%= l.title %></h1></a>
<% if (l.event.video && l.event.video !== 'TBD') { %>
<div class="vhsky-video"><%- l.event.video %></div>
<% } %>
</div>
<% } %>
</section>

View file

@ -1,11 +1,14 @@
<div class="homepage">
<%- include("_partial/index_event", {
item: site.posts.sort('-date')
}) %>
<style>
main { margin-top: 0 !important; }
body { overflow-x: hidden; }
</style>
<%- include("_partial/index_minifeed", {
<div class="homepage">
<%- include("_partial/index_event") %>
<%- include("_partial/index_minifeed", {
item: site.posts.sort('-date')
}) %>
<%- include("_partial/index_partners") %>
</div>
</div>

View file

@ -82,6 +82,48 @@
</div>
</main>
<!-- Newsletter side tab -->
<div class="newsletter-tab" id="newsletterTab">
<div class="newsletter-tab-label" id="newsletterLabel">Newsletter</div>
<div class="newsletter-tab-panel">
<p class="newsletter-tab-heading">Get notified about future events</p>
<form action="https://listmonk.hackman.club/subscription/form" method="post" class="newsletter-tab-form">
<input type="hidden" name="l" value="720a8345-78db-420c-ad80-0cfa2be62d9e">
<input type="text" name="name" placeholder="Your name" class="newsletter-input">
<input type="email" name="email" placeholder="your@email.com" required class="newsletter-input">
<button type="submit" class="newsletter-btn">Subscribe</button>
</form>
</div>
</div>
<script>
(function() {
var tab = document.getElementById('newsletterTab');
var label = document.getElementById('newsletterLabel');
var focused = false;
tab.addEventListener('mouseenter', function() { tab.classList.add('is-open'); });
tab.addEventListener('mouseleave', function() { if (!focused) tab.classList.remove('is-open'); });
tab.querySelectorAll('input').forEach(function(el) {
el.addEventListener('focus', function() { focused = true; });
el.addEventListener('blur', function() { focused = false; });
});
label.addEventListener('click', function() {
focused = false;
tab.classList.remove('is-open');
});
document.addEventListener('click', function(e) {
if (!tab.contains(e.target)) {
focused = false;
tab.classList.remove('is-open');
}
});
})();
</script>
<!-- Footer -->
<footer>
<div class="footer smoll">

View file

@ -56,7 +56,7 @@ h4 {
.vhsky-video {
width: 75%;
margin-bottom: 1em;
margin: 0 auto 1em;
}
a {
@ -76,6 +76,7 @@ a {
margin: 0;
top: 0;
width: 100%;
z-index: 100;
box-shadow:0 .125rem .25rem rgba(255,255,255,0.075) !important;
}
@ -564,6 +565,207 @@ section {
}
}
/* Newsletter side tab */
.newsletter-tab {
position: fixed;
right: 0;
bottom: 6em;
z-index: 200;
display: flex;
align-items: flex-end;
}
.newsletter-tab-label {
writing-mode: vertical-rl;
transform: rotate(180deg);
background-color: #002B7F;
color: #fff;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.1em;
padding: 1em 0.5em;
border-radius: 0 6px 6px 0;
cursor: default;
user-select: none;
}
.newsletter-tab-panel {
background-color: #161b22;
border: 1px solid #21262d;
border-right: none;
border-radius: 0 6px 6px 0;
padding: 1.25em 0;
width: 0;
overflow: hidden;
opacity: 0;
transition: width 0.3s ease, opacity 0.3s ease, padding 0.3s ease;
}
.newsletter-tab.is-open .newsletter-tab-panel {
width: 220px;
opacity: 1;
padding: 1.25em 1em;
}
.newsletter-tab-heading {
font-size: 12px;
color: #8b949e;
margin: 0 0 0.75em;
white-space: nowrap;
}
.newsletter-tab-form {
display: flex;
flex-direction: column;
gap: 0.5em;
}
.newsletter-input {
padding: 0.45em 0.75em;
border-radius: 5px;
border: 1px solid #30363d;
background-color: #0D1117;
color: #dcdcdf;
font-size: 13px;
font-family: inherit;
white-space: nowrap;
}
.newsletter-input::placeholder {
color: #484f58;
}
.newsletter-btn {
padding: 0.45em 1em;
border-radius: 5px;
border: none;
background-color: #002B7F;
color: #fff;
font-size: 13px;
font-family: inherit;
cursor: pointer;
transition: opacity 0.2s;
}
.newsletter-btn:hover {
background-color: #003fa3;
}
@media (max-width: 900px) {
.newsletter-tab {
display: none;
}
}
/* Homepage event banner */
.event-banner {
position: relative;
overflow: hidden;
background: #0d1117;
min-height: calc(100vh - 63px);
display: flex;
align-items: center;
width: 100vw;
margin-left: calc(50% - 50vw);
}
.event-banner-logo {
position: absolute;
right: 4%;
top: 50%;
transform: translateY(-50%);
height: 70vh;
width: auto;
opacity: 0.15;
pointer-events: none;
min-width: unset !important;
min-height: unset !important;
}
.event-banner-inner {
width: 70%;
margin: 0 auto;
position: relative;
text-align: center;
padding: 4em 0;
}
.event-banner-kicker {
font-size: 0.9em;
letter-spacing: 0.35em;
text-transform: uppercase;
color: #fcd116;
margin-bottom: 0.5em;
}
.event-banner-title {
font-size: 8em !important;
font-weight: 700 !important;
margin: 0 0 0.15em !important;
color: #dcdcdf;
line-height: 0.9 !important;
text-align: center;
}
.event-banner-meta {
font-size: 1.5em;
color: #8b949e;
margin-bottom: 2em;
}
.event-banner-meta strong { color: #dcdcdf; }
.event-banner-loc { color: #8b949e; white-space: nowrap; }
.event-banner-loc i { color: #fcd116; margin-right: 0.3em; }
.event-banner-loc a { color: #8b949e; }
.event-banner-agenda {
display: inline-flex;
gap: 3em;
flex-wrap: wrap;
justify-content: center;
background: rgba(255,255,255,0.04);
border: 1px solid #21262d;
border-radius: 6px;
padding: 1em 2.5em;
}
.event-banner-agenda-item { font-size: 1em; text-align: center; }
.event-banner-agenda-item .event-banner-spk { color: #8b949e; font-size: 0.85em; display: block; }
/* Event action buttons (Luma RSVP, Add to Calendar) */
.event-actions {
display: flex;
gap: 0.75em;
justify-content: center;
flex-wrap: wrap;
margin: 0.5em 0;
}
.btn-event {
display: inline-flex;
align-items: center;
gap: 0.4em;
padding: 0.55em 1.1em;
border-radius: 5px;
font-size: 14px;
font-weight: 600;
text-decoration: none;
transition: opacity 0.2s;
}
.btn-event:hover {
opacity: 0.85;
color: inherit;
}
.btn-luma {
background-color: #fcd116;
color: #0D1117 !important;
}
.btn-luma:hover {
background-color: #ffffff;
opacity: 1;
}
.btn-speaker {
background-color: transparent;
color: #dcdcdf !important;
border: 1px solid #555d68;
}
@media (max-width: 900px) {
nav {
flex-direction: column;