'use client'
import { useEffect, useState } from "react";
import { ArrowRight, File } from "@phosphor-icons/react";
import markdownIt from "markdown-it";
const md = new markdownIt({
html: true,
linkify: true,
typographer: true
});
import { Context, WebPage, OnlineContextData } from "../chatMessage/chatMessage";
import { Card } from "@/components/ui/card";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import * as DomPurify from 'dompurify';
interface NotesContextReferenceData {
title: string;
content: string;
}
interface NotesContextReferenceCardProps extends NotesContextReferenceData {
showFullContent: boolean;
}
function NotesContextReferenceCard(props: NotesContextReferenceCardProps) {
const snippet = props.showFullContent ? DomPurify.sanitize(md.render(props.content)) : DomPurify.sanitize(props.content);
const [isHovering, setIsHovering] = useState(false);
return (
<>
setIsHovering(true)}
onMouseLeave={() => setIsHovering(false)}
className={`${props.showFullContent ? 'w-auto' : 'w-[200px]'} overflow-hidden break-words text-balance rounded-lg p-2 bg-muted border-none`}
>
{props.title}
{props.title}
>
)
}
export interface ReferencePanelData {
notesReferenceCardData: NotesContextReferenceData[];
onlineReferenceCardData: OnlineReferenceData[];
}
interface OnlineReferenceData {
title: string;
description: string;
link: string;
}
interface OnlineReferenceCardProps extends OnlineReferenceData {
showFullContent: boolean;
}
function GenericOnlineReferenceCard(props: OnlineReferenceCardProps) {
const [isHovering, setIsHovering] = useState(false);
if (!props.link || props.link.split(' ').length > 1) {
return null;
}
let favicon = `https://www.google.com/s2/favicons?domain=globe`;
let domain = "unknown";
try {
domain = new URL(props.link).hostname;
favicon = `https://www.google.com/s2/favicons?domain=${domain}`;
} catch (error) {
console.warn(`Error parsing domain from link: ${props.link}`);
return null;
}
const handleMouseEnter = () => {
setIsHovering(true);
}
const handleMouseLeave = () => {
setIsHovering(false);
}
return (
<>
>
)
}
export function constructAllReferences(contextData: Context[], onlineData: { [key: string]: OnlineContextData }) {
const onlineReferences: OnlineReferenceData[] = [];
const contextReferences: NotesContextReferenceData[] = [];
if (onlineData) {
let localOnlineReferences = [];
for (const [key, value] of Object.entries(onlineData)) {
if (value.answerBox) {
localOnlineReferences.push({
title: value.answerBox.title,
description: value.answerBox.answer,
link: value.answerBox.source
});
}
if (value.knowledgeGraph) {
localOnlineReferences.push({
title: value.knowledgeGraph.title,
description: value.knowledgeGraph.description,
link: value.knowledgeGraph.descriptionLink
});
}
if (value.webpages) {
// If webpages is of type Array, iterate through it and add each webpage to the localOnlineReferences array
if (value.webpages instanceof Array) {
let webPageResults = value.webpages.map((webPage) => {
return {
title: webPage.query,
description: webPage.snippet,
link: webPage.link
}
});
localOnlineReferences.push(...webPageResults);
} else {
let singleWebpage = value.webpages as WebPage;
// If webpages is an object, add the object to the localOnlineReferences array
localOnlineReferences.push({
title: singleWebpage.query,
description: singleWebpage.snippet,
link: singleWebpage.link
});
}
}
if (value.organic) {
let organicResults = value.organic.map((organicContext) => {
return {
title: organicContext.title,
description: organicContext.snippet,
link: organicContext.link
}
});
localOnlineReferences.push(...organicResults);
}
}
onlineReferences.push(...localOnlineReferences);
}
if (contextData) {
let localContextReferences = contextData.map((context) => {
if (!context.compiled) {
const fileContent = context as unknown as string;
const title = fileContent.split('\n')[0];
const content = fileContent.split('\n').slice(1).join('\n');
return {
title: title,
content: content
};
}
return {
title: context.file,
content: context.compiled
}
});
contextReferences.push(...localContextReferences);
}
return {
notesReferenceCardData: contextReferences,
onlineReferenceCardData: onlineReferences
}
}
export interface TeaserReferenceSectionProps {
notesReferenceCardData: NotesContextReferenceData[];
onlineReferenceCardData: OnlineReferenceData[];
isMobileWidth: boolean;
}
export function TeaserReferencesSection(props: TeaserReferenceSectionProps) {
const [numTeaserSlots, setNumTeaserSlots] = useState(3);
useEffect(() => {
setNumTeaserSlots(props.isMobileWidth ? 1 : 3);
}, [props.isMobileWidth]);
const notesDataToShow = props.notesReferenceCardData.slice(0, numTeaserSlots);
const onlineDataToShow = notesDataToShow.length < numTeaserSlots ? props.onlineReferenceCardData.slice(0, numTeaserSlots - notesDataToShow.length) : [];
const shouldShowShowMoreButton = props.notesReferenceCardData.length > 0 || props.onlineReferenceCardData.length > 0;
const numReferences = props.notesReferenceCardData.length + props.onlineReferenceCardData.length;
if (numReferences === 0) {
return null;
}
return (
References
{numReferences} sources
{
notesDataToShow.map((note, index) => {
return
})
}
{
onlineDataToShow.map((online, index) => {
return
})
}
{
shouldShowShowMoreButton &&
}
)
}
interface ReferencePanelDataProps {
notesReferenceCardData: NotesContextReferenceData[];
onlineReferenceCardData: OnlineReferenceData[];
}
export default function ReferencePanel(props: ReferencePanelDataProps) {
if (!props.notesReferenceCardData && !props.onlineReferenceCardData) {
return null;
}
return (
View references
References
View all references for this response
{
props.notesReferenceCardData.map((note, index) => {
return
})
}
{
props.onlineReferenceCardData.map((online, index) => {
return
})
}
);
}