diff --git a/package-lock.json b/package-lock.json index 286bb23..86a4b55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1078,6 +1078,14 @@ "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" }, + "@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "requires": { + "@types/hammerjs": "^2.0.36" + } + }, "@emotion/is-prop-valid": { "version": "0.8.6", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.6.tgz", @@ -1541,6 +1549,11 @@ "@types/node": "*" } }, + "@types/hammerjs": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.36.tgz", + "integrity": "sha512-7TUK/k2/QGpEAv/BCwSHlYu3NXZhQ9ZwBYpzr9tjlPIL2C5BeGhH3DmVavRx3ZNyELX5TLC91JTz/cen6AAtIQ==" + }, "@types/istanbul-lib-coverage": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", @@ -7951,6 +7964,11 @@ "object.assign": "^4.1.0" } }, + "keycharm": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.2.0.tgz", + "integrity": "sha1-+m6i5DuQpoAohD0n8gddNajD5vk=" + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -11296,6 +11314,24 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.5.tgz", "integrity": "sha512-+DMR2k5c6BqMDSMF8hLH0vYKtKTeikiFW+fj0LClN+XZg4N9b8QUAdHC62CGWNLTi/gnuuemNcNcTFrCvK1f+A==" }, + "react-graph-vis": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/react-graph-vis/-/react-graph-vis-1.0.5.tgz", + "integrity": "sha512-y7+eHcwj7GryRoY+ZawwsDmS8OMeJ8Gpzmzejqwz+T2qg6IYTk1bod42H5g3J2zzHcPaqAZpwxZG3d3YB4nBwQ==", + "requires": { + "lodash": "^4.17.15", + "prop-types": "^15.5.10", + "uuid": "^2.0.1", + "vis-network": "^5.1.1" + }, + "dependencies": { + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" + } + } + }, "react-is": { "version": "16.12.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", @@ -13586,6 +13622,51 @@ "extsprintf": "^1.2.0" } }, + "vis-data": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vis-data/-/vis-data-6.3.5.tgz", + "integrity": "sha512-H8lD1NTmC5HimYeqTouxhbUya5qrYQGjpJhIHkxsm5R34EEdcm/D1cLTMLFFyIoZC6SQkADQj+dlFKf5DOnSww==", + "requires": { + "vis-util": "2.0.1", + "vis-uuid": "1.1.3" + }, + "dependencies": { + "vis-util": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vis-util/-/vis-util-2.0.1.tgz", + "integrity": "sha512-VBQ6zCT+Iaum70uzLbjk0nLMOjp9NhPzU42j0gaM6q6tg0eTcgIWNXzAqamhQtmm1kDj0jMLzKvkFOPENYv34w==", + "optional": true + } + } + }, + "vis-network": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/vis-network/-/vis-network-5.4.1.tgz", + "integrity": "sha512-hUJlFWoCmLup6IxoXCr//OO2ZCkC8jrXEkkHLG1DhBgB54Y3K33+e5q4tc436inMlGzfqqaKTIToNbOGr8Szww==", + "requires": { + "@egjs/hammerjs": "^2.0.15", + "component-emitter": "^1.3.0", + "keycharm": "^0.2.0", + "moment": "^2.24.0", + "timsort": "^0.3.0", + "vis-data": "^6.1.1", + "vis-util": "^1.1.6" + } + }, + "vis-util": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/vis-util/-/vis-util-1.1.10.tgz", + "integrity": "sha512-8hGSxsFi2ogYYweClQyITzWnirWgQ8p0i9M4d3OXMuUO8vjXrf+2zHOYI9OZbtUduxAWuMEePnS9BXDtPJmJ7Q==", + "requires": { + "moment": "2.24.0", + "vis-uuid": "1.1.3" + } + }, + "vis-uuid": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vis-uuid/-/vis-uuid-1.1.3.tgz", + "integrity": "sha512-2B6XdY1bkzbUh+TugmnAaFa61KO9R5pzBzIuFIm8a9FrkbxIdSmQXV+FbfkL8QunkQV/bT0JDLQ2puqCS2+0Og==" + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", diff --git a/package.json b/package.json index 0b7c224..e8c681d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "axios": "^0.19.2", "react": "^16.12.0", "react-dom": "^16.12.0", + "react-graph-vis": "^1.0.5", "react-router-dom": "^5.1.2", "react-scripts": "3.3.1", "react-sigma": "^1.2.34", diff --git a/src/App.js b/src/App.js index 8f6c484..964939b 100644 --- a/src/App.js +++ b/src/App.js @@ -7,7 +7,7 @@ function App() { return ( Dijkstra - Dijkstra is an app thas uses Dijkstra algorithm to display the shortest path between different cities in Belgium. + Find the shortest path between different cities in Belgium with Dijkstra algorithm. ); diff --git a/src/components/HomeView.jsx b/src/components/HomeView.jsx index 051db80..c0b95f7 100644 --- a/src/components/HomeView.jsx +++ b/src/components/HomeView.jsx @@ -1,66 +1,85 @@ import React, { useState ,useEffect } from "react"; -import Axios from '../utils/API'; +import { fetchRoads, fetchCities, getShortestPath } from './requests'; +import {Sigma, RandomizeNodePositions, RelativeSize, SigmaEnableSVG} from 'react-sigma'; import { Select, Button, Icon } from 'antd'; + const { Option } = Select; function HomeView() { - const [cities, setCities] = useState([]); const [startingPoint, setStartingPoint] = useState(); const [destination, setDestination] = useState(); + const [errorSelect, setError] = useState({ message: '', flag: false }); const [shortestPath, setShortestPath] = useState(); - const [errorMessage, setErrorMessage] = useState(); - + + const [cities, setCities] = useState([]); useEffect(() => { - async function fetchData() { - try { - const { data } = await Axios.get( - `/countries/1` - ); - setCities(data); - } catch (error) { - console.error(error); - } - }; - fetchData(); + 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)); + }, []); + + + const [graph, setGraph] = useState({nodes: [], edges: []}); + useEffect(() => { + let nodes = cities.map(node => ( + { id: `n${node.id}`, label: node.name} + )); + + let edges = roads.map(edge => ( + { id: `e${edge.id}`, source: `n${edge.start_city_id}`, target: `n${edge.end_city_id}`, label: 'SEES' } + )) + + setGraph({nodes, edges}) + }, [cities, roads]) + function handleStart(city_id) { // eslint-disable-next-line let [ startingPoint ] = cities.filter(city => city.id == city_id); setStartingPoint(startingPoint); + // 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 }); } function handleDestination(city_id) { // eslint-disable-next-line let [ destination ] = cities.filter(city => city.id == city_id); setDestination(destination); + // 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 }); } + function handleSubmit() { if (startingPoint === destination) { - setErrorMessage('Starting Point and Destination must be different cities.'); return - } else if (startingPoint && destination) { - async function getPath() { - try { - const response = await Axios.get( - `/path`, - { - params: { - start_city_id: startingPoint.id, - end_city_id: destination.id - } - } - ); - setShortestPath(response.data) - setErrorMessage(); - } catch (error) { - console.error(error); - } - } - getPath(); + } else + if (startingPoint && destination) { + getShortestPath(startingPoint.id, destination.id) + .then(data => setShortestPath(data)) + .catch(error => console.log(error)); + setError({ flag: false }); } else { - setErrorMessage('Please select a Starting point and a Destination'); + setError({ message: 'Please select a start and a destination', flag: true}); } } @@ -74,6 +93,7 @@ function HomeView() { {cities.map(city => ( {city.name} @@ -89,6 +109,7 @@ function HomeView() { {cities.map(city => ( {city.name} @@ -104,21 +125,32 @@ function HomeView() { Get shortest path between the cities - {errorMessage && - {errorMessage} + {errorSelect.flag && + {errorSelect.message} } { - shortestPath && + shortestPath && - Shortest path from {startingPoint.name} to {destination.name} - {shortestPath.path.map(city => ( - <>{city.name}> + Shortest path from {startingPoint.name} to {destination.name} ({shortestPath.distance}km) + {shortestPath.path.map(city => ( + {city.name} ))} - + } + { graph.nodes.length > 0 && + + + Graph + + + + + + + } ); } diff --git a/src/components/requests.js b/src/components/requests.js new file mode 100644 index 0000000..d50551a --- /dev/null +++ b/src/components/requests.js @@ -0,0 +1,40 @@ +import Axios from '../utils/API'; + +export async function fetchRoads() { + try { + const { data } = await Axios.get( + `api/roads` + ); + return data + } catch (error) { + console.error(error); + } +}; + +export async function fetchCities() { + try { + const { data } = await Axios.get( + `api/countries/1` + ); + return data + } catch (error) { + console.error(error); + } +}; + +export async function getShortestPath(startingPointId, destinationID) { + try { + const response = await Axios.get( + `api/path`, + { + params: { + start_city_id: startingPointId, + end_city_id: destinationID + } + } + ); + return response.data + } catch (error) { + console.error(error); + } +} diff --git a/src/utils/API.js b/src/utils/API.js index 23d9763..8805aff 100644 --- a/src/utils/API.js +++ b/src/utils/API.js @@ -1,6 +1,6 @@ import axios from "axios"; export default axios.create({ - baseURL: "https://dijkstra-backend.herokuapp.com/api", + baseURL: "https://dijkstra-backend.herokuapp.com/", responseType: "json" }); \ No newline at end of file
Dijkstra is an app thas uses Dijkstra algorithm to display the shortest path between different cities in Belgium.
Find the shortest path between different cities in Belgium with Dijkstra algorithm.
{errorMessage}
{errorSelect.message}
{shortestPath.path.map(city => ( - <>{city.name}> +
{city.name}
Graph