Merge Graph and PathVisualiser components

This commit is contained in:
Maciej Pędzich 2024-04-29 21:18:25 +02:00
parent da498bfab9
commit 79145b945c
Signed by: maciejpedzich
GPG Key ID: CE4A303D84882F0D
3 changed files with 43 additions and 154 deletions

View File

@ -1,16 +0,0 @@
---
import { db } from '@/db';
const { records } = await db.executeQuery(
`MATCH (d:Driver)
RETURN
(d.forename + " " + d.surname) AS fullname
ORDER BY
toUpper(d.surname),
toUpper(d.forename)`
);
---
<datalist id="drivers">
{records.map((rec) => <option value={rec.get('fullname')} />)}
</datalist>

View File

@ -1,121 +0,0 @@
---
import type { Path } from 'neo4j-driver';
import type { Edge, Node } from 'vis-network';
import Graph from '@/components/Graph.astro';
import { db } from '@/db';
import type { Driver } from '@/models/driver';
interface Props {
source: string;
dest: string;
}
const { source, dest } = Astro.props;
const pluralise = (word: string, num: number) =>
num + ' ' + word + (num > 1 ? 's' : '');
let paramsNotEqual = source !== dest;
let numPaths = 0;
let degsOfSeparation = 0;
let nodes: Node[] = [];
let edges: Edge[] = [];
if (paramsNotEqual) {
const { records } = await db.executeQuery(
`MATCH (n:Driver)
WHERE
(n.forename + " " + n.surname) = $source
OR (n.forename + " " + n.surname) = $dest
WITH collect(n) AS nodes
UNWIND nodes AS s
UNWIND nodes AS d
WITH *
WHERE
(s.forename + " " + s.surname) = $source
AND (d.forename + " " + d.surname) = $dest
MATCH path = allShortestPaths((s)-[*..20]-(d))
RETURN path`,
{ source, dest }
);
numPaths = records.length;
degsOfSeparation =
records.length > 0 ? (records[0].get('path') as Path).length : 0;
const pairsOfRelatedDrivers = records.flatMap((rec) =>
(rec.get('path') as Path).segments.map(
({ start, end }) => [start.properties, end.properties] as Driver[]
)
);
nodes = [
...new Map(
pairsOfRelatedDrivers.flatMap((pair) =>
pair.map(({ driverId, forename, surname }) => [
driverId.toNumber(),
forename + ' ' + surname
])
)
).entries()
].map(([id, label]) => ({ id, label }));
edges = [
...new Set(
pairsOfRelatedDrivers.map(
([from, to]) => from.driverId.toString() + '-' + to.driverId.toString()
)
).values()
].map((pair) => {
const [from, to] = pair.split('-').map(Number);
return { from, to };
});
}
---
<p>
{
paramsNotEqual ? (
nodes.length > 0 ? (
degsOfSeparation == 1 ? (
'Colosally, these drivers were teammates!'
) : (
<span>
Found <strong>{pluralise('path', numPaths)}</strong> with
<strong>{pluralise('degree', degsOfSeparation)}</strong>
of separation.
</span>
)
) : (
'No paths were found!'
)
) : (
"There's nothing wrong with the inputs, except they're identical."
)
}
</p>
{
nodes.length > 0 && (
<>
<div id="graph-container">
<Graph nodes={nodes} edges={edges} />
</div>
<small>
Drag to pan, scroll to zoom. Click on a node to highlight it and its
links.
</small>
</>
)
}
<style>
#graph-container {
height: 600px;
border: 1px solid gray;
margin-bottom: 0.5rem;
}
</style>

View File

@ -1,20 +1,45 @@
---
import type { Node, Edge } from 'vis-network/esnext';
import { getShortestPaths } from '@/db/getShortestPaths';
import { pluralise } from '@/utils/pluralise';
interface Props {
nodes: Node[];
edges: Edge[];
type Props = Awaited<ReturnType<typeof getShortestPaths>>;
const { nodes, edges, numPaths, degsOfSeparation } = Astro.props;
---
<p>
{
nodes.length > 0 ? (
degsOfSeparation == 1 ? (
'Colosally, these drivers were teammates!'
) : (
<span>
Found <strong>{pluralise('path', numPaths)}</strong> with
<strong>{pluralise('degree', degsOfSeparation)}</strong>
of separation.
</span>
)
) : (
'No paths were found!'
)
}
const { nodes, edges } = Astro.props;
---
</p>
{
nodes.length > 0 && (
<>
<vis-graph
data-nodes={JSON.stringify(nodes)}
data-edges={JSON.stringify(edges)}
>
<div></div>
<div id="graph-container" />
</vis-graph>
<small>
Drag to pan, scroll to zoom. Click on a node to highlight it and its
links.
</small>
</>
)
}
<script>
import type { Node, Data, Edge, Options } from 'vis-network/esnext';
@ -46,7 +71,6 @@ const { nodes, edges } = Astro.props;
}
},
edges: {
arrows: 'to',
color: '#4178e7'
},
layout: {
@ -68,8 +92,10 @@ const { nodes, edges } = Astro.props;
</script>
<style>
div {
#graph-container {
width: 100%;
height: 100%;
height: 600px;
border: 1px solid gray;
margin-bottom: 1rem;
}
</style>