Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/split view #157

Merged
merged 7 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
19 changes: 8 additions & 11 deletions Project/backend/codebase/graph_creator/router.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import logging
import mimetypes
import os
import uuid

import shutil
import tempfile
import uuid
from typing import Optional


from fastapi import APIRouter, Depends
from fastapi import UploadFile, File, HTTPException
from starlette.responses import JSONResponse

import graph_creator.graph_creator_main as graph_creator_main
from graph_creator.dao.graph_job_dao import GraphJobDAO
from graph_creator.schemas.graph_job import GraphJobCreate
from graph_creator.pdf_handler import process_pdf_into_chunks
from graph_creator.gemini import process_chunks
import shutil
import mimetypes
from graph_creator.pdf_handler import process_pdf_into_chunks
from graph_creator.schemas.graph_job import GraphJobCreate
from graph_creator.schemas.graph_vis import GraphVisData, QueryInputData, GraphQueryOutput
from graph_creator.services.netx_graphdb import NetXGraphDB

import graph_creator.graph_creator_main as graph_creator_main
from graph_creator.services.query_graph import GraphQuery
from graph_creator.utils.const import GraphStatus

Expand Down Expand Up @@ -282,8 +279,8 @@ async def get_graph_data_for_visualization(
raise HTTPException(
status_code=400, detail="A graph needs to be created for this job first!"
)
return netx_services.graph_data_for_visualization(
g_job.id, node=node, adj_depth=adj_depth
return await netx_services.graph_data_for_visualization(
graph_job=g_job, node=node, adj_depth=adj_depth
)


Expand Down
4 changes: 4 additions & 0 deletions Project/backend/codebase/graph_creator/schemas/graph_vis.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

from pydantic import BaseModel, Field


Expand All @@ -19,6 +21,8 @@ class GraphEdge(BaseModel):


class GraphVisData(BaseModel):
document_name: str
graph_created_at: datetime
nodes: list[GraphNode]
edges: list[GraphEdge]

Expand Down
32 changes: 23 additions & 9 deletions Project/backend/codebase/graph_creator/services/netx_graphdb.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import os
import uuid

import networkx as nx
import numpy as np
import pandas as pd

from graph_creator.models.graph_job import GraphJob
from graph_creator.schemas.graph_vis import GraphVisData, GraphNode, GraphEdge

# Scale range for min-max scaling the node sizes
Expand Down Expand Up @@ -66,19 +69,20 @@ def delete_graph(self, graph_job_id: uuid.UUID):
if os.path.exists(file_location):
os.remove(file_location)

def graph_data_for_visualization(
self, graph_job_id: uuid.UUID, node: str | None, adj_depth: int
async def graph_data_for_visualization(
self, graph_job: GraphJob, node: str | None, adj_depth: int
) -> GraphVisData:
"""
Given a graph travers it and return a json format of all the nodes and edges they have
ready for visualization to FE
"""
graph = self.load_graph(graph_job_id)

graph = self.load_graph(graph_job.id)

if node:
return self._graph_bfs_edges(graph, node, adj_depth)
return self._graph_bfs_edges(graph, graph_job, node, adj_depth)

return self._all_graph_data_for_visualization(graph)
return self._all_graph_data_for_visualization(graph, graph_job)

@staticmethod
def _get_graph_file_path_local_storage(graph_job_id: uuid.UUID) -> str:
Expand All @@ -95,7 +99,9 @@ def _get_graph_file_path_local_storage(graph_job_id: uuid.UUID) -> str:
return os.path.join(graphs_directory, f"{graph_job_id}.gml")

@staticmethod
def _graph_bfs_edges(graph: nx.Graph, node: str, adj_depth: int) -> GraphVisData:
def _graph_bfs_edges(
graph: nx.Graph, graph_job: GraphJob, node: str, adj_depth: int
) -> GraphVisData:
nodes_data = []
edges_data = []
visited = set()
Expand Down Expand Up @@ -132,10 +138,15 @@ def _graph_bfs_edges(graph: nx.Graph, node: str, adj_depth: int) -> GraphVisData
)
)

return GraphVisData(nodes=nodes_data, edges=edges_data)
return GraphVisData(document_name=graph_job.name,
graph_created_at=graph_job.updated_at,
nodes=nodes_data,
edges=edges_data)

@staticmethod
def _all_graph_data_for_visualization(graph: nx.Graph) -> GraphVisData:
def _all_graph_data_for_visualization(
graph: nx.Graph, graph_job: GraphJob
) -> GraphVisData:
nodes_data = []
edges_data = []

Expand Down Expand Up @@ -163,4 +174,7 @@ def _all_graph_data_for_visualization(graph: nx.Graph) -> GraphVisData:
)
)

return GraphVisData(nodes=nodes_data, edges=edges_data)
return GraphVisData(document_name=graph_job.name,
graph_created_at=graph_job.updated_at,
nodes=nodes_data,
edges=edges_data)
37 changes: 37 additions & 0 deletions Project/frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Project/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/icons-material": "^5.15.20",
"@mui/material": "^5.15.19",
"@react-sigma/core": "4.0.2",
"@sigma/edge-curve": "*",
Expand All @@ -27,6 +28,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-filepond": "^7.1.2",
"react-icons": "^5.2.1",
"react-router-dom": "^6.23.1",
"react-sigma": "*",
"sigma": "3.0.0-beta.16",
Expand Down
33 changes: 32 additions & 1 deletion Project/frontend/src/components/Graph/index.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.graph_container {
.main_graph_container {
flex: 1;
display: flex;
flex-direction: column;
gap: 50px;
Expand All @@ -10,6 +11,36 @@
/* overflow: hidden; */
}

.graph_container {
flex: 1;
display: flex;
flex-direction: row;
gap: 50px;
text-align: center;
justify-content: flex-start;
height: 100vh;
width: 100vw;
}

.graph_info {
width: 25%;
padding: 20px;
overflow-y: auto;
}

.graph_info h1 {
margin-bottom: 30px;
text-decoration: underline;
}

.graph_info p {
margin-bottom: 30px;
}

.search_container {
position: relative;
}

.sigma_container {
background: var(--mui-palette-primary-main);
}
Expand Down
69 changes: 66 additions & 3 deletions Project/frontend/src/components/Graph/index_visjs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { Network } from 'vis-network/standalone/esm/vis-network';
import { useParams } from 'react-router-dom';
import './index.css';
import { VISUALIZE_API_PATH } from '../../constant';
import SearchIcon from '@mui/icons-material/Search';
import TextField from '@mui/material/TextField';
import { InputAdornment } from '@mui/material';

const VisGraph = ({ graphData, options }) => {
const containerRef = useRef(null);
Expand Down Expand Up @@ -203,6 +206,25 @@ const GraphVisualization = () => {
},
};

const searchGraph = (event) => {
if (event.key === 'Enter') {
// Perform the search
}
};

const searchBarStyle = {
padding: '8px',
width: '100%',
marginBottom: '10px',
fontSize: '16px',
};

const answerAreaStyle = {
padding: '8px',
width: '100%',
fontSize: '16px',
};

if (isLoading) {
return <div className="loading_spinner_graph">Loading graph...</div>;
}
Expand All @@ -211,9 +233,17 @@ const GraphVisualization = () => {
return <div className="error_container">Sorry, an error has occurred!</div>;
}

const formattedDate = new Date(
graphData.graph_created_at,
).toLocaleDateString();

const formattedTime = new Date(
graphData.graph_created_at,
).toLocaleTimeString();

return (
<section className="graph_container">
<h1>Graph Visualization</h1>
<section className="main_graph_container">
<h1>Graph Visualization </h1>
<select onChange={(e) => setLayout(e.target.value)} value={layout}>
<option value="barnesHut">Barnes Hut</option>
<option value="forceAtlas2Based">Force Atlas 2 Based</option>
Expand All @@ -223,7 +253,40 @@ const GraphVisualization = () => {
<option value="grid">Grid</option>
<option value="random">Random</option>
</select>
<VisGraph graphData={graphData} options={options} />
<section className="graph_container">
<div className="graph_info">
<h1>Graph Information</h1>
<p>
Document Name: <br /> {graphData.document_name}
<br /> <br />
Created at: <br /> {formattedDate} {formattedTime}
</p>
<TextField
className="search_text_field"
placeholder="Search for keywords"
style={searchBarStyle}
onKeyDown={searchGraph}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<SearchIcon />
</InputAdornment>
),
}}
/>
<TextField
className="answer_text_field"
placeholder="Answer to your search will be displayed here!"
style={answerAreaStyle}
multiline
rows={8}
InputProps={{
readOnly: true,
}}
/>
</div>
<VisGraph graphData={graphData} options={options} />
</section>
</section>
);
};
Expand Down
Loading