mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-03 06:12:53 +02:00
Add google youtube links in topic content
This commit is contained in:
@@ -116,7 +116,12 @@ export function CustomRoadmap(props: CustomRoadmapProps) {
|
|||||||
<>
|
<>
|
||||||
{!isEmbed && <RoadmapHeader />}
|
{!isEmbed && <RoadmapHeader />}
|
||||||
<FlowRoadmapRenderer isEmbed={isEmbed} roadmap={roadmap!} />
|
<FlowRoadmapRenderer isEmbed={isEmbed} roadmap={roadmap!} />
|
||||||
<TopicDetail isEmbed={isEmbed} canSubmitContribution={false} />
|
<TopicDetail
|
||||||
|
resourceTitle={roadmap!.title}
|
||||||
|
resourceType="roadmap"
|
||||||
|
isEmbed={isEmbed}
|
||||||
|
canSubmitContribution={false}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
19
src/components/ReactIcons/YouTubeIcon.tsx
Normal file
19
src/components/ReactIcons/YouTubeIcon.tsx
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
type YouTubeIconProps = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
export function YouTubeIcon(props: YouTubeIconProps) {
|
||||||
|
const { className } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
<path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0C.488 3.45.029 5.804 0 12c.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0C23.512 20.55 23.971 18.196 24 12c-.029-6.185-.484-8.549-4.385-8.816zM9 16V8l8 3.993L9 16z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
@@ -27,8 +27,13 @@ import { Ban, FileText, X } from 'lucide-react';
|
|||||||
import { getUrlParams } from '../../lib/browser';
|
import { getUrlParams } from '../../lib/browser';
|
||||||
import { Spinner } from '../ReactIcons/Spinner';
|
import { Spinner } from '../ReactIcons/Spinner';
|
||||||
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
|
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
|
||||||
|
import { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';
|
||||||
|
import { YouTubeIcon } from '../ReactIcons/YouTubeIcon.tsx';
|
||||||
|
|
||||||
type TopicDetailProps = {
|
type TopicDetailProps = {
|
||||||
|
resourceTitle?: string;
|
||||||
|
resourceType?: ResourceType;
|
||||||
|
|
||||||
isEmbed?: boolean;
|
isEmbed?: boolean;
|
||||||
canSubmitContribution: boolean;
|
canSubmitContribution: boolean;
|
||||||
};
|
};
|
||||||
@@ -43,7 +48,7 @@ const linkTypes: Record<AllowedLinkTypes, string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function TopicDetail(props: TopicDetailProps) {
|
export function TopicDetail(props: TopicDetailProps) {
|
||||||
const { canSubmitContribution, isEmbed = false } = props;
|
const { canSubmitContribution, isEmbed = false, resourceTitle } = props;
|
||||||
|
|
||||||
const [hasEnoughLinks, setHasEnoughLinks] = useState(false);
|
const [hasEnoughLinks, setHasEnoughLinks] = useState(false);
|
||||||
const [contributionUrl, setContributionUrl] = useState('');
|
const [contributionUrl, setContributionUrl] = useState('');
|
||||||
@@ -53,6 +58,7 @@ export function TopicDetail(props: TopicDetailProps) {
|
|||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [topicHtml, setTopicHtml] = useState('');
|
const [topicHtml, setTopicHtml] = useState('');
|
||||||
const [topicTitle, setTopicTitle] = useState('');
|
const [topicTitle, setTopicTitle] = useState('');
|
||||||
|
const [topicHtmlTitle, setTopicHtmlTitle] = useState('');
|
||||||
const [links, setLinks] = useState<RoadmapContentDocument['links']>([]);
|
const [links, setLinks] = useState<RoadmapContentDocument['links']>([]);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
@@ -168,8 +174,11 @@ export function TopicDetail(props: TopicDetailProps) {
|
|||||||
topicDom.querySelector('[data-github-url]')!;
|
topicDom.querySelector('[data-github-url]')!;
|
||||||
const contributionUrl = urlElem?.dataset?.githubUrl || '';
|
const contributionUrl = urlElem?.dataset?.githubUrl || '';
|
||||||
|
|
||||||
|
const titleElem: HTMLElement = topicDom.querySelector('h1')!;
|
||||||
|
|
||||||
setContributionUrl(contributionUrl);
|
setContributionUrl(contributionUrl);
|
||||||
setHasEnoughLinks(links.length >= 3);
|
setHasEnoughLinks(links.length >= 3);
|
||||||
|
setTopicHtmlTitle(titleElem?.textContent || '');
|
||||||
} else {
|
} else {
|
||||||
setLinks((response as RoadmapContentDocument)?.links || []);
|
setLinks((response as RoadmapContentDocument)?.links || []);
|
||||||
setTopicTitle((response as RoadmapContentDocument)?.title || '');
|
setTopicTitle((response as RoadmapContentDocument)?.title || '');
|
||||||
@@ -198,6 +207,8 @@ export function TopicDetail(props: TopicDetailProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hasContent = topicHtml?.length > 0 || links?.length > 0 || topicTitle;
|
const hasContent = topicHtml?.length > 0 || links?.length > 0 || topicTitle;
|
||||||
|
const googleSearchUrl = `https://www.google.com/search?q=${topicHtmlTitle?.toLowerCase()} guide for ${resourceTitle?.toLowerCase()}`;
|
||||||
|
const youtubeSearchUrl = `https://www.youtube.com/results?search_query=${topicHtmlTitle?.toLowerCase()} for ${resourceTitle?.toLowerCase()}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'relative z-50'}>
|
<div className={'relative z-50'}>
|
||||||
@@ -288,6 +299,33 @@ export function TopicDetail(props: TopicDetailProps) {
|
|||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{canSubmitContribution && (
|
||||||
|
<div>
|
||||||
|
<p className='text-base text-gray-700'>
|
||||||
|
Use the pre-filled search queries below to find learning
|
||||||
|
resources:
|
||||||
|
</p>
|
||||||
|
<div className="mt-3 flex gap-2">
|
||||||
|
<a
|
||||||
|
href={googleSearchUrl}
|
||||||
|
target="_blank"
|
||||||
|
className="flex items-center gap-2 rounded-md border border-gray-300 px-3 py-1.5 pl-2 text-sm hover:border-gray-700 hover:bg-gray-100"
|
||||||
|
>
|
||||||
|
<GoogleIcon className={'h-4 w-4'} />
|
||||||
|
Google
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href={youtubeSearchUrl}
|
||||||
|
target="_blank"
|
||||||
|
className="flex items-center gap-2 rounded-md border border-gray-300 px-3 py-1.5 pl-2 text-sm hover:border-gray-700 hover:bg-gray-100"
|
||||||
|
>
|
||||||
|
<YouTubeIcon className={'h-4 w-4 text-red-500'} />
|
||||||
|
YouTube
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Contribution */}
|
{/* Contribution */}
|
||||||
{canSubmitContribution && !hasEnoughLinks && contributionUrl && (
|
{canSubmitContribution && !hasEnoughLinks && contributionUrl && (
|
||||||
<div className="mt-8 flex-1 border-t">
|
<div className="mt-8 flex-1 border-t">
|
||||||
|
@@ -106,7 +106,12 @@ const ogImageUrl =
|
|||||||
description={roadmapData.briefDescription}
|
description={roadmapData.briefDescription}
|
||||||
pageUrl={`https://roadmap.sh/${roadmapId}`}
|
pageUrl={`https://roadmap.sh/${roadmapId}`}
|
||||||
/>
|
/>
|
||||||
<TopicDetail client:idle canSubmitContribution={true} />
|
<TopicDetail
|
||||||
|
resourceTitle={roadmapData.title}
|
||||||
|
resourceType='roadmap'
|
||||||
|
client:idle
|
||||||
|
canSubmitContribution={true}
|
||||||
|
/>
|
||||||
|
|
||||||
<FrameRenderer
|
<FrameRenderer
|
||||||
resourceType={'roadmap'}
|
resourceType={'roadmap'}
|
||||||
|
@@ -98,7 +98,12 @@ const ogImageUrl = getOpenGraphImageUrl({
|
|||||||
pageUrl={`https://roadmap.sh/best-practices/${bestPracticeId}`}
|
pageUrl={`https://roadmap.sh/best-practices/${bestPracticeId}`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TopicDetail client:idle canSubmitContribution={true} />
|
<TopicDetail
|
||||||
|
resourceTitle={bestPracticeData.title}
|
||||||
|
resourceType='best-practice'
|
||||||
|
client:idle
|
||||||
|
canSubmitContribution={true}
|
||||||
|
/>
|
||||||
|
|
||||||
<FrameRenderer
|
<FrameRenderer
|
||||||
resourceType={'best-practice'}
|
resourceType={'best-practice'}
|
||||||
|
Reference in New Issue
Block a user