refac
This commit is contained in:
1 parent
8a90bf6256
commit
067cf31f40
5 files changed
+73
-65
No files matched your search
@@ -372,7 +372,6 @@
|
|||||||
const node = e.node;
|
const node = e.node;
|
||||||
showMessage(node.data.message, true);
|
showMessage(node.data.message, true);
|
||||||
}}
|
}}
|
||||||
onClose={() => showControls.set(false)}
|
|
||||||
/>
|
/>
|
||||||
{:else if activeTab === 'files' && $selectedTerminalId}
|
{:else if activeTab === 'files' && $selectedTerminalId}
|
||||||
<FileNav onAttach={handleTerminalAttach} {chatId} />
|
<FileNav onAttach={handleTerminalAttach} {chatId} />
|
||||||
@@ -522,7 +521,6 @@
|
|||||||
}
|
}
|
||||||
showMessage(node.data.message, true);
|
showMessage(node.data.message, true);
|
||||||
}}
|
}}
|
||||||
onClose={() => showControls.set(false)}
|
|
||||||
/>
|
/>
|
||||||
{:else if activeTab === 'files' && $selectedTerminalId}
|
{:else if activeTab === 'files' && $selectedTerminalId}
|
||||||
<FileNav onAttach={handleTerminalAttach} overlay={dragged} {chatId} />
|
<FileNav onAttach={handleTerminalAttach} overlay={dragged} {chatId} />
|
||||||
|
|||||||
@@ -1,17 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext, createEventDispatcher, onDestroy } from 'svelte';
|
import { SvelteFlowProvider } from '@xyflow/svelte';
|
||||||
import { useSvelteFlow, useNodesInitialized, useStore, SvelteFlowProvider } from '@xyflow/svelte';
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
import View from './Overview/View.svelte';
|
import View from './Overview/View.svelte';
|
||||||
|
|
||||||
export let history;
|
export let history;
|
||||||
|
|
||||||
export let onClose;
|
|
||||||
export let onNodeClick;
|
export let onNodeClick;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SvelteFlowProvider>
|
<SvelteFlowProvider>
|
||||||
<View {history} {onClose} {onNodeClick} />
|
<View {history} {onNodeClick} />
|
||||||
</SvelteFlowProvider>
|
</SvelteFlowProvider>
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import { getContext } from 'svelte';
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
import { theme } from '$lib/stores';
|
import { theme } from '$lib/stores';
|
||||||
import {
|
import {
|
||||||
@@ -11,15 +13,16 @@
|
|||||||
BackgroundVariant,
|
BackgroundVariant,
|
||||||
ControlButton
|
ControlButton
|
||||||
} from '@xyflow/svelte';
|
} from '@xyflow/svelte';
|
||||||
import BarsArrowUp from '$lib/components/icons/BarsArrowUp.svelte';
|
|
||||||
import Bars3BottomLeft from '$lib/components/icons/Bars3BottomLeft.svelte';
|
|
||||||
import AlignVertical from '$lib/components/icons/AlignVertical.svelte';
|
import AlignVertical from '$lib/components/icons/AlignVertical.svelte';
|
||||||
import AlignHorizontal from '$lib/components/icons/AlignHorizontal.svelte';
|
import AlignHorizontal from '$lib/components/icons/AlignHorizontal.svelte';
|
||||||
|
import Pin from '$lib/components/icons/Pin.svelte';
|
||||||
|
import PinSlash from '$lib/components/icons/PinSlash.svelte';
|
||||||
|
|
||||||
export let nodes;
|
export let nodes;
|
||||||
export let nodeTypes;
|
export let nodeTypes;
|
||||||
export let edges;
|
export let edges;
|
||||||
export let setLayoutDirection;
|
export let setLayoutDirection;
|
||||||
|
export let pinned = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SvelteFlow
|
<SvelteFlow
|
||||||
@@ -43,6 +46,16 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Controls showLock={false}>
|
<Controls showLock={false}>
|
||||||
|
<ControlButton
|
||||||
|
on:click={() => (pinned = !pinned)}
|
||||||
|
title={pinned ? $i18n.t('Viewport Pinned') : $i18n.t('Viewport Unpinned')}
|
||||||
|
>
|
||||||
|
{#if pinned}
|
||||||
|
<Pin />
|
||||||
|
{:else}
|
||||||
|
<PinSlash />
|
||||||
|
{/if}
|
||||||
|
</ControlButton>
|
||||||
<ControlButton on:click={() => setLayoutDirection('vertical')} title="Vertical Layout">
|
<ControlButton on:click={() => setLayoutDirection('vertical')} title="Vertical Layout">
|
||||||
<AlignVertical className="size-4" />
|
<AlignVertical className="size-4" />
|
||||||
</ControlButton>
|
</ControlButton>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
src={`${WEBUI_API_BASE_URL}/users/${data.user.id}/profile/image`}
|
src={`${WEBUI_API_BASE_URL}/users/${data.user.id}/profile/image`}
|
||||||
className={'size-5 -translate-y-[1px] flex-shrink-0'}
|
className={'size-5 -translate-y-[1px] flex-shrink-0'}
|
||||||
/>
|
/>
|
||||||
<div class="ml-2">
|
<div class="ml-2 flex-1 min-w-0">
|
||||||
<div class=" flex justify-between items-center">
|
<div class=" flex justify-between items-center">
|
||||||
<div class="text-xs text-black dark:text-white font-normal line-clamp-1">
|
<div class="text-xs text-black dark:text-white font-normal line-clamp-1">
|
||||||
{data?.user?.name ?? 'User'}
|
{data?.user?.name ?? 'User'}
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
className={'size-5 -translate-y-[1px] flex-shrink-0'}
|
className={'size-5 -translate-y-[1px] flex-shrink-0'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="ml-2">
|
<div class="ml-2 flex-1 min-w-0">
|
||||||
<div class=" flex justify-between items-center">
|
<div class=" flex justify-between items-center">
|
||||||
<div class="text-xs text-black dark:text-white font-normal line-clamp-1">
|
<div class="text-xs text-black dark:text-white font-normal line-clamp-1">
|
||||||
{data?.model?.name ?? data?.message?.model ?? 'Assistant'}
|
{data?.model?.name ?? data?.message?.model ?? 'Assistant'}
|
||||||
|
|||||||
@@ -1,37 +1,43 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext, createEventDispatcher, onDestroy } from 'svelte';
|
|
||||||
import { useSvelteFlow, useNodesInitialized, useStore } from '@xyflow/svelte';
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
const i18n = getContext('i18n');
|
|
||||||
|
|
||||||
import { onMount, tick } from 'svelte';
|
import { onMount, tick } from 'svelte';
|
||||||
|
import {
|
||||||
|
useSvelteFlow,
|
||||||
|
useNodesInitialized,
|
||||||
|
useStore,
|
||||||
|
type Edge,
|
||||||
|
type Node
|
||||||
|
} from '@xyflow/svelte';
|
||||||
|
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
import { models, theme, user } from '$lib/stores';
|
import { models, user } from '$lib/stores';
|
||||||
|
|
||||||
import '@xyflow/svelte/dist/style.css';
|
import '@xyflow/svelte/dist/style.css';
|
||||||
|
|
||||||
import CustomNode from './Node.svelte';
|
import CustomNode from './Node.svelte';
|
||||||
import Flow from './Flow.svelte';
|
import Flow from './Flow.svelte';
|
||||||
import XMark from '../../icons/XMark.svelte';
|
|
||||||
import ArrowLeft from '../../icons/ArrowLeft.svelte';
|
|
||||||
|
|
||||||
const { width, height } = useStore();
|
const { width, height } = useStore();
|
||||||
|
|
||||||
const { fitView, getViewport } = useSvelteFlow();
|
const { fitView } = useSvelteFlow();
|
||||||
const nodesInitialized = useNodesInitialized();
|
const nodesInitialized = useNodesInitialized();
|
||||||
|
|
||||||
export let history;
|
export let history;
|
||||||
export let onClose;
|
|
||||||
export let onNodeClick;
|
export let onNodeClick;
|
||||||
|
|
||||||
let selectedMessageId = null;
|
type LayoutDirection = 'vertical' | 'horizontal';
|
||||||
|
type PositionMapEntry = {
|
||||||
|
id: string;
|
||||||
|
level: number;
|
||||||
|
position: number;
|
||||||
|
};
|
||||||
|
|
||||||
const nodes = writable([]);
|
let selectedMessageId: string | null = null;
|
||||||
const edges = writable([]);
|
let pinned = false;
|
||||||
|
|
||||||
let layoutDirection = 'vertical';
|
const nodes = writable<Node[]>([]);
|
||||||
|
const edges = writable<Edge[]>([]);
|
||||||
|
|
||||||
|
let layoutDirection: LayoutDirection = 'vertical';
|
||||||
|
|
||||||
const nodeTypes = {
|
const nodeTypes = {
|
||||||
custom: CustomNode
|
custom: CustomNode
|
||||||
@@ -41,7 +47,7 @@
|
|||||||
drawFlow(layoutDirection);
|
drawFlow(layoutDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
$: if (history && history.currentId) {
|
$: if (history && history.currentId && !pinned) {
|
||||||
focusNode();
|
focusNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,23 +61,17 @@
|
|||||||
selectedMessageId = null;
|
selectedMessageId = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const drawFlow = async (direction) => {
|
const drawFlow = async (direction: LayoutDirection) => {
|
||||||
const nodeList = [];
|
const nodeList: Node[] = [];
|
||||||
const edgeList = [];
|
const edgeList: Edge[] = [];
|
||||||
const levelOffset = direction === 'vertical' ? 150 : 300;
|
const levelOffset = direction === 'vertical' ? 150 : 300;
|
||||||
const siblingOffset = direction === 'vertical' ? 250 : 150;
|
const siblingOffset = direction === 'vertical' ? 250 : 150;
|
||||||
|
|
||||||
// Map to keep track of node positions at each level
|
// Map to keep track of node positions at each level
|
||||||
let positionMap = new Map();
|
let positionMap = new Map<string, PositionMapEntry>();
|
||||||
|
|
||||||
// Helper function to truncate labels
|
|
||||||
function createLabel(content) {
|
|
||||||
const maxLength = 100;
|
|
||||||
return content.length > maxLength ? content.substr(0, maxLength) + '...' : content;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create nodes and map children to ensure alignment in width
|
// Create nodes and map children to ensure alignment in width
|
||||||
let layerWidths = {}; // Track widths of each layer
|
let layerWidths: Record<number, number> = {}; // Track widths of each layer
|
||||||
|
|
||||||
Object.keys(history.messages).forEach((id) => {
|
Object.keys(history.messages).forEach((id) => {
|
||||||
const message = history.messages[id];
|
const message = history.messages[id];
|
||||||
@@ -125,15 +125,15 @@
|
|||||||
await nodes.set([...nodeList]);
|
await nodes.set([...nodeList]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const recurseCheckChild = (nodeId, currentId) => {
|
const recurseCheckChild = (nodeId: string, currentId: string): boolean => {
|
||||||
const node = history.messages[nodeId];
|
const node = history.messages[nodeId];
|
||||||
return (
|
return (
|
||||||
node.childrenIds &&
|
node.childrenIds &&
|
||||||
node.childrenIds.some((id) => id === currentId || recurseCheckChild(id, currentId))
|
node.childrenIds.some((id: string) => id === currentId || recurseCheckChild(id, currentId))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setLayoutDirection = (direction) => {
|
const setLayoutDirection = (direction: LayoutDirection) => {
|
||||||
layoutDirection = direction;
|
layoutDirection = direction;
|
||||||
drawFlow(layoutDirection);
|
drawFlow(layoutDirection);
|
||||||
};
|
};
|
||||||
@@ -141,33 +141,31 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
drawFlow(layoutDirection);
|
drawFlow(layoutDirection);
|
||||||
|
|
||||||
nodesInitialized.subscribe(async (initialized) => {
|
const stopNodesInitialized = nodesInitialized.subscribe(async (initialized) => {
|
||||||
if (initialized) {
|
if (initialized && !pinned) {
|
||||||
await tick();
|
await tick();
|
||||||
const res = await fitView({ nodes: [{ id: history.currentId }] });
|
await fitView({ nodes: [{ id: history.currentId }] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const stopWidth = width.subscribe((value) => {
|
||||||
width.subscribe((value) => {
|
if (value && !pinned) {
|
||||||
if (value) {
|
fitView({ nodes: [{ id: history.currentId }] });
|
||||||
// fitView();
|
}
|
||||||
|
});
|
||||||
|
const stopHeight = height.subscribe((value) => {
|
||||||
|
if (value && !pinned) {
|
||||||
fitView({ nodes: [{ id: history.currentId }] });
|
fitView({ nodes: [{ id: history.currentId }] });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
height.subscribe((value) => {
|
return () => {
|
||||||
if (value) {
|
console.log('Overview destroyed');
|
||||||
// fitView();
|
stopNodesInitialized();
|
||||||
fitView({ nodes: [{ id: history.currentId }] });
|
stopWidth();
|
||||||
}
|
stopHeight();
|
||||||
});
|
nodes.set([]);
|
||||||
});
|
edges.set([]);
|
||||||
|
};
|
||||||
onDestroy(() => {
|
|
||||||
console.log('Overview destroyed');
|
|
||||||
|
|
||||||
nodes.set([]);
|
|
||||||
edges.set([]);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -178,10 +176,14 @@
|
|||||||
{nodeTypes}
|
{nodeTypes}
|
||||||
{edges}
|
{edges}
|
||||||
{setLayoutDirection}
|
{setLayoutDirection}
|
||||||
|
bind:pinned
|
||||||
on:nodeclick={(e) => {
|
on:nodeclick={(e) => {
|
||||||
onNodeClick(e.detail);
|
onNodeClick(e.detail);
|
||||||
selectedMessageId = e.detail.node.data.message.id;
|
const clickedMessageId = e.detail.node.data.message.id as string;
|
||||||
fitView({ nodes: [{ id: selectedMessageId }] });
|
selectedMessageId = clickedMessageId;
|
||||||
|
if (!pinned) {
|
||||||
|
fitView({ nodes: [{ id: clickedMessageId }] });
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in new issue
Block a user