Skip to content

Commit

Permalink
Merge branch 'main' into default-query
Browse files Browse the repository at this point in the history
  • Loading branch information
AviAvni authored Apr 4, 2024
2 parents 6a66102 + d76e62b commit 357cdb6
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 133 deletions.
39 changes: 22 additions & 17 deletions app/graph/DataPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";

export default function DataPanel({node}: {node: Node}) {
export default function DataPanel({ node }: { node: Node }) {
return (
<Table>
<TableHeader>
Expand All @@ -12,25 +12,30 @@ export default function DataPanel({node}: {node: Node}) {
</TableHeader>
<TableBody>
{
Object.entries(node).map((row, index) => (
Object.entries(node).filter((row) => Object.values(row)[0] !== "category" && Object.values(row)[0] !== "color").map((row, index) => (
// eslint-disable-next-line react/no-array-index-key
<TableRow key={index}>
{
Object.values(row).map((cell, cellIndex) => (
// eslint-disable-next-line react/no-array-index-key
<TableCell key={cellIndex}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger className="max-w-96 truncate">
{JSON.stringify(cell)}
</TooltipTrigger>
<TooltipContent>
<p>{JSON.stringify(cell)}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</TableCell>
))
Object.values(row).map((cell, cellIndex) => {

const strCell = JSON.stringify(cell)
const text = cellIndex === 1 ? JSON.parse(strCell) : strCell
return (
// eslint-disable-next-line react/no-array-index-key
<TableCell key={cellIndex}>
<TooltipProvider>
<Tooltip>
<TooltipTrigger className="max-w-96 truncate">
{text}
</TooltipTrigger>
<TooltipContent>
<p>{text}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</TableCell>
)
})
}
</TableRow>
))
Expand Down
2 changes: 1 addition & 1 deletion app/graph/GraphView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ const GraphView = forwardRef(({ graph, darkmode }: GraphViewProps, ref) => {
setSelectedNode(node);
dataPanel.current?.expand();
}

return (
<ResizablePanelGroup direction="horizontal">
<ResizablePanel className="h-full flex flex-col">
Expand Down
189 changes: 104 additions & 85 deletions app/graph/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function nodeSafeKey(key: string): string {
const index = NODE_RESERVED_KEYS.indexOf(key);
if (index === -1) {
return key;
}
}
return NODE_ALTERNATIVE_RESERVED_KEYS[index];
}

Expand All @@ -42,17 +42,17 @@ function edgeSafeKey(key: string): string {
const index = EDGE_RESERVED_KEYS.indexOf(key);
if (index === -1) {
return key;
}
}
return EDGE_ALTERNATIVE_RESERVED_KEYS[index];
}

export function getCategoryColorName(index: number): string {
const colorIndex = index<COLORS_ORDER.length ? index : 0
const colorIndex = index < COLORS_ORDER.length ? index : 0
return COLORS_ORDER[colorIndex]
}

function getCategoryColorValue(index=0): string {
const colorIndex = index<COLORS_ORDER.length ? index : 0
function getCategoryColorValue(index = 0): string {
const colorIndex = index < COLORS_ORDER.length ? index : 0
const colorName = COLORS_ORDER[colorIndex]

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -121,7 +121,7 @@ export class Graph {
get Data(): any[] {
return this.data;
}

public static empty(): Graph {
return new Graph("", [], [], new Map<string, Category>(), new Map<number, NodeDataDefinition>(), new Map<number, EdgeDataDefinition>())
}
Expand All @@ -134,6 +134,92 @@ export class Graph {
return graph
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private extendNode(cell: any, newElements: ElementDefinition[]) {
// check if category already exists in categories
let category = this.categoriesMap.get(cell.labels[0])
if (!category) {
category = { name: cell.labels[0], index: this.categoriesMap.size, show: true }
this.categoriesMap.set(category.name, category)
this.categories.push(category)
}

// check if node already exists in nodes or fake node was created
const currentNode = this.nodesMap.get(cell.id)
if (!currentNode) {
const node: NodeDataDefinition = {
id: cell.id.toString(),
name: cell.id.toString(),
category: category.name,
color: getCategoryColorValue(category.index)
}
Object.entries(cell.properties).forEach(([key, value]) => {
node[nodeSafeKey(key)] = value as string;
});
this.nodesMap.set(cell.id, node)
this.elements.push({ data: node })
newElements.push({ data: node })
} else if (currentNode.category === "") {
// set values in a fake node
currentNode.id = cell.id.toString();
currentNode.name = cell.id.toString();
currentNode.category = category.name;
currentNode.color = getCategoryColorValue(category.index)
Object.entries(cell.properties).forEach(([key, value]) => {
currentNode[nodeSafeKey(key)] = value as string;
});
newElements.push({ data: currentNode })
}
return newElements
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private extendEdge(cell: any, newElements: ElementDefinition[]) {
const currentEdge = this.edgesMap.get(cell.id)
if (!currentEdge) {
const sourceId = cell.sourceId.toString();
const destinationId = cell.destinationId.toString()

const edge: EdgeDataDefinition = { source: sourceId, target: destinationId, label: cell.relationshipType }
Object.entries(cell.properties).forEach(([key, value]) => {
edge[edgeSafeKey(key)] = value as string;
});
this.edgesMap.set(cell.id, edge)
this.elements.push({ data: edge })
newElements.push({ data: edge })

// creates a fakeS node for the source and target
let source = this.nodesMap.get(cell.sourceId)
if (!source) {
source = {
id: cell.sourceId.toString(),
name: cell.sourceId.toString(),
value: "",
category: "",
color: getCategoryColorValue()
}
this.nodesMap.set(cell.sourceId, source)
this.elements.push({ data: source })
newElements.push({ data: source })
}

let destination = this.nodesMap.get(cell.destinationId)
if (!destination) {
destination = {
id: cell.destinationId.toString(),
name: cell.destinationId.toString(),
value: "",
category: "",
color: getCategoryColorValue()
}
this.nodesMap.set(cell.destinationId, destination)
this.elements.push({ data: destination })
newElements.push({ data: destination })
}
}
return newElements
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public extend(results: any): ElementDefinition[] {

Expand All @@ -151,86 +237,19 @@ export class Graph {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Object.values(row).forEach((cell: any) => {
if (cell instanceof Object) {
if (cell.relationshipType) {

const currentEdge = this.edgesMap.get(cell.id)
if (!currentEdge) {
const sourceId = cell.sourceId.toString();
const destinationId = cell.destinationId.toString()

const edge: EdgeDataDefinition = { source: sourceId, target: destinationId, label: cell.relationshipType }
Object.entries(cell.properties).forEach(([key, value]) => {
edge[edgeSafeKey(key)] = value as string;
});
this.edgesMap.set(cell.id, edge)
this.elements.push({data:edge})
newElements.push({data:edge})

// creates a fakeS node for the source and target
let source = this.nodesMap.get(cell.sourceId)
if (!source) {
source = {
id: cell.sourceId.toString(),
name: cell.sourceId.toString(),
value: "",
category: "",
color: getCategoryColorValue()
}
this.nodesMap.set(cell.sourceId, source)
this.elements.push({data:source})
newElements.push({data:source})
}

let destination = this.nodesMap.get(cell.destinationId)
if (!destination) {
destination = {
id: cell.destinationId.toString(),
name: cell.destinationId.toString(),
value: "",
category: "",
color: getCategoryColorValue()
}
this.nodesMap.set(cell.destinationId, destination)
this.elements.push({data:destination})
newElements.push({data:destination})
}
}
if (cell.nodes) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cell.nodes.forEach((node: any) => {
this.extendNode(node, newElements)
})
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cell.edges.forEach((edge: any) => {
this.extendEdge(edge, newElements)
})
} else if (cell.relationshipType) {
this.extendEdge(cell, newElements)
} else if (cell.labels) {

// check if category already exists in categories
let category = this.categoriesMap.get(cell.labels[0])
if (!category) {
category = { name: cell.labels[0], index: this.categoriesMap.size, show: true }
this.categoriesMap.set(category.name, category)
this.categories.push(category)
}

// check if node already exists in nodes or fake node was created
const currentNode = this.nodesMap.get(cell.id)
if (!currentNode) {
const node: NodeDataDefinition = {
id: cell.id.toString(),
name: cell.id.toString(),
category: category.name,
color: getCategoryColorValue(category.index)
}
Object.entries(cell.properties).forEach(([key, value]) => {
node[nodeSafeKey(key)] = value as string;
});
this.nodesMap.set(cell.id, node)
this.elements.push({data:node})
newElements.push({data:node})
} else if (currentNode.category === ""){
// set values in a fake node
currentNode.id = cell.id.toString();
currentNode.name = cell.id.toString();
currentNode.category = category.name;
currentNode.color = getCategoryColorValue(category.index)
Object.entries(cell.properties).forEach(([key, value]) => {
currentNode[nodeSafeKey(key)] = value as string;
});
newElements.push({data:currentNode})
}
this.extendNode(cell, newElements)
}
}
})
Expand Down
31 changes: 21 additions & 10 deletions app/graph/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { toast } from "@/components/ui/use-toast";
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { signOut } from "next-auth/react";
import { useTheme } from "next-themes";
Expand All @@ -27,9 +27,20 @@ function validateGraphSelection(graphName: string): boolean {

export default function Page() {
const [graph, setGraph] = useState(Graph.empty());
const [value, setValue] = useState<string>("");
const [metaData, setMetaData] = useState<string[]>([]);
const [showGraph, setShowGraph] = useState<boolean>(true);

const [showData, setShowData] = useState<boolean>(true);

useEffect(() => {
if (showGraph) {
setValue("graph")
}else if(showData) {
setValue("data")
}else {
setValue("metadata")
}
}, [showData, showGraph])
const graphView = useRef<GraphViewRef>(null)


Expand Down Expand Up @@ -73,11 +84,11 @@ export default function Page() {
}

const json = await result.json()
setMetaData(json.result.metadata)
const newGraph = Graph.create(state.graphName, json.result)
setGraph(newGraph)
setMetaData(json.result.metadata)
setShowGraph((!!json.result.data && json.result.data.length > 0))

setShowGraph(!!newGraph.Categories && newGraph.Categories.length > 0)
setShowData(!!newGraph.Data && newGraph.Data.length > 0)
graphView.current?.expand(newGraph.Elements)
}

Expand All @@ -87,13 +98,13 @@ export default function Page() {
<div className="flex flex-col grow border border-gray-300 rounded-lg p-2 overflow-auto">
{
graph.Id &&
<Tabs defaultValue={showGraph ? "graph" : "metaData"} className="grow flex flex-col justify-center items-center">
<Tabs value={value} className="grow flex flex-col justify-center items-center">
<TabsList className="border w-fit">
<TabsTrigger value="metaData">MetaData</TabsTrigger>
{showGraph && <TabsTrigger value="data">Data</TabsTrigger>}
{showGraph && <TabsTrigger value="graph">Graph</TabsTrigger>}
<TabsTrigger value="metadata" onClick={() => setValue("metadata")}>Metadata</TabsTrigger>
{showData && <TabsTrigger value="data" onClick={() => setValue("data")}>Data</TabsTrigger>}
{showGraph && <TabsTrigger value="graph" onClick={() => setValue("graph")}>Graph</TabsTrigger>}
</TabsList>
<TabsContent value="metaData" className="grow w-full">
<TabsContent value="metadata" className="grow w-full">
<MetaDataView metadata={metaData} />
</TabsContent>
<TabsContent value="data" className="grow w-full flex-[1_1_0] overflow-auto">
Expand Down
Loading

0 comments on commit 357cdb6

Please sign in to comment.