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 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
4 changes: 2 additions & 2 deletions Project/backend/codebase/graph_creator/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,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
30 changes: 21 additions & 9 deletions Project/backend/codebase/graph_creator/services/netx_graphdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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 @@ -96,19 +97,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 = 1
async def graph_data_for_visualization(
self, graph_job: GraphJob, node: str = None, adj_depth: int = 1
) -> 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 @@ -125,7 +127,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 @@ -164,10 +168,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 @@ -196,4 +205,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