feat/topic-chat
Kamran Ahmed 1 week ago
parent 8ae8688996
commit fb6ce28104
  1. 65
      src/components/TopicDetail/TopicDetail.tsx
  2. 125
      src/components/TopicDetail/TopicProgressButton.tsx
  3. 2
      src/data/roadmaps/frontend/content/how-does-the-internet-work@yCnn-NfSxIybUQ2iTuUGq.md

@ -14,7 +14,6 @@ import {
updateResourceProgress as updateResourceProgressApi,
} from '../../lib/resource-progress';
import { pageProgressMessage } from '../../stores/page';
import { TopicProgressButton } from './TopicProgressButton';
import { showLoginPopup } from '../../lib/popup';
import { useToast } from '../../hooks/use-toast';
import type {
@ -22,16 +21,7 @@ import type {
RoadmapContentDocument,
} from '../CustomRoadmap/CustomRoadmap';
import { markdownToHtml, sanitizeMarkdown } from '../../lib/markdown';
import {
Ban,
BookIcon,
Coins,
FileText,
HeartHandshake,
SparklesIcon,
Star,
X,
} from 'lucide-react';
import { Ban, Coins, FileText, HeartHandshake, Star, X } from 'lucide-react';
import { getUrlParams, parseUrl } from '../../lib/browser';
import { Spinner } from '../ReactIcons/Spinner';
import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';
@ -50,6 +40,7 @@ import { TopicDetailAI } from './TopicDetailAI.tsx';
import { cn } from '../../lib/classname.ts';
import type { AIChatHistoryType } from '../GenerateCourse/AICourseLessonChat.tsx';
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';
import { TopicProgressButton } from './TopicProgressButton.tsx';
type TopicDetailProps = {
resourceId?: string;
@ -405,7 +396,41 @@ export function TopicDetail(props: TopicDetailProps) {
'flex flex-col': activeTab === 'ai',
})}
>
<div className={cn('mb-6', !shouldShowAiTab && 'mb-2')}>
<div className={cn('mb-6 -mx-6 -mt-6 border-b p-2 flex items-center justify-between')}>
<div>
{!isEmbed && (
<TopicProgressButton
topicId={
topicId.indexOf('@') !== -1
? topicId.split('@')[1]
: topicId
}
resourceId={resourceId}
resourceType={resourceType}
onClose={handleClose}
/>
)}
</div>
<button
type="button"
id="close-topic"
className="flex gap-2 items-center rounded-lg bg-transparent p-1.5 text-xs uppercase tracking-wider text-gray-400 hover:bg-gray-200 hover:text-gray-900"
onClick={handleClose}
>
<X className="size-4" />
Close
</button>
</div>
<div className="flex items-center justify-between">
<div>
{shouldShowAiTab && (
<TopicDetailsTabs
activeTab={activeTab}
setActiveTab={setActiveTab}
/>
)}
</div>
{!isEmbed && (
<TopicProgressButton
topicId={
@ -418,24 +443,8 @@ export function TopicDetail(props: TopicDetailProps) {
onClose={handleClose}
/>
)}
<button
type="button"
id="close-topic"
className="absolute top-2.5 right-2.5 inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900"
onClick={handleClose}
>
<X className="h-5 w-5" />
</button>
</div>
{shouldShowAiTab && (
<TopicDetailsTabs
activeTab={activeTab}
setActiveTab={setActiveTab}
/>
)}
{activeTab === 'ai' && shouldShowAiTab && (
<TopicDetailAI
resourceId={resourceId}

@ -17,6 +17,14 @@ import { useToast } from '../../hooks/use-toast';
import { Spinner } from '../ReactIcons/Spinner';
import { ChevronDown } from 'lucide-react';
const statusColors: Record<ResourceProgressType, string> = {
done: 'bg-green-500',
learning: 'bg-yellow-500',
pending: 'bg-gray-300',
skipped: 'bg-black',
removed: '',
};
type TopicProgressButtonProps = {
topicId: string;
resourceId: string;
@ -25,14 +33,32 @@ type TopicProgressButtonProps = {
onClose: () => void;
};
const statusColors: Record<ResourceProgressType, string> = {
done: 'bg-green-500',
learning: 'bg-yellow-500',
pending: 'bg-gray-300',
skipped: 'bg-black',
removed: '',
type ProgressDropdownItemProps = {
status: ResourceProgressType;
shortcutKey: string;
label: string;
onClick: () => void;
};
function ProgressDropdownItem(props: ProgressDropdownItemProps) {
const { status, shortcutKey, label, onClick } = props;
return (
<button
className="inline-flex justify-between px-3 py-1.5 text-left text-sm text-gray-800 hover:bg-gray-100"
onClick={onClick}
>
<span>
<span
className={`mr-2 inline-block h-2 w-2 rounded-full ${statusColors[status]}`}
></span>
{label}
</span>
<span className="text-xs text-gray-500">{shortcutKey}</span>
</button>
);
}
export function TopicProgressButton(props: TopicProgressButtonProps) {
const { topicId, resourceId, resourceType, onClose } = props;
@ -197,95 +223,66 @@ export function TopicProgressButton(props: TopicProgressButtonProps) {
if (isUpdatingProgress) {
return (
<button className="inline-flex cursor-default items-center rounded-md border border-gray-300 bg-white p-1 px-2 text-sm text-black">
<Spinner className="h-4 w-4" />
<button className="inline-flex cursor-default items-center rounded-md bg-white p-1 px-2 text-sm text-black">
<Spinner isDualRing={false} className="h-4 w-4" />
<span className="ml-2">Updating Status..</span>
</button>
);
}
return (
<div className="relative inline-flex rounded-md border border-gray-300">
<span className="inline-flex cursor-default items-center p-1 px-2 text-sm text-black">
<div className="relative inline-flex">
<button
onClick={() => setShowChangeStatus(true)}
className="inline-flex cursor-pointer items-center gap-2 rounded-md p-1 px-2 text-sm text-black hover:bg-gray-100"
>
<span className="flex h-2 w-2">
<span
className={`relative inline-flex h-2 w-2 rounded-full ${statusColors[progress]}`}
></span>
</span>
<span className="ml-2 capitalize">
<span className="capitalize">
{progress === 'learning' ? 'In Progress' : progress}
</span>
</span>
<button
className="inline-flex cursor-pointer items-center rounded-tr-md rounded-br-md border-l border-l-gray-300 bg-gray-100 p-1 px-2 text-sm text-black hover:bg-gray-200"
onClick={() => setShowChangeStatus(true)}
>
<span className="mr-0.5">Update Status</span>
<ChevronDown className="h-4 w-4" />
</button>
{showChangeStatus && (
<div
className="absolute top-full right-0 mt-1 flex min-w-[160px] flex-col divide-y rounded-md border border-gray-200 bg-white shadow-md [&>button:first-child]:rounded-t-md [&>button:last-child]:rounded-b-md"
className="absolute top-full left-0 z-50 mt-1 flex min-w-[160px] flex-col divide-y rounded-md border border-gray-200 bg-white shadow-md [&>button:first-child]:rounded-t-md [&>button:last-child]:rounded-b-md"
ref={changeStatusRef!}
>
{allowMarkingDone && (
<button
className="inline-flex justify-between px-3 py-1.5 text-left text-sm text-gray-800 hover:bg-gray-100"
<ProgressDropdownItem
status="done"
shortcutKey="D"
label="Done"
onClick={() => handleUpdateResourceProgress('done')}
>
<span>
<span
className={`mr-2 inline-block h-2 w-2 rounded-full ${statusColors['done']}`}
></span>
Done
</span>
<span className="text-xs text-gray-500">D</span>
</button>
/>
)}
{allowMarkingLearning && (
<button
className="inline-flex justify-between px-3 py-1.5 text-left text-sm text-gray-800 hover:bg-gray-100"
<ProgressDropdownItem
status="learning"
shortcutKey="L"
label="In Progress"
onClick={() => handleUpdateResourceProgress('learning')}
>
<span>
<span
className={`mr-2 inline-block h-2 w-2 rounded-full ${statusColors['learning']}`}
></span>
In Progress
</span>
<span className="text-xs text-gray-500">L</span>
</button>
/>
)}
{allowMarkingPending && (
<button
className="inline-flex justify-between px-3 py-1.5 text-left text-sm text-gray-800 hover:bg-gray-100"
<ProgressDropdownItem
status="pending"
shortcutKey="R"
label="Reset"
onClick={() => handleUpdateResourceProgress('pending')}
>
<span>
<span
className={`mr-2 inline-block h-2 w-2 rounded-full ${statusColors['pending']}`}
></span>
Reset
</span>
<span className="text-xs text-gray-500">R</span>
</button>
/>
)}
{allowMarkingSkipped && (
<button
className="inline-flex justify-between px-3 py-1.5 text-left text-sm text-gray-800 hover:bg-gray-100"
<ProgressDropdownItem
status="skipped"
shortcutKey="S"
label="Skip"
onClick={() => handleUpdateResourceProgress('skipped')}
>
<span>
<span
className={`mr-2 inline-block h-2 w-2 rounded-full ${statusColors['skipped']}`}
></span>
Skip
</span>
<span className="text-xs text-gray-500">S</span>
</button>
/>
)}
</div>
)}

@ -1,6 +1,6 @@
# How Does The Internet Work
The Internet works through a global network of interconnected computers and servers, communicating via standardized protocols. Data is broken into packets and routed through various network nodes using the Internet Protocol (IP). These packets travel across different physical infrastructures, including fiber optic cables, satellites, and wireless networks. The Transmission Control Protocol (TCP) ensures reliable delivery and reassembly of packets at their destination. Domain Name System (DNS) servers translate human-readable website names into IP addresses. When you access a website, your device sends a request to the appropriate server, which responds with the requested data. This process, facilitated by routers, switches, and other networking equipment, enables the seamless exchange of information across vast distances, forming the backbone of our digital communications.
The internet is a global network that connects computers and devices so they can share information with each other. It’s how you browse websites, send emails, watch videos, and use apps. Think of it like a giant web that links everything together.
Visit the following resources to learn more:

Loading…
Cancel
Save