mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-12 12:25:20 +00:00
feat/enh: embed citation
This commit is contained in:
parent
118549caf3
commit
f58fc753e3
9 changed files with 96 additions and 12 deletions
|
|
@ -38,7 +38,8 @@
|
||||||
toolServers,
|
toolServers,
|
||||||
functions,
|
functions,
|
||||||
selectedFolder,
|
selectedFolder,
|
||||||
pinnedChats
|
pinnedChats,
|
||||||
|
showEmbeds
|
||||||
} from '$lib/stores';
|
} from '$lib/stores';
|
||||||
import {
|
import {
|
||||||
convertMessagesToHistory,
|
convertMessagesToHistory,
|
||||||
|
|
@ -564,6 +565,7 @@
|
||||||
showCallOverlay.set(false);
|
showCallOverlay.set(false);
|
||||||
showOverview.set(false);
|
showOverview.set(false);
|
||||||
showArtifacts.set(false);
|
showArtifacts.set(false);
|
||||||
|
showEmbeds.set(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,14 @@
|
||||||
import { Pane, PaneResizer } from 'paneforge';
|
import { Pane, PaneResizer } from 'paneforge';
|
||||||
|
|
||||||
import { onDestroy, onMount, tick } from 'svelte';
|
import { onDestroy, onMount, tick } from 'svelte';
|
||||||
import { mobile, showControls, showCallOverlay, showOverview, showArtifacts } from '$lib/stores';
|
import {
|
||||||
|
mobile,
|
||||||
|
showControls,
|
||||||
|
showCallOverlay,
|
||||||
|
showOverview,
|
||||||
|
showArtifacts,
|
||||||
|
showEmbeds
|
||||||
|
} from '$lib/stores';
|
||||||
|
|
||||||
import Modal from '../common/Modal.svelte';
|
import Modal from '../common/Modal.svelte';
|
||||||
import Controls from './Controls/Controls.svelte';
|
import Controls from './Controls/Controls.svelte';
|
||||||
|
|
@ -13,6 +20,7 @@
|
||||||
import Overview from './Overview.svelte';
|
import Overview from './Overview.svelte';
|
||||||
import EllipsisVertical from '../icons/EllipsisVertical.svelte';
|
import EllipsisVertical from '../icons/EllipsisVertical.svelte';
|
||||||
import Artifacts from './Artifacts.svelte';
|
import Artifacts from './Artifacts.svelte';
|
||||||
|
import Embeds from './ChatControls/Embeds.svelte';
|
||||||
|
|
||||||
export let history;
|
export let history;
|
||||||
export let models = [];
|
export let models = [];
|
||||||
|
|
@ -134,6 +142,7 @@
|
||||||
showControls.set(false);
|
showControls.set(false);
|
||||||
showOverview.set(false);
|
showOverview.set(false);
|
||||||
showArtifacts.set(false);
|
showArtifacts.set(false);
|
||||||
|
showEmbeds.set(false);
|
||||||
|
|
||||||
if ($showCallOverlay) {
|
if ($showCallOverlay) {
|
||||||
showCallOverlay.set(false);
|
showCallOverlay.set(false);
|
||||||
|
|
@ -155,9 +164,9 @@
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class=" {$showCallOverlay || $showOverview || $showArtifacts
|
class=" {$showCallOverlay || $showOverview || $showArtifacts || $showEmbeds
|
||||||
? ' h-screen w-full'
|
? ' h-screen w-full'
|
||||||
: 'px-6 py-4'} h-full"
|
: 'px-4 py-3'} h-full"
|
||||||
>
|
>
|
||||||
{#if $showCallOverlay}
|
{#if $showCallOverlay}
|
||||||
<div
|
<div
|
||||||
|
|
@ -175,6 +184,8 @@
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{:else if $showEmbeds}
|
||||||
|
<Embeds />
|
||||||
{:else if $showArtifacts}
|
{:else if $showArtifacts}
|
||||||
<Artifacts {history} />
|
<Artifacts {history} />
|
||||||
{:else if $showOverview}
|
{:else if $showOverview}
|
||||||
|
|
@ -241,9 +252,9 @@
|
||||||
{#if $showControls}
|
{#if $showControls}
|
||||||
<div class="flex max-h-full min-h-full">
|
<div class="flex max-h-full min-h-full">
|
||||||
<div
|
<div
|
||||||
class="w-full {($showOverview || $showArtifacts) && !$showCallOverlay
|
class="w-full {($showOverview || $showArtifacts || $showEmbeds) && !$showCallOverlay
|
||||||
? ' '
|
? ' '
|
||||||
: 'px-4 py-4 bg-white dark:shadow-lg dark:bg-gray-850 '} z-40 pointer-events-auto overflow-y-auto scrollbar-hidden"
|
: 'px-4 py-3 bg-white dark:shadow-lg dark:bg-gray-850 '} z-40 pointer-events-auto overflow-y-auto scrollbar-hidden"
|
||||||
id="controls-container"
|
id="controls-container"
|
||||||
>
|
>
|
||||||
{#if $showCallOverlay}
|
{#if $showCallOverlay}
|
||||||
|
|
@ -260,6 +271,8 @@
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
{:else if $showEmbeds}
|
||||||
|
<Embeds overlay={dragged} />
|
||||||
{:else if $showArtifacts}
|
{:else if $showArtifacts}
|
||||||
<Artifacts {history} overlay={dragged} />
|
<Artifacts {history} overlay={dragged} />
|
||||||
{:else if $showOverview}
|
{:else if $showOverview}
|
||||||
|
|
|
||||||
42
src/lib/components/chat/ChatControls/Embeds.svelte
Normal file
42
src/lib/components/chat/ChatControls/Embeds.svelte
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
<script>
|
||||||
|
import { embed, showControls, showEmbeds } from '$lib/stores';
|
||||||
|
|
||||||
|
import FullHeightIframe from '$lib/components/common/FullHeightIframe.svelte';
|
||||||
|
import XMark from '$lib/components/icons/XMark.svelte';
|
||||||
|
|
||||||
|
export let overlay = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $embed}
|
||||||
|
<div class="h-full w-full">
|
||||||
|
<div
|
||||||
|
class="pointer-events-auto z-20 flex justify-between items-center py-3 px-2 font-primar text-gray-900 dark:text-white"
|
||||||
|
>
|
||||||
|
<div class="flex-1 flex items-center justify-between pl-2">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
{$embed?.title ?? 'Embedded Content'}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="self-center pointer-events-auto p-1 rounded-full bg-white dark:bg-gray-850"
|
||||||
|
on:click={() => {
|
||||||
|
console.log('hi');
|
||||||
|
showControls.set(false);
|
||||||
|
showEmbeds.set(false);
|
||||||
|
embed.set(null);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<XMark className="size-3.5 text-gray-900 dark:text-white" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class=" w-full h-full relative">
|
||||||
|
{#if overlay}
|
||||||
|
<div class=" absolute top-0 left-0 right-0 bottom-0 z-10"></div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<FullHeightIframe src={$embed?.url} iframeClassName="w-full h-full" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import CitationModal from './Citations/CitationModal.svelte';
|
import CitationModal from './Citations/CitationModal.svelte';
|
||||||
|
import { embed, showControls, showEmbeds } from '$lib/stores';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
|
|
@ -21,9 +22,25 @@
|
||||||
export const showSourceModal = (sourceIdx) => {
|
export const showSourceModal = (sourceIdx) => {
|
||||||
if (citations[sourceIdx]) {
|
if (citations[sourceIdx]) {
|
||||||
console.log('Showing citation modal for:', citations[sourceIdx]);
|
console.log('Showing citation modal for:', citations[sourceIdx]);
|
||||||
|
|
||||||
|
if (citations[sourceIdx]?.source?.embed_url) {
|
||||||
|
const embedUrl = citations[sourceIdx].source.embed_url;
|
||||||
|
if (embedUrl) {
|
||||||
|
showControls.set(true);
|
||||||
|
showEmbeds.set(true);
|
||||||
|
embed.set({
|
||||||
|
title: citations[sourceIdx]?.source?.name || 'Embedded Content',
|
||||||
|
url: embedUrl
|
||||||
|
});
|
||||||
|
} else {
|
||||||
selectedCitation = citations[sourceIdx];
|
selectedCitation = citations[sourceIdx];
|
||||||
showCitationModal = true;
|
showCitationModal = true;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
selectedCitation = citations[sourceIdx];
|
||||||
|
showCitationModal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function calculateShowRelevance(sources: any[]) {
|
function calculateShowRelevance(sources: any[]) {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
settings,
|
settings,
|
||||||
showArtifacts,
|
showArtifacts,
|
||||||
showControls,
|
showControls,
|
||||||
|
showEmbeds,
|
||||||
showOverview
|
showOverview
|
||||||
} from '$lib/stores';
|
} from '$lib/stores';
|
||||||
import FloatingButtons from '../ContentRenderer/FloatingButtons.svelte';
|
import FloatingButtons from '../ContentRenderer/FloatingButtons.svelte';
|
||||||
|
|
@ -194,6 +195,7 @@
|
||||||
await showControls.set(true);
|
await showControls.set(true);
|
||||||
await showArtifacts.set(true);
|
await showArtifacts.set(true);
|
||||||
await showOverview.set(false);
|
await showOverview.set(false);
|
||||||
|
await showEmbeds.set(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full h-full relative">
|
<div class="w-full h-full relative">
|
||||||
<div class=" absolute z-50 w-full flex justify-between dark:text-gray-100 px-4 py-3.5">
|
<div class=" absolute z-50 w-full flex justify-between dark:text-gray-100 px-4 py-3">
|
||||||
<div class="flex items-center gap-2.5">
|
<div class="flex items-center gap-2.5">
|
||||||
<button
|
<button
|
||||||
class="self-center p-0.5"
|
class="self-center p-0.5"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
export let title = 'Embedded Content';
|
export let title = 'Embedded Content';
|
||||||
export let initialHeight: number | null = null; // initial height in px, null = auto
|
export let initialHeight: number | null = null; // initial height in px, null = auto
|
||||||
|
|
||||||
|
export let iframeClassName = 'w-full rounded-2xl';
|
||||||
|
|
||||||
export let args = null;
|
export let args = null;
|
||||||
|
|
||||||
export let allowScripts = true;
|
export let allowScripts = true;
|
||||||
|
|
@ -174,7 +176,7 @@ window.Chart = parent.Chart; // Chart previously assigned on parent
|
||||||
bind:this={iframe}
|
bind:this={iframe}
|
||||||
srcdoc={iframeDoc}
|
srcdoc={iframeDoc}
|
||||||
{title}
|
{title}
|
||||||
class="w-full rounded-2xl"
|
class={iframeClassName}
|
||||||
style={`${initialHeight ? `height:${initialHeight}px;` : ''}`}
|
style={`${initialHeight ? `height:${initialHeight}px;` : ''}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
|
|
@ -187,7 +189,7 @@ window.Chart = parent.Chart; // Chart previously assigned on parent
|
||||||
bind:this={iframe}
|
bind:this={iframe}
|
||||||
src={iframeSrc}
|
src={iframeSrc}
|
||||||
{title}
|
{title}
|
||||||
class="w-full rounded-2xl"
|
class={iframeClassName}
|
||||||
style={`${initialHeight ? `height:${initialHeight}px;` : ''}`}
|
style={`${initialHeight ? `height:${initialHeight}px;` : ''}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@
|
||||||
theme,
|
theme,
|
||||||
user,
|
user,
|
||||||
settings,
|
settings,
|
||||||
folders
|
folders,
|
||||||
|
showEmbeds
|
||||||
} from '$lib/stores';
|
} from '$lib/stores';
|
||||||
import { flyAndScale } from '$lib/utils/transitions';
|
import { flyAndScale } from '$lib/utils/transitions';
|
||||||
import { getChatById } from '$lib/apis/chats';
|
import { getChatById } from '$lib/apis/chats';
|
||||||
|
|
@ -319,6 +320,7 @@
|
||||||
await showControls.set(true);
|
await showControls.set(true);
|
||||||
await showOverview.set(false);
|
await showOverview.set(false);
|
||||||
await showArtifacts.set(false);
|
await showArtifacts.set(false);
|
||||||
|
await showEmbeds.set(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AdjustmentsHorizontal className=" size-4" strokeWidth="1.5" />
|
<AdjustmentsHorizontal className=" size-4" strokeWidth="1.5" />
|
||||||
|
|
@ -333,6 +335,7 @@
|
||||||
await showControls.set(true);
|
await showControls.set(true);
|
||||||
await showOverview.set(true);
|
await showOverview.set(true);
|
||||||
await showArtifacts.set(false);
|
await showArtifacts.set(false);
|
||||||
|
await showEmbeds.set(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Map className=" size-4" strokeWidth="1.5" />
|
<Map className=" size-4" strokeWidth="1.5" />
|
||||||
|
|
@ -346,6 +349,7 @@
|
||||||
await showControls.set(true);
|
await showControls.set(true);
|
||||||
await showArtifacts.set(true);
|
await showArtifacts.set(true);
|
||||||
await showOverview.set(false);
|
await showOverview.set(false);
|
||||||
|
await showEmbeds.set(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Cube className=" size-4" strokeWidth="1.5" />
|
<Cube className=" size-4" strokeWidth="1.5" />
|
||||||
|
|
|
||||||
|
|
@ -75,10 +75,12 @@ export const showArchivedChats = writable(false);
|
||||||
export const showChangelog = writable(false);
|
export const showChangelog = writable(false);
|
||||||
|
|
||||||
export const showControls = writable(false);
|
export const showControls = writable(false);
|
||||||
|
export const showEmbeds = writable(false);
|
||||||
export const showOverview = writable(false);
|
export const showOverview = writable(false);
|
||||||
export const showArtifacts = writable(false);
|
export const showArtifacts = writable(false);
|
||||||
export const showCallOverlay = writable(false);
|
export const showCallOverlay = writable(false);
|
||||||
|
|
||||||
|
export const embed = writable(null);
|
||||||
export const artifactCode = writable(null);
|
export const artifactCode = writable(null);
|
||||||
|
|
||||||
export const temporaryChatEnabled = writable(false);
|
export const temporaryChatEnabled = writable(false);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue