Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 1 addition & 20 deletions frontend/app/src/components/graph/GraphEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import useSWR from 'swr';

export function GraphEditor ({ knowledgeBaseId }: { knowledgeBaseId: number }) {
const [query, setQuery] = useSearchParam('query', 'sample-question:What is TiDB?');
const [graphStyle, setGraphStyle] = useState<'new' | 'legacy'>('new');

const [key, fetcher] = getFetchInfo(knowledgeBaseId, query);

Expand All @@ -34,20 +33,18 @@ export function GraphEditor ({ knowledgeBaseId }: { knowledgeBaseId: number }) {
return (
<div className="p-4 space-y-4">
<SubgraphSelector knowledgeBaseId={knowledgeBaseId} query={query} onQueryChange={setQuery} />
<GraphStyleSelector style={graphStyle} onStyleChange={setGraphStyle} />
{(error != null) && <Alert variant="destructive">
<AlertTitle>Failed to fetch subgraph</AlertTitle>
<AlertDescription>{getErrorMessage(error)}</AlertDescription>
</Alert>}
<div className="w-full flex gap-4">
<div className="flex-1">
<NetworkViewer
key={`${query}-${graphStyle}`}
key={query}
className="border rounded h-auto aspect-square"
loading={isLoading}
loadingTitle={'Loading knowledge graph...'}
network={network}
useCanvasRenderer={graphStyle === 'new'}
Details={(props) => (
ref.current && createPortal(
<Editor
Expand Down Expand Up @@ -130,22 +127,6 @@ function SubgraphSelector ({ knowledgeBaseId, query, onQueryChange }: { knowledg
);
}

function GraphStyleSelector ({ style, onStyleChange }: { style: 'new' | 'legacy', onStyleChange: (style: 'new' | 'legacy') => void }) {
return (
<div>
<Select value={style} onValueChange={(value) => onStyleChange(value as 'new' | 'legacy')}>
<SelectTrigger className="w-max">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="legacy">Legacy (SVG)</SelectItem>
<SelectItem value="new">New (Canvas)</SelectItem>
</SelectContent>
</Select>
</div>
)
}

function Editor ({ knowledgeBaseId, network, target, onTargetChange, onEnterSubgraph }: NetworkViewerDetailsProps & { knowledgeBaseId: number, onEnterSubgraph: (type: string, entityId: IdType) => void }) {
if (target) {
if (target.type === 'link') {
Expand Down
18 changes: 8 additions & 10 deletions frontend/app/src/components/graph/components/NetworkCanvas.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import { useEffect, useRef, useState } from 'react';
import type { IdType, NetworkLink, NetworkNode, ReadonlyNetwork } from '../network/Network';
import { NetworkRenderer, type NetworkRendererOptions } from '../network/NetworkRenderer';
import { useEffect, useRef, useState } from 'react';

import { CanvasNetworkRenderer } from '../network/CanvasNetworkRenderer';
import type { NetworkRendererOptions } from '../network/NetworkRendererOptions';

export interface NetworkCanvasProps<Node extends NetworkNode, Link extends NetworkLink> extends NetworkRendererOptions<Node, Link> {
network: ReadonlyNetwork<Node, Link>;
target: { type: string, id: IdType } | undefined;
className?: string;
useCanvasRenderer?: boolean;
}

export function NetworkCanvas<Node extends NetworkNode, Link extends NetworkLink> ({ className, network, target, useCanvasRenderer = false, ...options }: NetworkCanvasProps<Node, Link>) {
export function NetworkCanvas<Node extends NetworkNode, Link extends NetworkLink> ({ className, network, target, ...options }: NetworkCanvasProps<Node, Link>) {
const ref = useRef<HTMLDivElement>(null);
const [renderer, setRenderer] = useState<NetworkRenderer<Node, Link> | CanvasNetworkRenderer<Node, Link>>();
const [renderer, setRenderer] = useState<CanvasNetworkRenderer<Node, Link>>();

useEffect(() => {
// Cleanup previous renderer if it exists (needed for renderer switching)
// Cleanup previous renderer if it exists
if (renderer) {
renderer.unmount();
}

const newRenderer = useCanvasRenderer
? new CanvasNetworkRenderer(network, options)
: new NetworkRenderer(network, options);
const newRenderer = new CanvasNetworkRenderer(network, options);

if (ref.current) {
newRenderer.mount(ref.current);
Expand All @@ -33,7 +31,7 @@ export function NetworkCanvas<Node extends NetworkNode, Link extends NetworkLink
newRenderer.unmount();
setRenderer(undefined);
};
}, [network, useCanvasRenderer]);
}, [network]);

useEffect(() => {
if (!renderer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { type FC, type ReactNode, useMemo, useState } from 'react';
import { NetworkCanvas } from '../components/NetworkCanvas';
import { NetworkContext } from '../components/NetworkContext';
import { BaseNetwork, type IdType } from '../network/Network';
import type { NetworkRendererOptions } from '../network/NetworkRenderer';
import type { NetworkRendererOptions } from '../network/NetworkRendererOptions';
import { type Entity, type Relationship } from '../utils';

export interface NetworkViewerProps {
Expand All @@ -13,7 +13,6 @@ export interface NetworkViewerProps {
loading: boolean;
loadingTitle: ReactNode;
Details: FC<NetworkViewerDetailsProps>;
useCanvasRenderer?: boolean;
}

export interface NetworkViewerDetailsProps {
Expand All @@ -32,7 +31,7 @@ function randomPosition (radius: number, kbSpacing: number, kbIndex: number, kbC
};
}

export function NetworkViewer ({ network, loading, loadingTitle, className, Details, useCanvasRenderer = false }: NetworkViewerProps) {
export function NetworkViewer ({ network, loading, loadingTitle, className, Details }: NetworkViewerProps) {
const [target, setTarget] = useState<{ type: string, id: IdType }>();

const knowledgeGraphIndexMap = useMemo(() => {
Expand Down Expand Up @@ -146,7 +145,6 @@ export function NetworkViewer ({ network, loading, loadingTitle, className, Deta
className={cn('w-full h-full overflow-hidden')}
network={network}
target={target}
useCanvasRenderer={useCanvasRenderer}
{...networkOptions}
/>
<Details
Expand Down
26 changes: 24 additions & 2 deletions frontend/app/src/components/graph/network/CanvasNetworkRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
import * as d3 from 'd3';
import ForceGraph from 'force-graph';

import type { IdType, NetworkLink, NetworkNode, ReadonlyNetwork } from './Network';
import type { NetworkRendererOptions, NetworkNodeView, NetworkLinkView } from './NetworkRenderer';
import type { SimulationLinkDatum, SimulationNodeDatum } from 'd3';

import ForceGraph from 'force-graph';
import type { NetworkRendererOptions } from './NetworkRendererOptions';

export interface NetworkNodeView extends SimulationNodeDatum {
id: IdType;
index: number;
radius: number;
label?: string;
details?: string;
meta?: any;
}

export interface NetworkLinkView extends SimulationLinkDatum<NetworkNodeView> {
id: IdType;
index: number;
source: NetworkNodeView;
target: NetworkNodeView;
label?: string;
details?: string;
meta?: any;
}

export class CanvasNetworkRenderer<Node extends NetworkNode, Link extends NetworkLink> {
private _el: HTMLElement | undefined;
Expand Down
Loading
Loading