2020-02-09 18:40:34 +00:00
|
|
|
import React, { useState ,useEffect } from "react";
|
2020-02-09 23:12:39 +00:00
|
|
|
import { fetchRoads, fetchCities, getShortestPath } from './requests';
|
2020-02-09 18:40:34 +00:00
|
|
|
import { Select, Button, Icon } from 'antd';
|
2020-02-10 01:05:34 +00:00
|
|
|
import Graph from "react-graph-vis";
|
2020-02-09 23:12:39 +00:00
|
|
|
|
2020-02-09 18:40:34 +00:00
|
|
|
const { Option } = Select;
|
|
|
|
|
|
|
|
function HomeView() {
|
|
|
|
const [startingPoint, setStartingPoint] = useState();
|
|
|
|
const [destination, setDestination] = useState();
|
2020-02-09 23:12:39 +00:00
|
|
|
const [errorSelect, setError] = useState({ message: '', flag: false });
|
2020-02-09 18:40:34 +00:00
|
|
|
const [shortestPath, setShortestPath] = useState();
|
2020-02-09 23:12:39 +00:00
|
|
|
|
|
|
|
const [cities, setCities] = useState([]);
|
2020-02-09 18:40:34 +00:00
|
|
|
useEffect(() => {
|
2020-02-09 23:12:39 +00:00
|
|
|
fetchCities()
|
|
|
|
.then(data => setCities(data))
|
|
|
|
.catch(error => console.log(error))
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const [roads, setRoads] = useState([]);
|
|
|
|
useEffect(() => {
|
|
|
|
fetchRoads()
|
|
|
|
.then(data => setRoads(data))
|
|
|
|
.catch(error => console.log(error));
|
2020-02-09 18:40:34 +00:00
|
|
|
}, []);
|
2020-02-09 23:12:39 +00:00
|
|
|
|
|
|
|
const [graph, setGraph] = useState({nodes: [], edges: []});
|
2020-02-10 01:05:34 +00:00
|
|
|
|
2020-02-09 23:12:39 +00:00
|
|
|
useEffect(() => {
|
|
|
|
let nodes = cities.map(node => (
|
2020-02-10 01:05:34 +00:00
|
|
|
{ id: node.id, label: node.name, title: node.name}
|
2020-02-09 23:12:39 +00:00
|
|
|
));
|
|
|
|
|
|
|
|
let edges = roads.map(edge => (
|
2020-02-10 01:05:34 +00:00
|
|
|
{ from: edge.start_city_id, to: edge.end_city_id, length: edge.distance }
|
2020-02-09 23:12:39 +00:00
|
|
|
))
|
|
|
|
|
|
|
|
setGraph({nodes, edges})
|
2020-02-10 01:05:34 +00:00
|
|
|
}, [cities, roads, shortestPath])
|
2020-02-09 18:40:34 +00:00
|
|
|
|
|
|
|
function handleStart(city_id) {
|
|
|
|
// eslint-disable-next-line
|
|
|
|
let [ startingPoint ] = cities.filter(city => city.id == city_id);
|
|
|
|
setStartingPoint(startingPoint);
|
2020-02-09 23:12:39 +00:00
|
|
|
// Check if start and destination are the same
|
|
|
|
if (startingPoint === destination) {
|
|
|
|
setError({ message: 'The start and destination must be different.', flag: true });
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// Will reset the error message and shown path
|
|
|
|
setShortestPath();
|
|
|
|
setError({ flag: false });
|
2020-02-09 18:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function handleDestination(city_id) {
|
|
|
|
// eslint-disable-next-line
|
|
|
|
let [ destination ] = cities.filter(city => city.id == city_id);
|
|
|
|
setDestination(destination);
|
2020-02-09 23:12:39 +00:00
|
|
|
// Check if start and destination are the same
|
|
|
|
if (startingPoint === destination) {
|
|
|
|
setError({ message: 'The start and destination must be different.', flag: true });
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// Will reset the error message and shown path
|
|
|
|
setShortestPath();
|
|
|
|
setError({ flag: false });
|
2020-02-09 18:40:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function handleSubmit() {
|
|
|
|
if (startingPoint === destination) {
|
|
|
|
return
|
2020-02-09 23:12:39 +00:00
|
|
|
} else
|
|
|
|
if (startingPoint && destination) {
|
|
|
|
getShortestPath(startingPoint.id, destination.id)
|
|
|
|
.then(data => setShortestPath(data))
|
|
|
|
.catch(error => console.log(error));
|
|
|
|
setError({ flag: false });
|
2020-02-09 18:40:34 +00:00
|
|
|
} else {
|
2020-02-09 23:12:39 +00:00
|
|
|
setError({ message: 'Please select a start and a destination', flag: true});
|
2020-02-09 18:40:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-10 01:05:34 +00:00
|
|
|
// Graph visualization settings
|
|
|
|
const options = {
|
|
|
|
layout: {
|
|
|
|
hierarchical: false
|
|
|
|
},
|
|
|
|
edges: {
|
|
|
|
color: "#000000"
|
|
|
|
},
|
|
|
|
height: "500px"
|
|
|
|
};
|
|
|
|
const events = {
|
|
|
|
select: function(event) {
|
|
|
|
let { nodes, edges } = event;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// // TODO Find a solution to trigger a re-render of the map
|
|
|
|
// // Add dashes to shortest path edges
|
|
|
|
// let path = test.path;
|
|
|
|
// let pairs = [];
|
|
|
|
|
|
|
|
// for (let i = 0; path.length - 1 > i; i++) {
|
|
|
|
// let obj = { from: path[i], to: path[i+1]}
|
|
|
|
// pairs.push(obj);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// let updatedEdges = graph.edges.map(edge => {
|
|
|
|
// if (pairs.includes(edge)){
|
|
|
|
// edge['dashes'] = true;
|
|
|
|
// }
|
|
|
|
// return edge
|
|
|
|
// })
|
|
|
|
// console.log(updatedEdges)
|
|
|
|
// setGraph({...graph, edges: updatedEdges});
|
|
|
|
|
2020-02-09 18:40:34 +00:00
|
|
|
return(
|
|
|
|
<main>
|
|
|
|
<section>
|
|
|
|
<h2>Select Starting Point</h2>
|
|
|
|
<div>
|
|
|
|
<Select defaultValue="Belgium" disabled>
|
|
|
|
</Select>
|
|
|
|
<Select
|
|
|
|
defaultValue="Choose a city"
|
|
|
|
onChange={handleStart}
|
2020-02-09 23:12:39 +00:00
|
|
|
style={{ width: 139 }}
|
2020-02-09 18:40:34 +00:00
|
|
|
>
|
|
|
|
{cities.map(city => (
|
|
|
|
<Option key={city.id}>{city.name}</Option>
|
|
|
|
))}
|
|
|
|
</Select>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<h2>Select Destination</h2>
|
|
|
|
<div>
|
|
|
|
<Select defaultValue="Belgium" disabled>
|
|
|
|
</Select>
|
|
|
|
<Select
|
|
|
|
defaultValue="Choose a city"
|
|
|
|
onChange={handleDestination}
|
2020-02-09 23:12:39 +00:00
|
|
|
style={{ width: 139 }}
|
2020-02-09 18:40:34 +00:00
|
|
|
>
|
|
|
|
{cities.map(city => (
|
|
|
|
<Option key={city.id}>{city.name}</Option>
|
|
|
|
))}
|
|
|
|
</Select>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
|
|
<Button
|
|
|
|
type="primary"
|
|
|
|
onClick={handleSubmit}
|
|
|
|
>
|
|
|
|
Get shortest path between the cities
|
|
|
|
<Icon type="right" />
|
|
|
|
</Button>
|
2020-02-09 23:12:39 +00:00
|
|
|
{errorSelect.flag &&
|
|
|
|
<p>{errorSelect.message}</p>
|
2020-02-09 18:40:34 +00:00
|
|
|
}
|
|
|
|
</section>
|
|
|
|
{
|
2020-02-09 23:12:39 +00:00
|
|
|
shortestPath &&
|
2020-02-09 18:40:34 +00:00
|
|
|
<section>
|
2020-02-09 23:12:39 +00:00
|
|
|
<h2>Shortest path from {startingPoint.name} to {destination.name} ({shortestPath.distance}km)</h2>
|
|
|
|
<div>{shortestPath.path.map(city => (
|
|
|
|
<p key={city.id}><Icon type="right" /><span>{city.name}</span></p>
|
2020-02-09 18:40:34 +00:00
|
|
|
))}
|
2020-02-09 23:12:39 +00:00
|
|
|
</div>
|
2020-02-09 18:40:34 +00:00
|
|
|
|
|
|
|
</section>
|
|
|
|
}
|
2020-02-09 23:12:39 +00:00
|
|
|
{ graph.nodes.length > 0 &&
|
|
|
|
|
2020-02-10 01:05:34 +00:00
|
|
|
<Graph
|
|
|
|
graph={graph}
|
|
|
|
options={options}
|
|
|
|
events={events}
|
|
|
|
getNetwork={network => {
|
|
|
|
// if you want access to vis.js network api you can set the state in a parent component using this property
|
|
|
|
}}
|
|
|
|
/>
|
2020-02-09 23:12:39 +00:00
|
|
|
}
|
2020-02-09 18:40:34 +00:00
|
|
|
</main>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default HomeView
|