2024-08-18 18:59:59 +00:00
|
|
|
<script lang="ts">
|
2024-10-07 19:04:06 +00:00
|
|
|
import { getContext } from 'svelte';
|
2025-09-12 09:49:53 +00:00
|
|
|
import CitationModal from './Citations/CitationModal.svelte';
|
2025-09-29 03:15:47 +00:00
|
|
|
import { embed, showControls, showEmbeds } from '$lib/stores';
|
2024-10-07 19:04:06 +00:00
|
|
|
|
|
|
|
|
const i18n = getContext('i18n');
|
2024-08-18 18:59:59 +00:00
|
|
|
|
2025-02-19 08:35:01 +00:00
|
|
|
export let id = '';
|
2024-11-22 03:46:09 +00:00
|
|
|
export let sources = [];
|
2025-10-02 16:48:56 +00:00
|
|
|
export let readOnly = false;
|
2024-08-18 18:59:59 +00:00
|
|
|
|
2024-11-22 03:46:09 +00:00
|
|
|
let citations = [];
|
2024-10-12 13:18:56 +00:00
|
|
|
let showPercentage = false;
|
2024-10-14 09:18:13 +00:00
|
|
|
let showRelevance = true;
|
2024-08-18 18:59:59 +00:00
|
|
|
|
2025-09-09 13:36:18 +00:00
|
|
|
let citationModal = null;
|
2025-09-12 09:49:53 +00:00
|
|
|
|
|
|
|
|
let showCitations = false;
|
2024-10-07 19:04:06 +00:00
|
|
|
let showCitationModal = false;
|
2025-09-12 09:49:53 +00:00
|
|
|
|
2024-10-12 13:18:56 +00:00
|
|
|
let selectedCitation: any = null;
|
2024-10-07 19:04:06 +00:00
|
|
|
|
2025-08-14 10:33:49 +00:00
|
|
|
export const showSourceModal = (sourceIdx) => {
|
|
|
|
|
if (citations[sourceIdx]) {
|
2025-09-09 13:36:18 +00:00
|
|
|
console.log('Showing citation modal for:', citations[sourceIdx]);
|
2025-09-29 03:15:47 +00:00
|
|
|
|
|
|
|
|
if (citations[sourceIdx]?.source?.embed_url) {
|
|
|
|
|
const embedUrl = citations[sourceIdx].source.embed_url;
|
|
|
|
|
if (embedUrl) {
|
2025-10-02 16:48:56 +00:00
|
|
|
if (readOnly) {
|
|
|
|
|
// Open in new tab if readOnly
|
|
|
|
|
window.open(embedUrl, '_blank');
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
showControls.set(true);
|
|
|
|
|
showEmbeds.set(true);
|
|
|
|
|
embed.set({
|
|
|
|
|
title: citations[sourceIdx]?.source?.name || 'Embedded Content',
|
|
|
|
|
url: embedUrl
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-09-29 03:15:47 +00:00
|
|
|
} else {
|
|
|
|
|
selectedCitation = citations[sourceIdx];
|
|
|
|
|
showCitationModal = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
selectedCitation = citations[sourceIdx];
|
|
|
|
|
showCitationModal = true;
|
|
|
|
|
}
|
2025-08-14 10:33:49 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-22 03:46:09 +00:00
|
|
|
function calculateShowRelevance(sources: any[]) {
|
|
|
|
|
const distances = sources.flatMap((citation) => citation.distances ?? []);
|
2024-10-14 09:18:13 +00:00
|
|
|
const inRange = distances.filter((d) => d !== undefined && d >= -1 && d <= 1).length;
|
|
|
|
|
const outOfRange = distances.filter((d) => d !== undefined && (d < -1 || d > 1)).length;
|
|
|
|
|
|
|
|
|
|
if (distances.length === 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
(inRange === distances.length - 1 && outOfRange === 1) ||
|
|
|
|
|
(outOfRange === distances.length - 1 && inRange === 1)
|
|
|
|
|
) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-22 03:46:09 +00:00
|
|
|
function shouldShowPercentage(sources: any[]) {
|
|
|
|
|
const distances = sources.flatMap((citation) => citation.distances ?? []);
|
2024-10-14 09:18:13 +00:00
|
|
|
return distances.every((d) => d !== undefined && d >= -1 && d <= 1);
|
2024-10-12 13:18:56 +00:00
|
|
|
}
|
2024-08-18 18:59:59 +00:00
|
|
|
|
2024-10-12 13:18:56 +00:00
|
|
|
$: {
|
2024-11-22 03:46:09 +00:00
|
|
|
citations = sources.reduce((acc, source) => {
|
|
|
|
|
if (Object.keys(source).length === 0) {
|
2024-11-22 02:26:38 +00:00
|
|
|
return acc;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-27 23:41:25 +00:00
|
|
|
source?.document?.forEach((document, index) => {
|
|
|
|
|
const metadata = source?.metadata?.[index];
|
|
|
|
|
const distance = source?.distances?.[index];
|
2024-11-22 03:46:09 +00:00
|
|
|
|
|
|
|
|
// Within the same citation there could be multiple documents
|
2025-02-26 23:42:19 +00:00
|
|
|
const id = metadata?.source ?? source?.source?.id ?? 'N/A';
|
2024-11-22 03:46:09 +00:00
|
|
|
let _source = source?.source;
|
2024-08-18 18:59:59 +00:00
|
|
|
|
2024-10-12 13:18:56 +00:00
|
|
|
if (metadata?.name) {
|
2024-11-22 03:46:09 +00:00
|
|
|
_source = { ..._source, name: metadata.name };
|
2024-10-12 13:18:56 +00:00
|
|
|
}
|
2024-08-18 18:59:59 +00:00
|
|
|
|
2024-10-12 13:18:56 +00:00
|
|
|
if (id.startsWith('http://') || id.startsWith('https://')) {
|
2024-11-22 03:46:09 +00:00
|
|
|
_source = { ..._source, name: id, url: id };
|
2024-10-12 13:18:56 +00:00
|
|
|
}
|
2024-08-18 18:59:59 +00:00
|
|
|
|
2024-10-12 13:18:56 +00:00
|
|
|
const existingSource = acc.find((item) => item.id === id);
|
|
|
|
|
|
|
|
|
|
if (existingSource) {
|
|
|
|
|
existingSource.document.push(document);
|
|
|
|
|
existingSource.metadata.push(metadata);
|
|
|
|
|
if (distance !== undefined) existingSource.distances.push(distance);
|
|
|
|
|
} else {
|
|
|
|
|
acc.push({
|
|
|
|
|
id: id,
|
2024-11-22 03:46:09 +00:00
|
|
|
source: _source,
|
2024-10-12 13:18:56 +00:00
|
|
|
document: [document],
|
|
|
|
|
metadata: metadata ? [metadata] : [],
|
2025-10-24 12:53:51 +00:00
|
|
|
distances: distance !== undefined ? [distance] : []
|
2024-10-12 13:18:56 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
2025-08-27 23:41:25 +00:00
|
|
|
|
2024-10-12 13:18:56 +00:00
|
|
|
return acc;
|
|
|
|
|
}, []);
|
2025-04-17 14:27:22 +00:00
|
|
|
console.log('citations', citations);
|
2024-10-12 13:18:56 +00:00
|
|
|
|
2024-11-22 03:46:09 +00:00
|
|
|
showRelevance = calculateShowRelevance(citations);
|
|
|
|
|
showPercentage = shouldShowPercentage(citations);
|
2024-10-12 13:18:56 +00:00
|
|
|
}
|
2025-09-12 09:49:53 +00:00
|
|
|
|
|
|
|
|
const decodeString = (str: string) => {
|
|
|
|
|
try {
|
|
|
|
|
return decodeURIComponent(str);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
};
|
2024-09-12 06:06:02 +00:00
|
|
|
</script>
|
|
|
|
|
|
2025-09-12 09:49:53 +00:00
|
|
|
<CitationModal
|
2025-09-09 13:36:18 +00:00
|
|
|
bind:show={showCitationModal}
|
2025-09-12 09:49:53 +00:00
|
|
|
citation={selectedCitation}
|
2025-09-09 13:36:18 +00:00
|
|
|
{showPercentage}
|
|
|
|
|
{showRelevance}
|
|
|
|
|
/>
|
2024-09-12 06:06:02 +00:00
|
|
|
|
2024-11-22 03:46:09 +00:00
|
|
|
{#if citations.length > 0}
|
2025-09-09 13:27:38 +00:00
|
|
|
{@const urlCitations = citations.filter((c) => c?.source?.name?.startsWith('http'))}
|
|
|
|
|
<div class=" py-1 -mx-0.5 w-full flex gap-1 items-center flex-wrap">
|
|
|
|
|
<button
|
|
|
|
|
class="text-xs font-medium text-gray-600 dark:text-gray-300 px-3.5 h-8 rounded-full hover:bg-gray-100 dark:hover:bg-gray-800 transition flex items-center gap-1 border border-gray-50 dark:border-gray-850"
|
|
|
|
|
on:click={() => {
|
2025-09-12 09:49:53 +00:00
|
|
|
showCitations = !showCitations;
|
2025-09-09 13:27:38 +00:00
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{#if urlCitations.length > 0}
|
|
|
|
|
<div class="flex -space-x-1 items-center">
|
|
|
|
|
{#each urlCitations.slice(0, 3) as citation, idx}
|
|
|
|
|
<img
|
|
|
|
|
src="https://www.google.com/s2/favicons?sz=32&domain={citation.source.name}"
|
|
|
|
|
alt="favicon"
|
|
|
|
|
class="size-4 rounded-full shrink-0 border border-white dark:border-gray-850 bg-white dark:bg-gray-900"
|
|
|
|
|
/>
|
|
|
|
|
{/each}
|
2024-10-07 19:04:06 +00:00
|
|
|
</div>
|
2025-09-09 13:27:38 +00:00
|
|
|
{/if}
|
|
|
|
|
<div>
|
|
|
|
|
{#if citations.length === 1}
|
|
|
|
|
{$i18n.t('1 Source')}
|
|
|
|
|
{:else}
|
|
|
|
|
{$i18n.t('{{COUNT}} Sources', {
|
|
|
|
|
COUNT: citations.length
|
|
|
|
|
})}
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
2024-09-12 06:06:02 +00:00
|
|
|
</div>
|
|
|
|
|
{/if}
|
2025-09-12 09:49:53 +00:00
|
|
|
|
|
|
|
|
{#if showCitations}
|
|
|
|
|
<div class="py-1.5">
|
|
|
|
|
<div class="text-xs gap-2 flex flex-col">
|
|
|
|
|
{#each citations as citation, idx}
|
|
|
|
|
<button
|
|
|
|
|
id={`source-${id}-${idx + 1}`}
|
2025-09-15 21:39:09 +00:00
|
|
|
class="no-toggle outline-hidden flex dark:text-gray-300 bg-transparent text-gray-600 rounded-xl gap-1.5 items-center"
|
2025-09-12 09:49:53 +00:00
|
|
|
on:click={() => {
|
|
|
|
|
showCitationModal = true;
|
|
|
|
|
selectedCitation = citation;
|
|
|
|
|
}}
|
|
|
|
|
>
|
2025-09-12 22:10:41 +00:00
|
|
|
<div class=" font-medium bg-gray-50 dark:bg-gray-850 rounded-md px-1">
|
2025-09-12 09:49:53 +00:00
|
|
|
{idx + 1}
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="flex-1 truncate hover:text-black dark:text-white/60 dark:hover:text-white transition text-left"
|
|
|
|
|
>
|
|
|
|
|
{decodeString(citation.source.name)}
|
|
|
|
|
</div>
|
|
|
|
|
</button>
|
|
|
|
|
{/each}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{/if}
|