feature: youtube player

This commit is contained in:
Benno Tielen 2025-11-20 12:01:26 +01:00
parent 4d562eab26
commit 550fad876a
11 changed files with 7291 additions and 1 deletions

View file

@ -6,6 +6,7 @@ import { ContactformBlock } from '@/collections/blocks/Contactform'
import { GalleryBlock } from '@/collections/blocks/Gallery' import { GalleryBlock } from '@/collections/blocks/Gallery'
import { DonationBlock } from '@/collections/blocks/Donation' import { DonationBlock } from '@/collections/blocks/Donation'
import { ButtonBlock } from '@/collections/blocks/Button' import { ButtonBlock } from '@/collections/blocks/Button'
import { YoutubePlayerBlock } from '@/collections/blocks/YoutubePlayer'
export const Blog: CollectionConfig = { export const Blog: CollectionConfig = {
@ -60,6 +61,7 @@ export const Blog: CollectionConfig = {
DonationBlock, DonationBlock,
ContactformBlock, ContactformBlock,
GalleryBlock, GalleryBlock,
YoutubePlayerBlock,
ButtonBlock, ButtonBlock,
], ],
required: true, required: true,

View file

@ -7,6 +7,7 @@ import { DocumentBlock } from '@/collections/blocks/Document'
import { lexicalHTML } from '@payloadcms/richtext-lexical' import { lexicalHTML } from '@payloadcms/richtext-lexical'
import { DonationBlock } from '@/collections/blocks/Donation' import { DonationBlock } from '@/collections/blocks/Donation'
import { ButtonBlock } from '@/collections/blocks/Button' import { ButtonBlock } from '@/collections/blocks/Button'
import { YoutubePlayerBlock } from '@/collections/blocks/YoutubePlayer'
export const Groups: CollectionConfig = { export const Groups: CollectionConfig = {
slug: 'group', slug: 'group',
@ -69,6 +70,7 @@ export const Groups: CollectionConfig = {
GalleryBlock, GalleryBlock,
DocumentBlock, DocumentBlock,
DonationBlock, DonationBlock,
YoutubePlayerBlock,
ContactformBlock, ContactformBlock,
ButtonBlock ButtonBlock
] ]

View file

@ -0,0 +1,20 @@
import { Block } from 'payload'
export const YoutubePlayerBlock: Block = {
slug: 'youtube',
labels: {
singular: {
de: 'Youtube'
},
plural: {
de: 'Youtube'
}
},
fields: [
{
name: 'youtube_id',
type: 'text',
required: true
}
]
}

View file

@ -0,0 +1,15 @@
import { Meta, StoryObj } from '@storybook/react'
import { YoutubePlayer } from './YoutubePlayer'
const meta: Meta<typeof YoutubePlayer> = {
component: YoutubePlayer,
}
type Story = StoryObj<typeof YoutubePlayer>;
export default meta
export const Default: Story = {
args: {
id: "VMWnjhy2Mqo"
},
}

View file

@ -0,0 +1,16 @@
import styles from './styles.module.scss'
type YoutubePlayerProps = {
id: string
}
export const YoutubePlayer = ({id}: YoutubePlayerProps) => {
return (
<div className={styles.container}>
<iframe src={`https://www.youtube-nocookie.com/embed/${id}`}
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></iframe>
</div>
)
}

View file

@ -0,0 +1,10 @@
.container {
display: flex;
justify-content: left;
}
.container iframe {
aspect-ratio: 16 / 9;
width: 100% !important;
max-width: 560px;
}

View file

@ -7,6 +7,7 @@ import { ContactSection } from '@/compositions/ContactSection/ContactSection'
import { Gallery } from '@/components/Gallery/Gallery' import { Gallery } from '@/components/Gallery/Gallery'
import { transformGallery } from '@/utils/dto/gallery' import { transformGallery } from '@/utils/dto/gallery'
import { DonationForm } from '@/components/DonationForm/DonationForm' import { DonationForm } from '@/components/DonationForm/DonationForm'
import { YoutubePlayer } from '@/components/YoutubePlayer/YoutubePlayer'
type BlocksProps = { type BlocksProps = {
content: Blog['content']['content'] content: Blog['content']['content']
@ -65,6 +66,14 @@ export function Blocks({ content }: BlocksProps) {
</Section> </Section>
} }
if (item.blockType === "youtube") {
return <Section key={item.id} padding={"small"}>
<Container>
<YoutubePlayer id={item.youtube_id} />
</Container>
</Section>
}
if (item.blockType === "button") { if (item.blockType === "button") {
return <Section key={item.id} padding={"small"}> return <Section key={item.id} padding={"small"}>
<Container> <Container>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
CREATE TABLE "blog_blocks_youtube" (
"_order" integer NOT NULL,
"_parent_id" uuid NOT NULL,
"_path" text NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"youtube_id" varchar NOT NULL,
"block_name" varchar
);
CREATE TABLE "group_blocks_youtube" (
"_order" integer NOT NULL,
"_parent_id" uuid NOT NULL,
"_path" text NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"youtube_id" varchar NOT NULL,
"block_name" varchar
);
ALTER TABLE "announcement" ALTER COLUMN "date" SET DEFAULT '2025-11-23T15:05:28.806Z';
ALTER TABLE "calendar" ALTER COLUMN "date" SET DEFAULT '2025-11-23T15:05:28.910Z';
ALTER TABLE "classifieds" ALTER COLUMN "until" SET DEFAULT '2025-12-18T15:05:28.976Z';
ALTER TABLE "blog_blocks_youtube" ADD CONSTRAINT "blog_blocks_youtube_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."blog"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "group_blocks_youtube" ADD CONSTRAINT "group_blocks_youtube_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."group"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "blog_blocks_youtube_order_idx" ON "blog_blocks_youtube" USING btree ("_order");
CREATE INDEX "blog_blocks_youtube_parent_id_idx" ON "blog_blocks_youtube" USING btree ("_parent_id");
CREATE INDEX "blog_blocks_youtube_path_idx" ON "blog_blocks_youtube" USING btree ("_path");
CREATE INDEX "group_blocks_youtube_order_idx" ON "group_blocks_youtube" USING btree ("_order");
CREATE INDEX "group_blocks_youtube_parent_id_idx" ON "group_blocks_youtube" USING btree ("_parent_id");
CREATE INDEX "group_blocks_youtube_path_idx" ON "group_blocks_youtube" USING btree ("_path");`)
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
ALTER TABLE "blog_blocks_youtube" DISABLE ROW LEVEL SECURITY;
ALTER TABLE "group_blocks_youtube" DISABLE ROW LEVEL SECURITY;
DROP TABLE "blog_blocks_youtube" CASCADE;
DROP TABLE "group_blocks_youtube" CASCADE;
ALTER TABLE "announcement" ALTER COLUMN "date" SET DEFAULT '2025-09-21T07:52:17.724Z';
ALTER TABLE "calendar" ALTER COLUMN "date" SET DEFAULT '2025-09-21T07:52:17.817Z';
ALTER TABLE "classifieds" ALTER COLUMN "until" SET DEFAULT '2025-10-15T07:52:17.878Z';`)
}

View file

@ -12,6 +12,7 @@ import * as migration_20250827_093559_magazine from './20250827_093559_magazine'
import * as migration_20250827_105121_new_payload_version from './20250827_105121_new_payload_version'; import * as migration_20250827_105121_new_payload_version from './20250827_105121_new_payload_version';
import * as migration_20250909_075603 from './20250909_075603'; import * as migration_20250909_075603 from './20250909_075603';
import * as migration_20250915_075218 from './20250915_075218'; import * as migration_20250915_075218 from './20250915_075218';
import * as migration_20251118_150529_youtube_player from './20251118_150529_youtube_player';
export const migrations = [ export const migrations = [
{ {
@ -82,6 +83,11 @@ export const migrations = [
{ {
up: migration_20250915_075218.up, up: migration_20250915_075218.up,
down: migration_20250915_075218.down, down: migration_20250915_075218.down,
name: '20250915_075218' name: '20250915_075218',
},
{
up: migration_20251118_150529_youtube_player.up,
down: migration_20251118_150529_youtube_player.down,
name: '20251118_150529_youtube_player'
}, },
]; ];

View file

@ -386,6 +386,12 @@ export interface Blog {
blockName?: string | null; blockName?: string | null;
blockType: 'gallery'; blockType: 'gallery';
} }
| {
youtube_id: string;
id?: string | null;
blockName?: string | null;
blockType: 'youtube';
}
| { | {
text: string; text: string;
url: string; url: string;
@ -541,6 +547,12 @@ export interface Group {
blockName?: string | null; blockName?: string | null;
blockType: 'donation'; blockType: 'donation';
} }
| {
youtube_id: string;
id?: string | null;
blockName?: string | null;
blockType: 'youtube';
}
| { | {
title: string; title: string;
description: string; description: string;
@ -904,6 +916,13 @@ export interface BlogSelect<T extends boolean = true> {
id?: T; id?: T;
blockName?: T; blockName?: T;
}; };
youtube?:
| T
| {
youtube_id?: T;
id?: T;
blockName?: T;
};
button?: button?:
| T | T
| { | {
@ -1044,6 +1063,13 @@ export interface GroupSelect<T extends boolean = true> {
id?: T; id?: T;
blockName?: T; blockName?: T;
}; };
youtube?:
| T
| {
youtube_id?: T;
id?: T;
blockName?: T;
};
contactform?: contactform?:
| T | T
| { | {