Adding podcast episodes (#27462)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Zachary DeRose 2024-08-15 16:12:25 -04:00 committed by GitHub
parent 01985c11db
commit f7eab14f6b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 233 additions and 11 deletions

View File

@ -0,0 +1,18 @@
---
title: 'Nx Enterprise Podcast Episode 1: Hicham El Hammouchi'
slug: 'hicham-el-hammouchi-podcast-1'
authors: ['Zack DeRose']
tags: [podcast]
cover_image: /blog/images/2024-06-18/ep-1-hicham.png
podcastYoutubeId: 8iiLB_2djZ8
podcastSpotifyId: 24yagCNpu9EGj0fCwSDQkj
podcastAmazonUrl: https://music.amazon.com/podcasts/a221fdad-36fd-4695-a5b4-038d7b99d284/episodes/899a2e4c-2e56-4dfa-a3e3-e69eb216f2b0/the-enterprise-software-podcast-by-nx-the-enterprise-software-podcast-by-nx-1-hicham-el-hamouchi
podcastAppleUrl: https://podcasters.spotify.com/pod/show/enterprise-software/episodes/The-Enterprise-Software-Podcast-By-Nx-1--Hicham-El-Hamouchi-e2l0302
podcastIHeartUrl: https://www.iheart.com/podcast/269-the-enterprise-software-po-186891508/episode/the-enterprise-software-podcast-by-nx-186891511/
---
In this episode, Zack DeRose from Nx chats with Hicham El Hammouchi, a veteran in enterprise software. Hicham dives into his background, sharing his career journey and the wealth of experience he's gathered along the way.
They tackle the tough challenges that companies face in software development. Hicham offers practical insights and real-life examples from his own career, making complex issues easier to understand. He also shares some tried-and-true strategies for overcoming these hurdles, emphasizing the importance of teamwork and effective project management.
As the chat continues, Zack and Hicham explore the latest tech trends and innovations that are shaking up the industry. Hicham's forward-thinking views provide a sneak peek into the future of enterprise software. They also discuss detailed case studies of successful projects, highlighting the importance of staying focused on customer needs and feedback.

View File

@ -0,0 +1,18 @@
---
title: 'Nx Enterprise Podcast Episode 2: Tine Kondo'
slug: 'tine-kondo-podcast-2'
authors: ['Zack DeRose']
tags: [podcast]
cover_image: /blog/images/2024-07-19/ep-2-tine.png
podcastYoutubeId: Nzf3BmymfEo
podcastSpotifyId: 0CCQaWCln7rvwkkVvsyxsk
podcastAmazonUrl: https://music.amazon.com/podcasts/a221fdad-36fd-4695-a5b4-038d7b99d284/episodes/53934cd9-c521-441e-8523-8b947ed207ca/the-enterprise-software-podcast-by-nx-the-enterprise-software-podcast-by-nx-2-tine-kondo
podcastAppleUrl: https://podcasts.apple.com/us/podcast/the-enterprise-software-podcast-by-nx-2-tine-kondo/id1752704996?i=1000662764990
podcastIHeartUrl: https://www.iheart.com/podcast/269-the-enterprise-software-po-186891508/episode/the-enterprise-software-podcast-by-nx-197335640/
---
In this episode, welcome Nx Champion and Nx Expert, Tine Kondo. Our discussion highlights how Nx is poised to make an impact in the Java space.
We touch on the difficulties larger organizations face when merging PRs in a timely manner, emphasizing how a monorepo alleviates the headache of coordinating multiple PRs across various repositories, and share firsthand experiences and frustrations with traditional multi-repo setups, underscoring the benefits of a unified approach.
In particular, Nx's new plugin: [@nx/gradle](/nx-api/gradle) is of interest, and Tine provides some valuable insight on the impact this plugin can make, as well as the importance for Maven support.

View File

@ -0,0 +1,16 @@
---
title: 'Nx Enterprise Podcast Episode 3: Ahmed Elsakaan'
slug: 'ahmed-elsakaan-podcast-3'
authors: ['Zack DeRose']
tags: [podcast]
cover_image: /blog/images/2024-08-14/ep-3-ahmed.png
podcastYoutubeId: l_b6EOXqYRg
podcastSpotifyId: 4d4oE8B3y9BmECZ3P4uvDP
podcastAmazonUrl: https://music.amazon.com/podcasts/a221fdad-36fd-4695-a5b4-038d7b99d284/episodes/28209cf9-1b88-48b5-a798-7b24c843e9b1/the-enterprise-software-podcast-by-nx-the-enterprise-software-podcast-by-nx-3-ahmed-elsakaan
podcastAppleUrl: https://podcasts.apple.com/us/podcast/the-enterprise-software-podcast-by-nx-3-ahmed-elsakaan/id1752704996?i=1000665363260
podcastIHeartUrl: https://www.iheart.com/podcast/269-the-enterprise-software-po-186891508/episode/the-enterprise-software-podcast-by-nx-205664230/
---
In this episode we welcome Nx Champion and creator of [noodle](https://noodle.run) and [OrbitKit](https://orbitkit.dev/): Ahmed Elsakaan.
As a monorepo enthusiast, we explore Ahmed's thoughts on monorepos and how these tools can add value to developers - both in the space of setting up your monorepo (like Nx does) and in the space of creating reusable customizable modules (like OrbitKit is attempting).

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 KiB

View File

@ -68,6 +68,11 @@ export class BlogApi {
ogImageType: type, ogImageType: type,
filePath, filePath,
slug, slug,
podcastYoutubeId: frontmatter.podcastYoutubeId,
podcastSpotifyId: frontmatter.podcastSpotifyId,
podcastIHeartUrl: frontmatter.podcastIHeartUrl,
podcastAppleUrl: frontmatter.podcastAppleUrl,
podcastAmazonUrl: frontmatter.podcastAmazonUrl,
}; };
const isDevelopment = process.env.NODE_ENV === 'development'; const isDevelopment = process.env.NODE_ENV === 'development';
const shouldIncludePost = !frontmatter.draft || isDevelopment; const shouldIncludePost = !frontmatter.draft || isDevelopment;

View File

@ -11,8 +11,11 @@ export type BlogPostDataEntry = {
pinned?: boolean; pinned?: boolean;
filePath: string; filePath: string;
slug: string; slug: string;
ogImage: string; podcastYoutubeId?: string;
ogImageType: string; podcastSpotifyId?: string;
podcastAmazonUrl?: string;
podcastAppleUrl?: string;
podcastIHeartUrl?: string;
}; };
export type BlogAuthor = { export type BlogAuthor = {

View File

@ -4,6 +4,7 @@ import Image from 'next/image';
import { BlogAuthors } from './authors'; import { BlogAuthors } from './authors';
import { ChevronLeftIcon } from '@heroicons/react/24/outline'; import { ChevronLeftIcon } from '@heroicons/react/24/outline';
import { renderMarkdown } from '@nx/nx-dev/ui-markdoc'; import { renderMarkdown } from '@nx/nx-dev/ui-markdoc';
import { EpisodePlayer } from './episode-player';
export interface BlogDetailsProps { export interface BlogDetailsProps {
post: BlogPostDataEntry; post: BlogPostDataEntry;
@ -65,16 +66,28 @@ export function BlogDetails({ post }: BlogDetailsProps) {
{post.title} {post.title}
</h1> </h1>
</header> </header>
{post.cover_image && ( {post.podcastYoutubeId && post.podcastSpotifyId ? (
<div className="mx-auto mb-16 aspect-[1.7] w-full max-w-screen-md"> <div className="mx-auto mb-16 w-full max-w-screen-md">
<Image <EpisodePlayer
className="h-full w-full object-cover md:rounded-md" podcastYoutubeId={post.podcastYoutubeId}
src={post.cover_image} podcastSpotifyId={post.podcastSpotifyId}
alt={post.title} amazonUrl={post.podcastAmazonUrl}
width={1400} appleUrl={post.podcastAppleUrl}
height={735} iHeartUrl={post.podcastIHeartUrl}
/> />
</div> </div>
) : (
post.cover_image && (
<div className="mx-auto mb-16 aspect-[1.7] w-full max-w-screen-md">
<Image
className="h-full w-full object-cover md:rounded-md"
src={post.cover_image}
alt={post.title}
width={1400}
height={735}
/>
</div>
)
)} )}
<div className="mx-auto min-w-0 max-w-3xl flex-auto px-4 pb-24 lg:px-0 lg:pb-16"> <div className="mx-auto min-w-0 max-w-3xl flex-auto px-4 pb-24 lg:px-0 lg:pb-16">
<div className="relative"> <div className="relative">

View File

@ -0,0 +1,149 @@
'use client';
import { useState } from 'react';
import {
AmazonMusicIcon,
ApplePodcastsIcon,
IHeartRadioIcon,
SpotifyIcon,
} from '@nx/nx-dev/ui-icons';
import Link from 'next/link';
export function EpisodePlayer({
podcastYoutubeId,
podcastSpotifyId,
amazonUrl,
appleUrl,
iHeartUrl,
}: {
podcastYoutubeId: string;
podcastSpotifyId: string;
amazonUrl?: string;
appleUrl?: string;
iHeartUrl?: string;
}) {
const [viewType, setViewType] = useState<ViewMode>('audio');
return (
<div className="flex basis-2/3 flex-col items-center justify-center gap-2">
{viewType === 'audio' ? (
<>
<iframe
style={{ borderRadius: '12px' }}
src={`https://open.spotify.com/embed/episode/${podcastSpotifyId}?utm_source=generator&theme=0`}
width="100%"
height="152"
frameBorder="0"
allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
loading="lazy"
key="audio"
></iframe>
</>
) : (
<iframe
style={{ borderRadius: '12px' }}
width="100%"
height="400"
src={`https://www.youtube.com/embed/${podcastYoutubeId}?si=8rkgAzJfLfd-hxAA`}
title="YouTube video player"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerPolicy="strict-origin-when-cross-origin"
allowFullScreen
key="video"
></iframe>
)}
<div className="container my-1 flex">
<div className="basis-1/2">
{viewType === 'audio' && (
<PlatformLinks
amazonUrl={amazonUrl}
appleUrl={appleUrl}
iHeartUrl={iHeartUrl}
podcastSpotifyId={podcastSpotifyId}
/>
)}
</div>
<div className="flex basis-1/2 flex-wrap justify-end gap-6 sm:gap-4">
<button
className="flex shrink-0 items-center gap-2 text-slate-400 hover:text-slate-800 dark:text-slate-600 dark:hover:text-slate-200"
onClick={() => setViewType(getOpposite(viewType))}
>
Switch to {getOpposite(viewType) === 'audio' ? 'Audio' : 'Video'}
</button>
<Link
className="flex shrink-0 items-center gap-2 text-slate-400 hover:text-slate-800 dark:text-slate-600 dark:hover:text-slate-200"
href="/podcast"
>
More Podcasts
</Link>
</div>
</div>
</div>
);
}
export function PlatformLinks({
amazonUrl,
appleUrl,
iHeartUrl,
podcastSpotifyId,
}: {
amazonUrl?: string;
appleUrl?: string;
iHeartUrl?: string;
podcastSpotifyId: string;
}): JSX.Element {
const platforms = [
{
name: 'Amazon Music',
url: amazonUrl,
icon: AmazonMusicIcon,
},
{
name: 'Apple Podcasts',
url: appleUrl,
icon: ApplePodcastsIcon,
},
{
name: 'iHeartRadio',
url: iHeartUrl,
icon: IHeartRadioIcon,
},
{
name: 'Spotify',
url: `https://open.spotify.com/episode/${podcastSpotifyId}?si=Nqd7F40hQXugagH8oDxxpA`,
icon: SpotifyIcon,
},
];
return (
<ul className="flex flex-wrap gap-6 sm:gap-4">
{platforms
.filter((platform) => !!platform.url)
.map((platform) => {
return (
<li
key={platform.name}
className="inline-block cursor-pointer place-items-center rounded-2xl border border-slate-100 bg-white p-4 text-slate-600 transition-all hover:scale-[1.02] hover:text-slate-950 dark:border-slate-800/60 dark:bg-slate-950 dark:text-slate-400 dark:hover:text-white"
>
<a
href={platform.url}
target="_blank"
rel="noopener noreferrer"
className="flex h-full w-full items-center justify-center"
>
<platform.icon className="h-6 w-6 shrink-0" />
</a>
</li>
);
})}
</ul>
);
}
type ViewMode = 'audio' | 'video';
function getOpposite(viewMode: ViewMode): ViewMode {
if (viewMode === 'audio') return 'video';
return 'audio';
}

View File

@ -20,7 +20,7 @@ export function PodcastListItem({ podcast, episode }: PodcastListItemProps) {
prefetch={false} prefetch={false}
> >
<span className="w-1/2 flex-none text-balance text-slate-500 sm:w-8/12 dark:text-white"> <span className="w-1/2 flex-none text-balance text-slate-500 sm:w-8/12 dark:text-white">
Episode {episode}: {podcast.title} {podcast.title}
</span> </span>
<span className="hidden w-2/12 flex-none sm:inline-block"> <span className="hidden w-2/12 flex-none sm:inline-block">
<time dateTime={podcast.date}>{formattedDate}</time> <time dateTime={podcast.date}>{formattedDate}</time>