mirror of
https://github.com/khoaliber/khoj.git
synced 2026-03-09 05:39:12 +00:00
Simplify references section with icons in chat message
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { ArrowCircleDown, ArrowRight } from "@phosphor-icons/react";
|
import { ArrowCircleDown, ArrowRight, Code, Note } from "@phosphor-icons/react";
|
||||||
|
|
||||||
import markdownIt from "markdown-it";
|
import markdownIt from "markdown-it";
|
||||||
const md = new markdownIt({
|
const md = new markdownIt({
|
||||||
@@ -239,7 +239,7 @@ function CodeContextReferenceCard(props: CodeContextReferenceCardProps) {
|
|||||||
</div>
|
</div>
|
||||||
{(props.output_files?.length > 0 &&
|
{(props.output_files?.length > 0 &&
|
||||||
renderOutputFiles(props.output_files?.slice(0, 1), true)) || (
|
renderOutputFiles(props.output_files?.slice(0, 1), true)) || (
|
||||||
<pre className="text-xs border-t mt-1 pt-1 verflow-hidden line-clamp-10">
|
<pre className="text-xs border-t mt-1 pt-1 overflow-hidden line-clamp-10">
|
||||||
{sanitizedCodeSnippet}
|
{sanitizedCodeSnippet}
|
||||||
</pre>
|
</pre>
|
||||||
)}
|
)}
|
||||||
@@ -475,6 +475,63 @@ export function constructAllReferences(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SimpleIconProps {
|
||||||
|
type: string;
|
||||||
|
link?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function SimpleIcon(props: SimpleIconProps) {
|
||||||
|
|
||||||
|
let favicon = ``;
|
||||||
|
let domain = "unknown";
|
||||||
|
|
||||||
|
if (props.link) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let symbol = null;
|
||||||
|
|
||||||
|
const itemClasses = "!w-4 !h-4 text-muted-foreground inline-flex mr-2 rounded-lg";
|
||||||
|
|
||||||
|
switch (props.type) {
|
||||||
|
case "code":
|
||||||
|
symbol = <Code className={`${itemClasses}`} />;
|
||||||
|
break;
|
||||||
|
case "online":
|
||||||
|
symbol =
|
||||||
|
<img
|
||||||
|
src={favicon}
|
||||||
|
alt=""
|
||||||
|
className={`${itemClasses}`}
|
||||||
|
/>;
|
||||||
|
break;
|
||||||
|
case "notes":
|
||||||
|
symbol =
|
||||||
|
<Note className={`${itemClasses}`} />;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
symbol = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("symbol", symbol);
|
||||||
|
|
||||||
|
if (!symbol) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
{symbol}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export interface TeaserReferenceSectionProps {
|
export interface TeaserReferenceSectionProps {
|
||||||
notesReferenceCardData: NotesContextReferenceData[];
|
notesReferenceCardData: NotesContextReferenceData[];
|
||||||
onlineReferenceCardData: OnlineReferenceData[];
|
onlineReferenceCardData: OnlineReferenceData[];
|
||||||
@@ -483,25 +540,6 @@ export interface TeaserReferenceSectionProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function TeaserReferencesSection(props: TeaserReferenceSectionProps) {
|
export function TeaserReferencesSection(props: TeaserReferenceSectionProps) {
|
||||||
const [numTeaserSlots, setNumTeaserSlots] = useState(3);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setNumTeaserSlots(props.isMobileWidth ? 1 : 3);
|
|
||||||
}, [props.isMobileWidth]);
|
|
||||||
|
|
||||||
const codeDataToShow = props.codeReferenceCardData.slice(0, numTeaserSlots);
|
|
||||||
const notesDataToShow = props.notesReferenceCardData.slice(
|
|
||||||
0,
|
|
||||||
numTeaserSlots - codeDataToShow.length,
|
|
||||||
);
|
|
||||||
const onlineDataToShow =
|
|
||||||
notesDataToShow.length + codeDataToShow.length < numTeaserSlots
|
|
||||||
? props.onlineReferenceCardData.slice(
|
|
||||||
0,
|
|
||||||
numTeaserSlots - codeDataToShow.length - notesDataToShow.length,
|
|
||||||
)
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const shouldShowShowMoreButton =
|
const shouldShowShowMoreButton =
|
||||||
props.notesReferenceCardData.length > 0 ||
|
props.notesReferenceCardData.length > 0 ||
|
||||||
props.codeReferenceCardData.length > 0 ||
|
props.codeReferenceCardData.length > 0 ||
|
||||||
@@ -517,47 +555,20 @@ export function TeaserReferencesSection(props: TeaserReferenceSectionProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pt-0 px-4 pb-4 md:px-6">
|
<div className="pt-0 px-4 pb-4">
|
||||||
<h3 className="inline-flex items-center">
|
<h3 className="inline-flex items-center">
|
||||||
References
|
|
||||||
<p className="text-gray-400 m-2">{numReferences} sources</p>
|
<p className="text-gray-400 m-2">{numReferences} sources</p>
|
||||||
</h3>
|
<div className={`flex flex-wrap gap-2 w-auto m-2`}>
|
||||||
<div className={`flex flex-wrap gap-2 w-auto mt-2`}>
|
|
||||||
{codeDataToShow.map((code, index) => {
|
|
||||||
return (
|
|
||||||
<CodeContextReferenceCard
|
|
||||||
showFullContent={false}
|
|
||||||
{...code}
|
|
||||||
key={`code-${index}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{notesDataToShow.map((note, index) => {
|
|
||||||
return (
|
|
||||||
<NotesContextReferenceCard
|
|
||||||
showFullContent={false}
|
|
||||||
{...note}
|
|
||||||
key={`${note.title}-${index}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{onlineDataToShow.map((online, index) => {
|
|
||||||
return (
|
|
||||||
<GenericOnlineReferenceCard
|
|
||||||
showFullContent={false}
|
|
||||||
{...online}
|
|
||||||
key={`${online.title}-${index}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{shouldShowShowMoreButton && (
|
{shouldShowShowMoreButton && (
|
||||||
<ReferencePanel
|
<ReferencePanel
|
||||||
notesReferenceCardData={props.notesReferenceCardData}
|
notesReferenceCardData={props.notesReferenceCardData}
|
||||||
onlineReferenceCardData={props.onlineReferenceCardData}
|
onlineReferenceCardData={props.onlineReferenceCardData}
|
||||||
codeReferenceCardData={props.codeReferenceCardData}
|
codeReferenceCardData={props.codeReferenceCardData}
|
||||||
|
isMobileWidth={props.isMobileWidth}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -566,18 +577,52 @@ interface ReferencePanelDataProps {
|
|||||||
notesReferenceCardData: NotesContextReferenceData[];
|
notesReferenceCardData: NotesContextReferenceData[];
|
||||||
onlineReferenceCardData: OnlineReferenceData[];
|
onlineReferenceCardData: OnlineReferenceData[];
|
||||||
codeReferenceCardData: CodeReferenceData[];
|
codeReferenceCardData: CodeReferenceData[];
|
||||||
|
isMobileWidth: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ReferencePanel(props: ReferencePanelDataProps) {
|
export default function ReferencePanel(props: ReferencePanelDataProps) {
|
||||||
|
const [numTeaserSlots, setNumTeaserSlots] = useState(3);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNumTeaserSlots(props.isMobileWidth ? 1 : 3);
|
||||||
|
}, [props.isMobileWidth]);
|
||||||
|
|
||||||
if (!props.notesReferenceCardData && !props.onlineReferenceCardData) {
|
if (!props.notesReferenceCardData && !props.onlineReferenceCardData) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const codeDataToShow = props.codeReferenceCardData.slice(0, numTeaserSlots);
|
||||||
|
const notesDataToShow = props.notesReferenceCardData.slice(
|
||||||
|
0,
|
||||||
|
numTeaserSlots - codeDataToShow.length,
|
||||||
|
);
|
||||||
|
const onlineDataToShow =
|
||||||
|
notesDataToShow.length + codeDataToShow.length < numTeaserSlots
|
||||||
|
? props.onlineReferenceCardData.filter((online) => online.link).slice(
|
||||||
|
0,
|
||||||
|
numTeaserSlots - codeDataToShow.length - notesDataToShow.length,
|
||||||
|
)
|
||||||
|
: [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sheet>
|
<Sheet>
|
||||||
<SheetTrigger className="text-balance w-auto md:w-[200px] justify-start overflow-hidden break-words p-0 bg-transparent border-none text-gray-400 align-middle items-center !m-2 inline-flex">
|
<SheetTrigger className="text-balance w-auto md:w-[200px] justify-start overflow-hidden break-words p-0 bg-transparent border-none text-gray-400 align-middle items-center m-0 inline-flex">
|
||||||
View references
|
{codeDataToShow.map((code, index) => {
|
||||||
<ArrowRight className="m-1" />
|
return (
|
||||||
|
<SimpleIcon type="code" key={`code-${index}`} />
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{notesDataToShow.map((note, index) => {
|
||||||
|
return (
|
||||||
|
<SimpleIcon type="notes" key={`${note.title}-${index}`} />
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{onlineDataToShow.map((online, index) => {
|
||||||
|
return (
|
||||||
|
<SimpleIcon type="online" key={`${online.title}-${index}`} link={online.link} />
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<ArrowRight className="m-0" />
|
||||||
</SheetTrigger>
|
</SheetTrigger>
|
||||||
<SheetContent className="overflow-y-scroll">
|
<SheetContent className="overflow-y-scroll">
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
|
|||||||
Reference in New Issue
Block a user