-
-
{{ post.date | date: date_format }}
- {%- if site.show_excerpts -%}
-
{{ post.description}}
- {%- endif -%}
+ {%- assign date_format = site.bpdevs.date_format | default: "%b %-d, %Y" -%}
+
+ {% assign count = 0 %} {% assign limit_posts = 3 %} {%- for post in posts -%} {%- if count < limit_posts -%}
+
+
+
{{ post.date | date: date_format }} by: {{ post.author }}
+
+ {%- assign count = count | plus: 1 -%} {%- endif -%} {%- endfor -%}
- {%- assign count = count | plus:1 -%} {%- endif -%} {%- endfor -%}
{% if site.paginate %}
diff --git a/_layouts/index.html b/_layouts/index.html
index a3b4b19..3a6f8a2 100644
--- a/_layouts/index.html
+++ b/_layouts/index.html
@@ -3,15 +3,41 @@
---
{% assign t = site.data.locales[page.lang][page.lang] %} {% if page.title %} {% assign header = page.title %} {% else %} {% assign header = site.title %} {% endif %}
-
- {{ t.index.lead }}
-
+
+
+ {% assign recent_posts = site.posts | slice: 0, 3 %}
+ {% for post in recent_posts %}
+
+
+
+
+
+
{{ post.title }}
+
{{ post.excerpt | strip_html | truncatewords: 20 }}
+
+
+ {% endfor %}
+
+
❮
+
❯
+
{{ content }}
- {%- include latest-posts.html -%}
- {%- include join_us.html -%}
+
+
+
+ {% include latest-posts.html %}
+
+
+ {% include join-us-on-social-media.html %}
+
+
+
+
+ {% include join_us.html %}
+
{%- include partnerships.html -%}
{%- include newsletter_form.html newsletter_title="Learn what the community and its members are doing from our newsletter!" -%}
diff --git a/assets/css/bpd.css b/assets/css/bpd.css
index 7c53dd0..f66cfb9 100644
--- a/assets/css/bpd.css
+++ b/assets/css/bpd.css
@@ -517,3 +517,146 @@ ul.speaking-list {
max-width: 60%;
}
}
+
+.slider {
+ position: relative;
+ max-width: 1200px;
+ margin: 50px auto;
+ overflow: hidden;
+ border: 2px solid #ddd;
+ border-radius: 8px;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
+}
+
+.slides {
+ display: flex;
+ transition: transform 0.5s ease-in-out;
+}
+
+.slide {
+ min-width: 100%;
+ box-sizing: border-box;
+ position: relative;
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+}
+
+.slide .image-wrapper {
+ width: 100%;
+ height: 300px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+ background-color: #222;
+}
+
+.slide .image-wrapper img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+}
+
+.info {
+ padding: 15px;
+ background-color: #fff;
+}
+
+
+.info h2 {
+ margin: 10px 0;
+ font-size: 1.5em;
+ color: #333;
+}
+.info p {
+ margin: 0;
+ font-size: 1em;
+ color: #666;
+}
+
+button {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ background-color: #666;
+ border: none;
+ color: white;
+ font-size: 18px;
+ padding: 10px;
+ cursor: pointer;
+ z-index: 1000;
+ outline: none;
+}
+
+button:focus {
+ outline: none !important;
+}
+
+button:hover {
+ background-color: #333;
+}
+
+button.prev:focus,
+button.next:focus {
+ outline: none !important;
+}
+
+:focus {
+ outline: none !important;
+}
+
+.prev {
+ left: 10px;
+}
+
+.next {
+ right: 10px;
+}
+.grid-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+ gap: 20px;
+ margin-top: 20px;
+}
+
+.grid-item {
+ padding: 15px;
+ border: 1px solid #ddd;
+ border-radius: 8px;
+ background-color: #f9f9f9;
+
+.latest-posts-grid {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20px;
+}
+
+.post-item {
+ flex: 1 1 calc(33.333% - 20px);
+ box-sizing: border-box;
+ padding: 10px;
+ border: 1px solid #ddd;
+ border-radius: 8px;
+ background-color: #f9f9f9;
+}
+
+.post-item h3 {
+ margin-top: 0;
+}
+
+.post-item p {
+ margin: 10px 0 0;
+}
+
+@media (max-width: 800px) {
+ .post-item {
+ flex: 1 1 calc(50% - 20px);
+ }
+}
+
+@media (max-width: 500px) {
+ .post-item {
+ flex: 1 1 100%;
+ }
+}
diff --git a/assets/js/bpd.js b/assets/js/bpd.js
index 27cc31a..c57e320 100644
--- a/assets/js/bpd.js
+++ b/assets/js/bpd.js
@@ -42,3 +42,20 @@ $(document).ready(function () {
loadLanguage($("#language option:selected").val());
});
});
+
+let currentIndex = 0;
+
+function moveSlide(direction) {
+ const slides = document.querySelector(".slides");
+ const totalSlides = slides.children.length;
+
+ currentIndex += direction;
+
+ if (currentIndex < 0) {
+ currentIndex = totalSlides - 1;
+ } else if (currentIndex >= totalSlides) {
+ currentIndex = 0;
+ }
+
+ slides.style.transform = `translateX(-${currentIndex * 100}%)`;
+}
diff --git a/index.html b/index.html
index 4daba48..1bf2ad9 100644
--- a/index.html
+++ b/index.html
@@ -2,7 +2,7 @@
layout: index
lang: en
title: Home
-list_title: Recently on the blog
+list_title: Recent blog
---
Our Mission
diff --git a/tests/test.py b/tests/test.py
index 8c20e34..e1e7e2e 100644
--- a/tests/test.py
+++ b/tests/test.py
@@ -14,7 +14,7 @@ def page_url(xprocess, url_port):
url, port = url_port
class Starter(ProcessStarter):
- timeout = 4
+ timeout = 60
# Start the process
args = [
"bundle",
@@ -103,6 +103,36 @@ def test_mailto_bpdevs(page_url: tuple[Page, str]) -> None:
expect(mailto).to_have_attribute("href", "mailto:contact@blackpythondevs.com")
+def test_carousel_displayed(page_url: tuple[Page, str]) -> None:
+ page, live_server_url = page_url
+ page.goto(live_server_url)
+
+ carousel = page.locator(".slider")
+ expect(carousel).to_be_visible()
+
+ next_button = page.locator(".next")
+ prev_button = page.locator(".prev")
+ expect(next_button).to_be_visible()
+ expect(prev_button).to_be_visible()
+
+
+def test_first_slide_matches_latest_post(page_url: tuple[Page, str]) -> None:
+ page, live_server_url = page_url
+ page.goto(live_server_url)
+
+ # First slide and its title
+ first_slide_title = page.locator(".slide .info h2").nth(0)
+
+ # First slide's title is visible
+ expect(first_slide_title).to_be_visible()
+
+ expected_title = page.locator(".info h2").nth(0).inner_text().strip()
+
+ assert (
+ first_slide_title.inner_text().strip() == expected_title.strip()
+ ), "The first slide's title does not match the expected title of the latest post."
+
+
@pytest.mark.parametrize(
"url",
(
@@ -110,13 +140,6 @@ def test_mailto_bpdevs(page_url: tuple[Page, str]) -> None:
"/blog",
),
)
-def test_page_description_in_index_and_blog(page_url: tuple[Page, str], url: str):
- """Checks for the descriptions data in the blog posts. There should be some objects with the class `post-description`"""
- page, live_server_url = page_url
- page.goto(f"{live_server_url}{url}")
- expect(page.locator("p.post-description").first).to_be_visible()
- expect(page.locator("p.post-description").first).not_to_be_empty()
-
def stem_description(
path: pathlib.Path,