Update MessageSources.tsx
Cards sources Doc RAG
This commit is contained in:
parent
b087f32690
commit
ec940aeada
1 changed files with 152 additions and 93 deletions
|
@ -23,21 +23,36 @@ 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">
|
||||||
{source.metadata.url === 'File' ? (
|
{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 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>
|
||||||
|
@ -51,16 +66,51 @@ const MessageSources = ({ sources }: { sources: Document[] }) => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis">
|
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis">
|
||||||
{source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')}
|
{isFile
|
||||||
|
? `Page ${source.metadata.page || 1}`
|
||||||
|
: source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</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="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>
|
||||||
|
</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>
|
</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>
|
||||||
|
);
|
||||||
|
})}
|
||||||
{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,37 +139,27 @@ 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">
|
||||||
<TransitionChild
|
<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">
|
||||||
as={Fragment}
|
<Dialog.Title className="text-lg font-medium leading-6 dark:text-white">
|
||||||
enter="ease-out duration-200"
|
|
||||||
enterFrom="opacity-0 scale-95"
|
|
||||||
enterTo="opacity-100 scale-100"
|
|
||||||
leave="ease-in duration-100"
|
|
||||||
leaveFrom="opacity-100 scale-200"
|
|
||||||
leaveTo="opacity-0 scale-95"
|
|
||||||
>
|
|
||||||
<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">
|
|
||||||
<DialogTitle className="text-lg font-medium leading-6 dark:text-white">
|
|
||||||
Sources
|
Sources
|
||||||
</DialogTitle>
|
</Dialog.Title>
|
||||||
<div className="grid grid-cols-2 gap-2 overflow-auto max-h-[300px] mt-2 pr-2">
|
<div className="grid grid-cols-2 gap-2 overflow-auto max-h-[300px] mt-2 pr-2">
|
||||||
{sources.map((source, i) => (
|
{sources.map((source, i) => {
|
||||||
<a
|
const urls = getSourceUrl(source);
|
||||||
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"
|
return (
|
||||||
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
href={source.metadata.url}
|
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"
|
||||||
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">
|
||||||
{source.metadata.url === 'File' ? (
|
{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 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>
|
||||||
|
@ -132,26 +173,44 @@ const MessageSources = ({ sources }: { sources: Document[] }) => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis">
|
<p className="text-xs text-black/50 dark:text-white/50 overflow-hidden whitespace-nowrap text-ellipsis">
|
||||||
{source.metadata.url.replace(
|
{source.metadata.isFile
|
||||||
/.+\/\/|www.|\..+/g,
|
? `Page ${source.metadata.page || 1}`
|
||||||
'',
|
: source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')}
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex flex-row items-center space-x-2">
|
||||||
|
{source.metadata.isFile && (
|
||||||
|
<a
|
||||||
|
href={urls.pdfUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-xs text-blue-500 hover:text-blue-600 transition-colors duration-200"
|
||||||
|
>
|
||||||
|
PDF
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
<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>
|
||||||
</DialogPanel>
|
</div>
|
||||||
</TransitionChild>
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Dialog.Panel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Transition>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue