Update MessageSources.tsx

Cards sources Doc RAG
This commit is contained in:
Lucas 2025-01-08 16:32:16 +01:00 committed by GitHub
parent b087f32690
commit ec940aeada
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -23,44 +23,94 @@ const MessageSources = ({ sources }: { sources: Document[] }) => {
document.body.classList.add('overflow-hidden-scrollable'); document.body.classList.add('overflow-hidden-scrollable');
}; };
const getSourceUrl = (source: Document) => {
if (source.metadata.isFile) {
// Pour les fichiers locaux, on retourne à la fois l'URL du viewer et l'URL directe du PDF
const page = source.metadata.page || 1;
return {
viewerUrl: source.metadata.url, // On utilise l'URL déjà construite
pdfUrl: `/api/uploads/${source.metadata.fileId}/content?page=${page}`
};
}
// Pour les URLs web, on retourne la même URL pour les deux
return {
viewerUrl: source.metadata.url,
pdfUrl: source.metadata.url
};
};
return ( return (
<div className="grid grid-cols-2 lg:grid-cols-4 gap-2"> <div className="grid grid-cols-2 lg:grid-cols-4 gap-2">
{sources.slice(0, 3).map((source, i) => ( {sources.slice(0, 3).map((source, i) => {
<a const urls = getSourceUrl(source);
className="bg-light-100 hover:bg-light-200 dark:bg-dark-100 dark:hover:bg-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium" const isFile = source.metadata.isFile;
key={i}
href={source.metadata.url} const CardContent = () => (
target="_blank" <>
> <p className="dark:text-white text-xs overflow-hidden whitespace-nowrap text-ellipsis">
<p className="dark:text-white text-xs overflow-hidden whitespace-nowrap text-ellipsis"> {source.metadata.title}
{source.metadata.title} </p>
</p> <div className="flex flex-row items-center justify-between">
<div className="flex flex-row items-center justify-between"> <div className="flex flex-row items-center space-x-1">
<div className="flex flex-row items-center space-x-1"> {isFile ? (
{source.metadata.url === 'File' ? ( <div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full">
<div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full"> <File size={12} className="text-white/70" />
<File size={12} className="text-white/70" /> </div>
) : (
<img
src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`}
width={16}
height={16}
alt="favicon"
className="rounded-lg h-4 w-4"
/>
)}
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis">
{isFile
? `Page ${source.metadata.page || 1}`
: source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')}
</p>
</div>
<div className="flex flex-row items-center space-x-2">
{!isFile && (
<a
href={urls.viewerUrl}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-blue-500 hover:text-blue-600 transition-colors duration-200"
onClick={(e) => e.stopPropagation()}
>
Voir
</a>
)}
<div className="flex flex-row items-center space-x-1 text-black/50 dark:text-white/50 text-xs">
<div className="bg-black/50 dark:bg-white/50 h-[4px] w-[4px] rounded-full" />
<span>{i + 1}</span>
</div> </div>
) : ( </div>
<img
src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`}
width={16}
height={16}
alt="favicon"
className="rounded-lg h-4 w-4"
/>
)}
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis">
{source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')}
</p>
</div>
<div className="flex flex-row items-center space-x-1 text-black/50 dark:text-white/50 text-xs">
<div className="bg-black/50 dark:bg-white/50 h-[4px] w-[4px] rounded-full" />
<span>{i + 1}</span>
</div> </div>
</>
);
return isFile ? (
<a
key={i}
href={urls.viewerUrl}
target="_blank"
rel="noopener noreferrer"
className="bg-light-100 hover:bg-light-200 dark:bg-dark-100 dark:hover:bg-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium"
>
<CardContent />
</a>
) : (
<div
key={i}
className="bg-light-100 hover:bg-light-200 dark:bg-dark-100 dark:hover:bg-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium"
>
<CardContent />
</div> </div>
</a> );
))} })}
{sources.length > 3 && ( {sources.length > 3 && (
<button <button
onClick={openModal} onClick={openModal}
@ -68,12 +118,13 @@ const MessageSources = ({ sources }: { sources: Document[] }) => {
> >
<div className="flex flex-row items-center space-x-1"> <div className="flex flex-row items-center space-x-1">
{sources.slice(3, 6).map((source, i) => { {sources.slice(3, 6).map((source, i) => {
return source.metadata.url === 'File' ? ( return source.metadata.isFile ? (
<div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full"> <div key={i} className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full">
<File size={12} className="text-white/70" /> <File size={12} className="text-white/70" />
</div> </div>
) : ( ) : (
<img <img
key={i}
src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`} src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`}
width={16} width={16}
height={16} height={16}
@ -88,70 +139,78 @@ const MessageSources = ({ sources }: { sources: Document[] }) => {
</p> </p>
</button> </button>
)} )}
<Transition appear show={isDialogOpen} as={Fragment}> <Dialog as="div" className="relative z-50" open={isDialogOpen} onClose={closeModal}>
<Dialog as="div" className="relative z-50" onClose={closeModal}> <div className="fixed inset-0 overflow-y-auto">
<div className="fixed inset-0 overflow-y-auto"> <div className="flex min-h-full items-center justify-center p-4 text-center">
<div className="flex min-h-full items-center justify-center p-4 text-center"> <Dialog.Panel className="w-full max-w-md transform rounded-2xl bg-light-secondary dark:bg-dark-secondary border border-light-200 dark:border-dark-200 p-6 text-left align-middle shadow-xl transition-all">
<TransitionChild <Dialog.Title className="text-lg font-medium leading-6 dark:text-white">
as={Fragment} Sources
enter="ease-out duration-200" </Dialog.Title>
enterFrom="opacity-0 scale-95" <div className="grid grid-cols-2 gap-2 overflow-auto max-h-[300px] mt-2 pr-2">
enterTo="opacity-100 scale-100" {sources.map((source, i) => {
leave="ease-in duration-100" const urls = getSourceUrl(source);
leaveFrom="opacity-100 scale-200" return (
leaveTo="opacity-0 scale-95" <div
> key={i}
<DialogPanel className="w-full max-w-md transform rounded-2xl bg-light-secondary dark:bg-dark-secondary border border-light-200 dark:border-dark-200 p-6 text-left align-middle shadow-xl transition-all"> className="bg-light-secondary hover:bg-light-200 dark:bg-dark-secondary dark:hover:bg-dark-200 border border-light-200 dark:border-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium"
<DialogTitle className="text-lg font-medium leading-6 dark:text-white"> >
Sources <p className="dark:text-white text-xs overflow-hidden whitespace-nowrap text-ellipsis">
</DialogTitle> {source.metadata.title}
<div className="grid grid-cols-2 gap-2 overflow-auto max-h-[300px] mt-2 pr-2"> </p>
{sources.map((source, i) => ( <div className="flex flex-row items-center justify-between">
<a <div className="flex flex-row items-center space-x-1">
className="bg-light-secondary hover:bg-light-200 dark:bg-dark-secondary dark:hover:bg-dark-200 border border-light-200 dark:border-dark-200 transition duration-200 rounded-lg p-3 flex flex-col space-y-2 font-medium" {source.metadata.isFile ? (
key={i} <div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full">
href={source.metadata.url} <File size={12} className="text-white/70" />
target="_blank" </div>
> ) : (
<p className="dark:text-white text-xs overflow-hidden whitespace-nowrap text-ellipsis"> <img
{source.metadata.title} src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`}
</p> width={16}
<div className="flex flex-row items-center justify-between"> height={16}
<div className="flex flex-row items-center space-x-1"> alt="favicon"
{source.metadata.url === 'File' ? ( className="rounded-lg h-4 w-4"
<div className="bg-dark-200 hover:bg-dark-100 transition duration-200 flex items-center justify-center w-6 h-6 rounded-full"> />
<File size={12} className="text-white/70" /> )}
</div> <p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis">
) : ( {source.metadata.isFile
<img ? `Page ${source.metadata.page || 1}`
src={`https://s2.googleusercontent.com/s2/favicons?domain_url=${source.metadata.url}`} : source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')}
width={16} </p>
height={16} </div>
alt="favicon" <div className="flex flex-row items-center space-x-2">
className="rounded-lg h-4 w-4" {source.metadata.isFile && (
/> <a
)} href={urls.pdfUrl}
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis"> target="_blank"
{source.metadata.url.replace( rel="noopener noreferrer"
/.+\/\/|www.|\..+/g, className="text-xs text-blue-500 hover:text-blue-600 transition-colors duration-200"
'', >
)} PDF
</p> </a>
</div> )}
<a
href={urls.viewerUrl}
target="_blank"
rel="noopener noreferrer"
className="text-xs text-blue-500 hover:text-blue-600 transition-colors duration-200"
>
{source.metadata.isFile ? 'Voir' : 'Voir'}
</a>
<div className="flex flex-row items-center space-x-1 text-black/50 dark:text-white/50 text-xs"> <div className="flex flex-row items-center space-x-1 text-black/50 dark:text-white/50 text-xs">
<div className="bg-black/50 dark:bg-white/50 h-[4px] w-[4px] rounded-full" /> <div className="bg-black/50 dark:bg-white/50 h-[4px] w-[4px] rounded-full" />
<span>{i + 1}</span> <span>{i + 1}</span>
</div> </div>
</div> </div>
</a> </div>
))} </div>
</div> );
</DialogPanel> })}
</TransitionChild> </div>
</div> </Dialog.Panel>
</div> </div>
</Dialog> </div>
</Transition> </Dialog>
</div> </div>
); );
}; };