Skip to content

Commit 3ae4870

Browse files
author
Hrithik-Gavankar
committed
feat(NGUI-176): add VideoPlayerWrapper component and update componentsMap
1 parent 98d9097 commit 3ae4870

File tree

3 files changed

+444
-1
lines changed

3 files changed

+444
-1
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import {
2+
Card,
3+
CardBody,
4+
CardTitle,
5+
Title,
6+
} from "@patternfly/react-core";
7+
import React from "react";
8+
9+
interface VideoPlayerProps {
10+
id?: string;
11+
title: string;
12+
video?: string | null;
13+
video_img?: string | null;
14+
className?: string;
15+
autoPlay?: boolean;
16+
controls?: boolean;
17+
width?: string | number;
18+
height?: string | number;
19+
}
20+
21+
const VideoPlayerWrapper: React.FC<VideoPlayerProps> = ({
22+
id,
23+
title,
24+
video,
25+
video_img,
26+
className,
27+
autoPlay = false,
28+
controls = true,
29+
width = "100%",
30+
height = "auto",
31+
}) => {
32+
// Extract video ID from YouTube URL for embedding
33+
const getYouTubeEmbedUrl = (url: string) => {
34+
// Match various YouTube URL formats
35+
let videoId = '';
36+
37+
// Standard YouTube URL: https://www.youtube.com/watch?v=VIDEO_ID
38+
const standardMatch = url.match(/[?&]v=([^&\s]{11})/);
39+
if (standardMatch) {
40+
videoId = standardMatch[1];
41+
} else {
42+
// Short YouTube URL: https://youtu.be/VIDEO_ID
43+
const shortMatch = url.match(/youtu\.be\/([^?\s]{11})/);
44+
if (shortMatch) {
45+
videoId = shortMatch[1];
46+
}
47+
}
48+
49+
if (videoId) {
50+
const autoPlayParam = autoPlay ? '&autoplay=1' : '';
51+
return `https://www.youtube.com/embed/${videoId}?rel=0${autoPlayParam}`;
52+
}
53+
return url;
54+
};
55+
56+
// Check if URL is a YouTube video
57+
const isYouTubeUrl = (url: string) => {
58+
return url.includes('youtube.com') || url.includes('youtu.be');
59+
};
60+
61+
const renderVideoContent = () => {
62+
if (video) {
63+
if (isYouTubeUrl(video)) {
64+
// YouTube video embedding
65+
return (
66+
<div
67+
style={{
68+
position: 'relative',
69+
paddingBottom: '56.25%', // 16:9 aspect ratio
70+
height: 0,
71+
overflow: 'hidden',
72+
maxWidth: '100%',
73+
background: '#000',
74+
borderRadius: 'var(--pf-global--BorderRadius--sm)'
75+
}}
76+
>
77+
<iframe
78+
title={title}
79+
src={getYouTubeEmbedUrl(video)}
80+
style={{
81+
position: 'absolute',
82+
top: 0,
83+
left: 0,
84+
width: '100%',
85+
height: '100%',
86+
border: 0
87+
}}
88+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
89+
referrerPolicy="strict-origin-when-cross-origin"
90+
allowFullScreen
91+
/>
92+
</div>
93+
);
94+
} else {
95+
// Direct video file
96+
return (
97+
<video
98+
src={video}
99+
controls={controls}
100+
autoPlay={autoPlay}
101+
style={{
102+
width,
103+
height,
104+
maxWidth: '100%',
105+
borderRadius: 'var(--pf-global--BorderRadius--sm)'
106+
}}
107+
title={title}
108+
>
109+
Your browser does not support the video tag.
110+
</video>
111+
);
112+
}
113+
} else if (video_img) {
114+
// Show poster image when no video URL is provided
115+
return (
116+
<div style={{ textAlign: 'center' }}>
117+
<img
118+
src={video_img}
119+
alt={title}
120+
style={{
121+
maxWidth: '100%',
122+
height: 'auto',
123+
borderRadius: 'var(--pf-global--BorderRadius--sm)',
124+
objectFit: 'cover',
125+
}}
126+
/>
127+
</div>
128+
);
129+
}
130+
131+
// Fallback when neither video nor poster image is available
132+
return (
133+
<div
134+
style={{
135+
textAlign: 'center',
136+
padding: '2rem',
137+
backgroundColor: 'var(--pf-global--BackgroundColor--200)',
138+
borderRadius: 'var(--pf-global--BorderRadius--sm)',
139+
color: 'var(--pf-global--Color--200)'
140+
}}
141+
>
142+
No video content available
143+
</div>
144+
);
145+
};
146+
147+
return (
148+
<Card
149+
id={id}
150+
className={className}
151+
style={{
152+
maxWidth: "1440px",
153+
margin: "0 auto",
154+
width: "100%"
155+
}}
156+
>
157+
<CardTitle>
158+
<Title headingLevel="h4" size="lg">
159+
{title}
160+
</Title>
161+
</CardTitle>
162+
<CardBody>
163+
{renderVideoContent()}
164+
</CardBody>
165+
</Card>
166+
);
167+
};
168+
169+
export default VideoPlayerWrapper;

src/constants/componentsMap.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import OneCardWrapper from "../components/OneCardWrapper";
22
import TableWrapper from "../components/TableWrapper";
3+
import VideoPlayerWrapper from "../components/VideoPlayerWrapper";
34

45
export const componentsMap = {
56
"one-card": OneCardWrapper,
6-
table: TableWrapper,
7+
"table": TableWrapper,
8+
"video-player": VideoPlayerWrapper,
79
};

0 commit comments

Comments
 (0)