feat: add talks

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2023-07-19 18:34:44 +02:00
parent ab4ba212d1
commit 7155a112ab
Signed by: mfocko
GPG key ID: 7C47D46246790496
10 changed files with 267 additions and 0 deletions

View file

@ -138,6 +138,10 @@ const config = {
to: "contributions", to: "contributions",
label: "Contributions", label: "Contributions",
}, },
{
to: "talks",
label: "Talks",
},
{ {
to: "blog", to: "blog",
position: "right", position: "right",

View file

@ -0,0 +1,52 @@
@import "../../css/mixins";
.card {
margin-bottom: calc(var(--ifm-spacing-horizontal) * 2);
border: 1px solid var(--ifm-color-emphasis-300);
box-shadow: none;
}
.eventDetailsContainer {
border-left: 1px solid var(--ifm-color-emphasis-300);
@include small-size {
border-left: 0;
border-top: 1px solid var(--ifm-color-emphasis-300);
padding-top: var(--ifm-spacing-vertical);
}
}
.list {
list-style-type: none;
padding-left: 0;
}
.buttons {
> a {
@include small-size {
width: 100%;
margin-top: calc(var(--ifm-spacing-vertical) / 2);
}
}
a + a {
margin-left: 0.5em;
@include small-size {
margin-left: 0;
}
}
}
.icon {
width: 22px;
height: 22px;
margin-right: 0.3rem;
display: inline-block;
position: relative;
top: 4px;
[data-theme="dark"] & {
fill: var(--ifm-font-color-base);
}
}

View file

@ -0,0 +1,138 @@
import clsx from "clsx";
import React, { FunctionComponent } from "react";
import styles from "./Talk.module.scss";
import RecordingIcon from "./assets/icon-recording.svg";
import SlidesIcon from "./assets/icon-slides.svg";
import RepositoryIcon from "./assets/icon-repository.svg";
import CalendarIcon from "./assets/icon-calendar.svg";
import MessageIcon from "./assets/icon-message.svg";
import LocationIcon from "./assets/icon-location.svg";
export interface TalkMetadata {
title: string;
description: React.ReactNode;
events: EventMetadata[];
recordingURL?: string;
slidesURL?: string;
repoURL?: string;
}
export interface EventMetadata {
name: string;
location: string;
date: Date;
}
const Talk: FunctionComponent<TalkMetadata> = ({
title,
description,
events = [],
recordingURL,
slidesURL,
repoURL,
}) => {
return (
<div className="col col--12">
<div className={clsx("card", styles.card)}>
<div className="card__header">
<h2>{title}</h2>
</div>
<div className="card__body">
<div className="row">
<div className="col col--7">{description}</div>
<div className={clsx("col col--5", styles.eventDetailsContainer)}>
<EventDetails data={events} />
</div>
</div>
</div>
<div className="card__footer">
<div className={styles.buttons}>
{recordingURL && (
<a
href={recordingURL}
target="_blank"
className="button button--primary button--outline"
>
<span className="button__icon">
<RecordingIcon />
</span>
Watch recording
</a>
)}
{slidesURL && (
<a
href={slidesURL}
target="_blank"
className="button button--secondary button--outline"
>
<span className="button__icon">
<SlidesIcon />
</span>
See slides
</a>
)}
{repoURL && (
<a
href={repoURL}
target="_blank"
className="button button--secondary button--outline"
>
<span className="button__icon">
<RepositoryIcon />
</span>
See repository
</a>
)}
</div>
</div>
</div>
</div>
);
};
const EventDetails: FunctionComponent<{ data: EventMetadata[] }> = ({
data,
}) => {
if (data.length === 0) {
return null;
}
const [firstEvent, ...otherEvents] = data;
const { name, location, date } = firstEvent;
return (
<div className="row">
<div className="col col--12">
<ul className={styles.list}>
<li>
<MessageIcon className={styles.icon} /> <strong>{name}</strong>
</li>
<li>
<LocationIcon className={styles.icon} /> {location}
</li>
<li>
<CalendarIcon className={styles.icon} /> {formatDateString(date)}
</li>
</ul>
</div>
{data.length > 1 && (
<div className="col col--12">
<p className="margin--none">Also presented on:</p>
<ul>
{otherEvents.map(({ name, location, date }) => (
<li key={name}>
<strong>{name}</strong> in {location} ({formatDateString(date)})
</li>
))}
</ul>
</div>
)}
</div>
);
};
function formatDateString(date: Date): string {
return `${date.getMonth() + 1}/${date.getUTCFullYear()}`;
}
export default Talk;

View file

@ -0,0 +1,2 @@
<!-- Source: https://remixicon.com/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M17 3h4a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h4V1h2v2h6V1h2v2zm-2 2H9v2H7V5H4v4h16V5h-3v2h-2V5zm5 6H4v8h16v-8z"/></svg>

After

Width:  |  Height:  |  Size: 290 B

View file

@ -0,0 +1,2 @@
<!-- Source: https://remixicon.com/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 23.728l-6.364-6.364a9 9 0 1 1 12.728 0L12 23.728zm4.95-7.778a7 7 0 1 0-9.9 0L12 20.9l4.95-4.95zM12 13a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></svg>

After

Width:  |  Height:  |  Size: 289 B

View file

@ -0,0 +1,2 @@
<!-- Source: https://remixicon.com/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M6.455 19L2 22.5V4a1 1 0 0 1 1-1h18a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H6.455zm-.692-2H20V5H4v13.385L5.763 17zM11 10h2v2h-2v-2zm-4 0h2v2H7v-2zm8 0h2v2h-2v-2z"/></svg>

After

Width:  |  Height:  |  Size: 307 B

View file

@ -0,0 +1,2 @@
<!-- Source: https://remixicon.com/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M2 3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H2.992A.993.993 0 0 1 2 20.007V3.993zM8 5v14h8V5H8zM4 5v2h2V5H4zm14 0v2h2V5h-2zM4 9v2h2V9H4zm14 0v2h2V9h-2zM4 13v2h2v-2H4zm14 0v2h2v-2h-2zM4 17v2h2v-2H4zm14 0v2h2v-2h-2z"/></svg>

After

Width:  |  Height:  |  Size: 407 B

View file

@ -0,0 +1,2 @@
<!-- Source: https://remixicon.com/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13 21v2.5l-3-2-3 2V21h-.5A3.5 3.5 0 0 1 3 17.5V5a3 3 0 0 1 3-3h14a1 1 0 0 1 1 1v17a1 1 0 0 1-1 1h-7zm0-2h6v-3H6.5a1.5 1.5 0 0 0 0 3H7v-2h6v2zm6-5V4H6v10.035A3.53 3.53 0 0 1 6.5 14H19zM7 5h2v2H7V5zm0 3h2v2H7V8zm0 3h2v2H7v-2z"/></svg>

After

Width:  |  Height:  |  Size: 379 B

View file

@ -0,0 +1,2 @@
<!-- Source: https://remixicon.com/ -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13 18v2h4v2H7v-2h4v-2H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h18a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-8zM4 5v11h16V5H4zm6 2.5l5 3-5 3v-6z"/></svg>

After

Width:  |  Height:  |  Size: 280 B

61
src/pages/talks.tsx Normal file
View file

@ -0,0 +1,61 @@
import React from "react";
import Layout from "@theme/Layout";
import Talk, { TalkMetadata } from "../components/talks/Talk";
const talks: TalkMetadata[] = [
{
title: "Packit: RPM integration, all in one",
description: (
<>
Do you want to automate how you build and test your RPM packages?
Do you maintain any package in Fedora and want to automate the
releases? Or are you just interested in CI/CD on GitHub or GitLab,
Fedora and integration of upstream projects with RPM-based Linux
distributions? In this session, we are going to deep-dive into
features of Packit that can help you do your day-to-day job.
</>
),
events: [
{
name: "DevConf.cz",
location: "Brno, Czechia",
date: new Date(2023, 6, 17),
},
{
name: "DevConf.cz Mini",
location: "Brno, Czechia",
date: new Date(2023, 3, 31),
},
],
recordingURL: "https://www.youtube.com/watch?v=FxhXzgxWO18",
slidesURL: "https://static.sched.com/hosted_files/devconfcz2023/37/DevConf.cz%20June%202023%20Packit%20talk-1.pdf",
},
];
const title = "Talks";
const description = "Featured talks I presented on various events.";
export default function Talks(): JSX.Element {
return (
<Layout title={title} description={description}>
<main className="container container--fluid margin-vert--lg">
<h1>{title}</h1>
<p>{description}</p>
<div className="row">
{talks.map((talkData) => (
<Talk key={talkData.title} {...talkData} />
))}
</div>
<hr/>
<p>
Credits to <a href="https://kosiec.dev/" target="_blank">
Paweł Kosiec</a> for implementing his own React components
for talks.
</p>
</main>
</Layout>
);
}