diff --git a/src/components/pages/home/speakers/speakers.jsx b/src/components/pages/home/speakers/speakers.jsx index eb2130e..00da8d1 100644 --- a/src/components/pages/home/speakers/speakers.jsx +++ b/src/components/pages/home/speakers/speakers.jsx @@ -313,6 +313,7 @@ const ITEMS = [ { // 20 + id: '50', name: 'Engin Diri', position: 'Customer Experience Architect
Pulumi', content: @@ -323,10 +324,12 @@ const ITEMS = [ time: '10:25', title: 'How To Add Infrastructure Provisioning to Your Backstage Templates', duration: '90 min', + isWorkshop: true, }, { // 21 + id: '51', name: 'Mikkel Mørk Hegnhøj', position: 'Head of Product and DevRel
Fermyon', content: @@ -337,10 +340,12 @@ const ITEMS = [ time: '10:25', title: 'Hands on with WebAssembly and Kubernetes', duration: '90 min', + isWorkshop: true, }, { // 22 + id: '52', name: 'Nic Vermande', position: 'Head of Developer Relations
Spectro Cloud', content: @@ -352,10 +357,12 @@ const ITEMS = [ title: 'Mastering Cluster API and GitOps: Deep Dive into Extensible Components for Building Production-Ready Kubernetes Clusters', duration: '90 min', + isWorkshop: true, }, { // 23 + id: '53', name: 'Thomas Labarussias', position: 'OSS and Ecosystem Advocate
Sysdig', content: @@ -366,10 +373,12 @@ const ITEMS = [ time: '13:40', title: 'Detecting unexpected behavior and intrusions with Falco', duration: '90 min', + isWorkshop: true, }, { // 24 + id: '53', name: 'Vicente J. Jiménez Miras', position: 'Security Content Engineer
Sysdig', content: @@ -378,6 +387,7 @@ const ITEMS = [ time: '13:40', title: 'Detecting unexpected behavior and intrusions with Falco', duration: '90 min', + isWorkshop: true, }, { diff --git a/src/components/pages/workshops/hero/hero.jsx b/src/components/pages/workshops/hero/hero.jsx new file mode 100644 index 0000000..71833bd --- /dev/null +++ b/src/components/pages/workshops/hero/hero.jsx @@ -0,0 +1,31 @@ +import React from 'react'; + +import Button from 'components/shared/button'; + +const TITLE = 'Workshops schedule for '; +const DESCRIPTION = + "Workshops are included in the schedule for the Kubernetes Community Days Denmark. Attendance is included with the conference ticket and available on a first-come first-served basis."; + +const Hero = () => ( +
+
+

+

+ {DESCRIPTION} +

+ +

+
+); + +export default Hero; diff --git a/src/components/pages/workshops/hero/index.js b/src/components/pages/workshops/hero/index.js new file mode 100644 index 0000000..cffaeab --- /dev/null +++ b/src/components/pages/workshops/hero/index.js @@ -0,0 +1,3 @@ +import Hero from './hero'; + +export default Hero; diff --git a/src/components/pages/workshops/schedule/images/engin-diri.jpg b/src/components/pages/workshops/schedule/images/engin-diri.jpg new file mode 100644 index 0000000..8995611 Binary files /dev/null and b/src/components/pages/workshops/schedule/images/engin-diri.jpg differ diff --git a/src/components/pages/workshops/schedule/images/mikkel-hegnhoj.jpg b/src/components/pages/workshops/schedule/images/mikkel-hegnhoj.jpg new file mode 100644 index 0000000..4e91a43 Binary files /dev/null and b/src/components/pages/workshops/schedule/images/mikkel-hegnhoj.jpg differ diff --git a/src/components/pages/workshops/schedule/images/nicolas-vermande.jpg b/src/components/pages/workshops/schedule/images/nicolas-vermande.jpg new file mode 100644 index 0000000..14fcc5a Binary files /dev/null and b/src/components/pages/workshops/schedule/images/nicolas-vermande.jpg differ diff --git a/src/components/pages/workshops/schedule/images/thomas-labarussias.jpg b/src/components/pages/workshops/schedule/images/thomas-labarussias.jpg new file mode 100644 index 0000000..c83c360 Binary files /dev/null and b/src/components/pages/workshops/schedule/images/thomas-labarussias.jpg differ diff --git a/src/components/pages/workshops/schedule/images/vicente-miras.jpg b/src/components/pages/workshops/schedule/images/vicente-miras.jpg new file mode 100644 index 0000000..931bc0f Binary files /dev/null and b/src/components/pages/workshops/schedule/images/vicente-miras.jpg differ diff --git a/src/components/pages/workshops/schedule/index.js b/src/components/pages/workshops/schedule/index.js new file mode 100644 index 0000000..eb56775 --- /dev/null +++ b/src/components/pages/workshops/schedule/index.js @@ -0,0 +1,3 @@ +import Workshops from './workshops'; + +export default Workshops; diff --git a/src/components/pages/workshops/schedule/workshops.jsx b/src/components/pages/workshops/schedule/workshops.jsx new file mode 100644 index 0000000..3d448ca --- /dev/null +++ b/src/components/pages/workshops/schedule/workshops.jsx @@ -0,0 +1,280 @@ +/* eslint-disable react/prop-types */ +import clsx from 'clsx'; +import React, { useEffect, useState } from 'react'; + +import Button from 'components/shared/button'; +import Modal from 'components/shared/modal'; + +import EnginDiri from './images/engin-diri.jpg'; +import MikkelHegnhoj from './images/mikkel-hegnhoj.jpg'; +import NicVermande from './images/nicolas-vermande.jpg'; +import ThomasLabarussias from './images/thomas-labarussias.jpg'; +import VicenteMiras from './images/vicente-miras.jpg'; + +// TODO: merge with ITEMS array from components/pages/home/speakers +const ITEMS = [ + { + id: '50', + time: '10:25', + title: 'How To Add Infrastructure Provisioning to Your Backstage Templates', + duration: '90 min', + speakers: [ + { + id: '20', + name: 'Engin Diri', + photo: EnginDiri, + }, + ], + presentation: + 'Software templates in Backstage are vital for bootstrapping new projects, effectively reducing startup time and masking complexities. When provisioning infrastructure, questions arise on modeling both day-1 and day-2 operations and ensuring compliance with security and company policies.

In this interactive workshop, I will lead participants through these essential concepts. We\'ll explore how to integrate infrastructure provisioning into software templates and provide a detailed walkthrough of a reference implementation, including day-2 operations.

By the end, attendees will:' + + '
- Understand the benefits of provisioning with Backstage' + + '
- Identify challenges in provisioning infrastructure in templates' + + '
- Apply best practices through Backstage' + + '
- Automate continuous delivery and verification of changes using GitOps with Pulumi' + + '
- Build self-service enabled software templates in Backstage', + coincidedEvent: { + id: '51', + time: '10:25', + title: 'Hands on with WebAssembly and Kubernetes', + duration: '90 min', + speakers: [ + { + id: '21', + name: 'Mikkel Mørk Hegnhøj', + photo: MikkelHegnhoj, + }, + ], + presentation: + 'Learning a new technology can be daunting, and getting started with WebAssembly on the server requires getting up to speed with both new concepts and new tooling. With Spin (https://github.com/fermyon/spin), we want to bring a delightful developer experience to building, distributing, and running serverless functions and microservices with WebAssembly.
As with any exciting early ecosystem, there are a lot of tools, libraries, and CLIs out there, and figuring out how and if they work together can be difficult. With Spin, our goal is to empower developers to go from nothing to building and iterating on their application in just a few commands: `spin new` , `spin build`, and `spin up` is all you need to remember.
In this tutorial, you will get hands-on with Spin and see how Spin applications can run in a Kubernetes environment.', + }, + }, + { + id: '52', + time: '13:40', + title: 'Mastering Cluster API and GitOps: Deep Dive into Extensible Components for Building Production-Ready Kubernetes Clusters', + duration: '90 min', + speakers: [ + { + id: '22', + name: 'Nic Vermande', + photo: NicVermande + } + ], + presentation: + 'There are many different ways you can bootstrap Kubernetes clusters, with various degrees of complexity. Modern Kubernetes installers automate manual tasks but generally, the more they abstract away complexity, the more opinionated they are — and that restricts your choice. Cluster API is different. It is one of the most flexible and efficient tools for managing the Kubernetes lifecycle, whether used for deployments, upgrades or scaling operations. While Cluster API is a powerful tool for provisioning Kubernetes clusters, it doesn\'t cover everything. Essential add-on components and software, such as node auto-scalers, CNI, ingress controllers, and other key infrastructure elements, are not included.
In this workshop, you will delve into how to supercharge Cluster API by integrating it with various solutions to build production-ready clusters, with GitOps as the automation master.', + coincidedEvent: { + id: '53', + time: '13:40', + title: 'Detecting unexpected behavior and intrusions with Falco', + duration: '90 min', + speakers: [ + { + id: '23', + name: 'Thomas Labarussias', + photo: ThomasLabarussias, + }, + { + id: '24', + name: 'Vicente J. Jiménez Miras', + photo: VicenteMiras, + }, + ], + presentation: + "The adoption of containers and orchestration systems, such as Kubernetes, has skyrocketed over the last few years. The popularity of these platforms makes them common targets for cyber criminals. Kubernetes combats this risk with built in controls but what if you want to observe the behavior of your pods at runtime to detect intrusions? In this entry-level tutorial, the instructors will dive into cloud threat detection and explain how to detect unexpected behavior and intrusion.
This tutorial offers a hands-on introduction to Falco, an open source CNCF incubation project. Every participant will use a web browser to access their own lab environment, in which they will use Falco to identify and notify of suspicious behaviors and intrusions. This session targets security practitioners that are new to cloud native and want to expand their knowledge of runtime security and Falco.", + }, + }, +]; + +const Workshops = ({ location }) => { + const [isModalVisible, setIsModalVisible] = useState(false); + const [isCoincidedEvent, setIsCoincidedEvent] = useState(false); + const [modalDataId, setModalDataId] = useState(0); + + const handleModalShow = (id) => { + document.body.classList.add('overflow-hidden'); + setIsModalVisible(true); + setModalDataId(id); + }; + + const handleModalHide = () => { + document.body.classList.remove('overflow-hidden'); + setIsModalVisible(false); + setIsCoincidedEvent(false); + setModalDataId(0); + }; + + useEffect(() => { + if (typeof window !== `undefined`) { + const { state = {} } = location; + + if (state?.modalId) { + handleModalShow(Number(state.modalId)); + } + + if (state?.isCoincidedEvent) { + setIsCoincidedEvent(true); + } + } + }, [location]); + + return ( +
+ + +
+ ); +}; + +export default Workshops; diff --git a/src/components/shared/modal/modal.jsx b/src/components/shared/modal/modal.jsx index 6ddcb38..1d4fb95 100644 --- a/src/components/shared/modal/modal.jsx +++ b/src/components/shared/modal/modal.jsx @@ -48,6 +48,7 @@ const Modal = ({ isVisible, modalData, onModalHide, isPresentationShow }) => { presentation = '', speakers = [], isCoincidedEvent = false, + isWorkshop = false, } = modalData; const shouldReduceMotion = useReducedMotion(); const headingId = useId(); @@ -235,13 +236,26 @@ const Modal = ({ isVisible, modalData, onModalHide, isPresentationShow }) => { {duration} - + {isWorkshop ? ( + {title} - + + // + // {title} + // + ) : ( + + {title} + + )} @@ -282,6 +296,7 @@ Modal.propTypes = { presentation: PropTypes.string, speakers: PropTypes.array, isCoincidedEvent: PropTypes.bool, + isWorkshop: PropTypes.bool, }).isRequired, }; export default Modal; diff --git a/src/constants/links.js b/src/constants/links.js index 610e317..f1a5c14 100644 --- a/src/constants/links.js +++ b/src/constants/links.js @@ -12,6 +12,11 @@ export default { id: getAnchor('Schedule'), homeTo: '/schedule', }, + workshops: { + to: '/workshops', + id: getAnchor('Workshops'), + homeTo: '/workshops', + }, sponsors: { to: `/#${getAnchor('Sponsors')}`, id: getAnchor('Sponsors'), diff --git a/src/constants/menus.js b/src/constants/menus.js index d1ff079..9c1ea4f 100644 --- a/src/constants/menus.js +++ b/src/constants/menus.js @@ -4,6 +4,7 @@ const MENUS = { header: [ { text: 'Speakers', ...LINKS.speakers }, { text: 'Schedule', ...LINKS.schedule }, + { text: 'Workshops', ...LINKS.workshops }, // { text: 'Call for Proposal', ...LINKS.proposal }, { text: 'Call for Volunteers', ...LINKS.volunteer }, { text: 'Venue', ...LINKS.venue }, @@ -18,6 +19,7 @@ const MENUS = { mobile: [ { text: 'Speakers', ...LINKS.speakers }, { text: 'Schedule', ...LINKS.schedule }, + { text: 'Workshops', ...LINKS.workshops }, // { text: 'Call for Proposal', ...LINKS.proposal }, { text: 'Call for Volunteers', ...LINKS.volunteer }, { text: 'Venue', ...LINKS.venue }, diff --git a/src/constants/seo-data.js b/src/constants/seo-data.js index 16ecdfa..61d28e6 100644 --- a/src/constants/seo-data.js +++ b/src/constants/seo-data.js @@ -4,6 +4,11 @@ export default { description: 'Explore the detailed agenda for Kubernetes Community Days in Denmark on November 14, 2023. Listen to expert talks, and connect with Kubernetes professionals. Plan your day now!', }, + workshops: { + title: 'Kubernetes Community Days Denmark (Aarhus) - November 14, 2023', + description: + 'Explore the detailed agenda for the workshops at the Kubernetes Community Days in Denmark on November 14, 2023. Plan your day now!', + }, team: { title: 'Team — Kubernetes Community Days Denmark', description: 'Experience the power of community at the Kubernetes Community Days in Denmark!', diff --git a/src/pages/workshops.jsx b/src/pages/workshops.jsx new file mode 100644 index 0000000..d57c85b --- /dev/null +++ b/src/pages/workshops.jsx @@ -0,0 +1,21 @@ +/* eslint-disable react/prop-types */ +import React from 'react'; + +import Hero from 'components/pages/workshops/hero'; +import Workshops from 'components/pages/workshops/schedule'; +import Layout from 'components/shared/layout'; +import SEO from 'components/shared/seo'; +import SEO_DATA from 'constants/seo-data'; + +const WorkshopsPage = ({ location }) => ( + + + + +); + +export default WorkshopsPage; + +export const Head = ({ location: { pathname } }) => ( + +);