Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/draft2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 77 additions & 0 deletions src/components/SprintCard.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
import { getEntry } from 'astro:content';
import Markdown from "@ui/Markdown.astro";

const { slug } = Astro.props;


const sprint = await getEntry("sprints", slug);

if (!sprint) {
throw new Error(`Sprint entry "${slug}" not found`);
}

const { data, body } = sprint;

// <a href={`/sprints/${slug}`} id={slug} class="text-blue-600 hover:text-blue-800 hover:underline"></a>
---

<article class=`${data.draft?"draft2":""} sprint-card bg-white border border-gray-200 rounded-lg p-6 mb-8 shadow-sm hover:shadow-md transition-shadow duration-200` data-python-level={data.pythonLevel} data-room={data.room}>
<header class="mb-4">
<h3 class="text-2xl font-semibold mb-2">
{data.title}
</h3>
<div class="flex flex-wrap gap-4 text-lg text-gray-600">
<span class="flex items-center gap-1">
<span>👥</span>
<span>{data.numberOfPeople}</span>
</span>
<span class="flex items-center gap-1">
<span>🐍</span>
<span>{data.pythonLevel}</span>
</span>
</div>
</header>

<div class="space-y-4">
<div class="text-lg">
<span class="text-gray-900">Contact:</span>
<span class="text-gray-700">{data.contactPerson.name}</span>
{data.contactPerson.email && (
<span class="text-gray-600">
{' '}(<a href={`mailto:${data.contactPerson.email}`} class="text-primary hover:text-primary-hover underline">{data.contactPerson.email}</a>)
</span>
)}
{data.contactPerson.github && (
<span class="text-gray-600">
{' '}(<a href={`https://github.com/${data.contactPerson.github}`} target="_blank" rel="noopener" class="text-primary hover:text-primary-hover underline">@{data.contactPerson.github}</a>)
</span>
)}
{data.contactPerson.twitter && (
<span class="text-gray-600">
{' '}(<a href={`https://x.com/${data.contactPerson.twitter}`} target="_blank" rel="noopener" class="text-primary hover:text-primary-hover underline">@{data.contactPerson.twitter}</a>)
</span>
)}
</div>

{(data.links) && (
<div class="text-lg">
<span class="font-medium text-gray-900">Links:</span>
<ul class="mt-2 ml-6 space-y-1 list-disc">
{data.links?.map((link) => (
<li>
<a href={link.url} target="_blank" rel="noopener" class="text-primary hover:text-primary-hover underline ">{link.title}</a>
</li>
))}
</ul>
</div>
)}


{body &&
<Markdown content={body} />
}

</div>

</article>
26 changes: 26 additions & 0 deletions src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,39 @@ const jobs = defineCollection({
}),
});

const sprints = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
slug: z.string().optional(), // Auto-generated from filename if not provided
numberOfPeople: z.string().or(z.number()),
pythonLevel: z.enum(["Any", "Beginner", "Intermediate", "Advanced"]),
contactPerson: z.object({
name: z.string(),
email: z.string().email().optional().nullable(),
github: z.string().optional().nullable(),
twitter: z.string().optional().nullable(),
}),
links: z
.array(
z.object({
title: z.string(),
url: z.string().url(),
})
)
.optional(),
draft: z.boolean().optional().default(false),
}),
});

export const collections = {
days,
pages,
deadlines,
week,
sessions,
speakers,
sprints,
keynoters,
sponsors,
jobs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ together.

## Open-Source Projects

More info soon!
Anyone can submit a project for the sprints, although sprints are typically
submitted by project maintainers or frequet contributors.

To submit a project for the sprints, head to
[the EuroPython website repository](https://github.com/EuroPython/website) and
add your project as a markdown file in the folder `src/content/spints`. Use the
file `_sprints_template.md` as the template for your project file.

<!-- ## Location of the sprints venue
The Rajska Building (RB), [Žižkov Campus, VŠE](https://maps.app.goo.gl/azRTAczu8B5ma1XFA) (Prague University of Economics and Business) is the home of our sprints again this year.
Expand Down
16 changes: 16 additions & 0 deletions src/content/sprints/_sprints_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "Project name"
numberOfPeople: "" # How many people you expect to be able to accommodate.
pythonLevel: "Any" # Any, Beginner, Intermediate, or Advanced.
contactPerson: # The main person to reach out to regarding the sprint.
name: ""
email:
github:
twitter:
links: # Add as many links as relevant.
- title: "Project xyz GitHub repo"
url: "https://github.com/xyz"
draft: true # Keep this true when you send PR.
---

Your sprint/project description goes here.
13 changes: 13 additions & 0 deletions src/content/sprints/beeware.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: "BeeWare"
numberOfPeople: "TBA"
pythonLevel: "Beginner"
contactPerson:
name: "Russell Keith-Magee"
email:
links:
- title: "BeeWare GitHub"
url: "https://github.com/beeware"
---

Come sprint on the BeeWare project!
17 changes: 17 additions & 0 deletions src/content/sprints/cpython.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
title: "CPython Core"
numberOfPeople: "TBA"
pythonLevel: "Intermediate"
contactPerson:
name: "Petr Viktorin"
email:
links:
- title: "CPython's Developer Guide"
url: "https://devguide.python.org/"
- title: "Code of Conduct"
url: "https://www.python.org/psf/conduct/"
- title: "Easy Issues"
url: "https://github.com/python/cpython/issues?q=is%3Aissue+is%3Aopen+label%3Aeasy"
---

Come sprint on CPython and work on Python 3.15!
16 changes: 16 additions & 0 deletions src/content/sprints/sprints_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "Secret project"
numberOfPeople: "5"
pythonLevel: "Any"
contactPerson:
name: "Nikoś Hell"
email:
github: "nikoshell"
twitter: "nikoshell20"
links:
- title: "Secret GitHub repo"
url: "https://github.com/nikoshell/secret"
draft: true
---

Your sprint/project description goes here.
86 changes: 86 additions & 0 deletions src/pages/sprints.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
import { getCollection } from 'astro:content';
import Layout from '@layouts/SectionLayout.astro';
import SprintCard from '@components/SprintCard.astro';
import Headline from "@ui/Headline.astro"

const sprints = await getCollection("sprints", ({ data }) => {
return import.meta.env.MODE === "production" ? data.draft !== true : true;
});

---

<Layout title="Sprints & Workshops" description="All in one">
<header class="text-center mb-12">
<Headline title="Sprints & Workshops" />
<p class="text-xl text-gray-600 max-w-2xl mx-auto leading-relaxed">
Join collaborative coding sessions and hands-on workshops.
Connect with maintainers, contribute to open source projects,
and learn new skills alongside fellow Python enthusiasts.
</p>
</header>

<div class="flex flex-wrap gap-8 justify-center mb-8">
<div class="flex flex-col gap-2">
<label for="level-filter" class="font-semibold text-gray-700 text-lg">Python Level:</label>
<select id="level-filter" class="px-4 py-2 border border-gray-300 rounded-lg bg-white text-lg min-w-[150px] focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent">
<option value="">All Levels</option>
<option value="Any">Any</option>
<option value="Beginner">Beginner</option>
<option value="Intermediate">Intermediate</option>
<option value="Advanced">Advanced</option>
</select>
</div>
</div>

<div class="text-center mb-8">
<p class="text-gray-600 font-medium">{sprints.length} active {sprints.length === 1 ? 'sprint' : 'sprints'}</p>
</div>

<section class="max-w-4xl mx-auto" id="sprints-list">
{sprints.map((sprint) => (
<SprintCard slug={sprint.slug} />
))}
</section>

{sprints.length === 0 && (
<div class="text-center py-12">
<p class="text-gray-500 text-lg">No sprints are currently available. Check back soon!</p>
</div>
)}
</Layout>

<script>
document.addEventListener('DOMContentLoaded', () => {
const levelFilter = document.getElementById('level-filter') as HTMLSelectElement;
const sprintsList = document.getElementById('sprints-list');
const sprintsCount = document.querySelector('.text-center.mb-8 p');

function filterSprints() {
const selectedLevel = levelFilter.value;
const sprintCards = sprintsList?.querySelectorAll('.sprint-card');

let visibleCount = 0;

sprintCards?.forEach((card) => {
const cardElement = card as HTMLElement;
const pythonLevel = cardElement.getAttribute('data-python-level');

const levelMatch = !selectedLevel || pythonLevel === selectedLevel;

if (levelMatch) {
cardElement.style.display = 'block';
visibleCount++;
} else {
cardElement.style.display = 'none';
}
});

if (sprintsCount) {
sprintsCount.textContent = `${visibleCount} active ${visibleCount === 1 ? 'sprint' : 'sprints'}`;
}
}

levelFilter?.addEventListener('change', filterSprints);
});
</script>
6 changes: 6 additions & 0 deletions src/styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ main a[href^="#"]::before {
background-color: white;
}

.draft2 {
background: url("/draft2.png");
background-size: 25%;
background-color: white;
}

.social-icon {
display: inline-flex;
align-items: center;
Expand Down