feat(ui): add HB, HH and NI analysis

This commit is contained in:
dancingCycle 2023-08-21 22:02:43 +02:00
parent 94831d2a6b
commit e7b4803788
10 changed files with 2263 additions and 2032 deletions

View File

@ -1,6 +1,7 @@
import React from 'react';
import { Link, BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Header from './components/header';
import Home from './pages/home';
import StopsNonConforming from './pages/stops-non-conforming';
import StopsRefined from './pages/stops-refined';
@ -9,16 +10,30 @@ export default function App(){
return (
<div className='App'>
<Router>
<Link to='/'>
<button>Home</button>
</Link>
<h1>NAP Display</h1>
<h2>
Wellcome to the German NAP Display!
</h2>
<p>
This page compares Global IDs of stops from different NAP sources. <br/>
</p>
<Header />
<h1>DELFI-Display</h1>
<p>
Display analysis results made on public transport data provided by &nbsp;
<a href="https://www.delfi.de/"
target="_blank" rel="noopener noreferrer"
>
DELFI
</a>.
</p>
<h2>GTFS Static Feed</h2>
<p>
The so called "DELFI-Datensatz GTFS" is a GTFS Static Feed provided by DELFI accessible either via the &nbsp;
<a href="https://www.opendata-oepnv.de"
target="_blank" rel="noopener noreferrer"
>
opendata-oepnv.de
</a> or the &nbsp;
<a href="https://mobilithek.info/offers/552578819783815168"
target="_blank" rel="noopener noreferrer"
>
mobilithek.info
</a> data access point.
</p>
<Routes>
<Route exact path='/' element={<Home/>}/>
<Route exact path='/stops-non-compliant' element={<StopsNonConforming/>}/>

View File

@ -0,0 +1,31 @@
import React from 'react'
import { Link} from 'react-router-dom';
export default function Header(){
return (
<>
<Link
to='/'
>
<button>
Home
</button>
</Link>
<Link
to='https://www.swingbe.de/imprint/'
>
<button>
Imprint
</button>
</Link>
<Link
to='https://www.swingbe.de/privacy-policy/'
>
<button>
Privacy Policy
</button>
</Link>
</>
);
};

View File

@ -1,13 +1,30 @@
import React, { useState, useEffect } from 'react'
import {Link} from 'react-router-dom';
import '../style.css';
import {getStopsCountGtfsDeNotDhid, getStopsCountZhv, getStopsCountGtfs, getStopsCountGtfsDe} from '../utils/api';
import {
getStopsCountGtfsDeNotDhid,
getStopsCountGtfsDeHbNotDhid,
getStopsCountGtfsDeHhNotDhid,
getStopsCountGtfsDeNiNotDhid,
getStopsCountGtfs,
getStopsCountGtfsDe,
getStopsCountGtfsDeHb,
getStopsCountGtfsDeHh,
getStopsCountGtfsDeNi
} from '../utils/api';
export default function Home(){
const [countStopsGtfs, setCountStopsGtfs] = useState('loading...');
const [countStopsGtfsDe, setCountStopsGtfsDe] = useState('loading...');
const [countStopsGtfsDeHb, setCountStopsGtfsDeHb] = useState('loading...');
const [countStopsGtfsDeHh, setCountStopsGtfsDeHh] = useState('loading...');
const [countStopsGtfsDeNi, setCountStopsGtfsDeNi] = useState('loading...');
const [countStopsGtfsDeNotDhid, setCountStopsGtfsDeNotDhid] = useState('loading...');
const [countStopsZhv, setCountStopsZhv] = useState('loading...');
const [countStopsGtfsDeHbNotDhid, setCountStopsGtfsDeHbNotDhid] = useState('loading...');
const [countStopsGtfsDeHhNotDhid, setCountStopsGtfsDeHhNotDhid] = useState('loading...');
const [countStopsGtfsDeNiNotDhid, setCountStopsGtfsDeNiNotDhid] = useState('loading...');
/*fetch countStopsGtfs in a JavaScript function*/
const fetchGtfs = async () => {
@ -25,6 +42,30 @@ export default function Home(){
}
};
/*fetch countStopsGtfsDeHb in a JavaScript function*/
const fetchGtfsDeHb = async () => {
let count=await getStopsCountGtfsDeHb();
if(count > -1){
setCountStopsGtfsDeHb((countStopsGtfsDeHb) => count);
}
};
/*fetch countStopsGtfsDeHh in a JavaScript function*/
const fetchGtfsDeHh = async () => {
let count=await getStopsCountGtfsDeHh();
if(count > -1){
setCountStopsGtfsDeHh((countStopsGtfsDeHh) => count);
}
};
/*fetch countStopsGtfsDeNi in a JavaScript function*/
const fetchGtfsDeNi = async () => {
let count=await getStopsCountGtfsDeNi();
if(count > -1){
setCountStopsGtfsDeNi((countStopsGtfsDeNi) => count);
}
};
/*fetch countStopsGtfsDeNotDhid in a JavaScript function*/
const fetchGtfsDeNotDhid = async () => {
let count=await getStopsCountGtfsDeNotDhid();
@ -33,32 +74,85 @@ export default function Home(){
}
};
/*fetch countStopsZhv in a JavaScript function*/
const fetchZhv = async () => {
let count=await getStopsCountZhv();
/*fetch countStopsGtfsDeHbNotDhid in a JavaScript function*/
const fetchGtfsDeHbNotDhid = async () => {
let count=await getStopsCountGtfsDeHbNotDhid();
if(count > -1){
setCountStopsZhv((countStopsZhv) => count);
setCountStopsGtfsDeHbNotDhid((countStopsGtfsDeHbNotDhid) => count);
}
};
/*fetch countStopsGtfsDeHhNotDhid in a JavaScript function*/
const fetchGtfsDeHhNotDhid = async () => {
let count=await getStopsCountGtfsDeHhNotDhid();
if(count > -1){
setCountStopsGtfsDeHhNotDhid((countStopsGtfsDeHhNotDhid) => count);
}
};
/*fetch countStopsGtfsDeNiNotDhid in a JavaScript function*/
const fetchGtfsDeNiNotDhid = async () => {
let count=await getStopsCountGtfsDeNiNotDhid();
if(count > -1){
setCountStopsGtfsDeNiNotDhid((countStopsGtfsDeNiNotDhid) => count);
}
};
useEffect(() => {
/*effect goes here*/
fetchGtfs();
fetchGtfsDe();
fetchGtfsDeHb();
fetchGtfsDeHh();
fetchGtfsDeNi();
fetchGtfsDeNotDhid();
fetchZhv();
fetchGtfsDeHbNotDhid();
fetchGtfsDeHhNotDhid();
fetchGtfsDeNiNotDhid();
/*use an empty dependency countStopsGtfs to ensure the hook is running only once*/
/*TODO study dependency countStopsGtfs: https://reactjs.org/docs/hooks-effect.html*/
}, []);
return (
<>
<h3>Zentrales Haltestellenverzeichnis (ZHV)</h3>
<p>Number of stops: {countStopsZhv}</p>
<h3>DELFI GTFS Feed</h3>
<p>Number of stops: {countStopsGtfs}</p>
<p>Number of stops inside DE: {countStopsGtfsDe}</p>
<p>Number of stops inside DE not compliant with the Global ID: {countStopsGtfsDeNotDhid}</p>
<p>
Number of stops:&nbsp;
{countStopsGtfs}
</p>
<p>
Number of stops inside DE:&nbsp;
{countStopsGtfsDe}
</p>
<p>
Number of stops inside DE not compliant with the Global ID:&nbsp;
{countStopsGtfsDeNotDhid}
</p>
<p>
Number of stops inside DE-HB:&nbsp;
{countStopsGtfsDeHb}
</p>
<p>
Number of stops inside DE-HB not compliant with the Global ID:&nbsp;
{countStopsGtfsDeHbNotDhid} ({countStopsGtfsDeHb !== 0 ? (countStopsGtfsDeHbNotDhid / countStopsGtfsDeHb * 100).toFixed(2) : 'loading...'} %)
</p>
<p>
Number of stops inside DE-HH:&nbsp;
{countStopsGtfsDeHh}
</p>
<p>
Number of stops inside DE-HH not compliant with the Global ID:&nbsp;
{countStopsGtfsDeHhNotDhid} ({countStopsGtfsDeHh !== 0 ? (countStopsGtfsDeHhNotDhid / countStopsGtfsDeHh * 100).toFixed(2) : 'loading...'} %)
</p>
<p>
Number of stops inside DE-NI:&nbsp;
{countStopsGtfsDeNi}
</p>
<p>
Number of stops inside DE-NI not compliant with the Global ID:&nbsp;
{countStopsGtfsDeNiNotDhid} ({countStopsGtfsDeNi !== 0 ? (countStopsGtfsDeNiNotDhid / countStopsGtfsDeNi * 100).toFixed(2) : 'loading...'} %)
</p>
<h3>
<Link to="/stops-non-compliant">
Browse through stops inside DE not compliant with the Global ID.

View File

@ -1,12 +1,10 @@
import React from 'react';
import '../style.css';
import Entities from '../components/entities';
const StopsNonConforming = () => {
return (
<>
<h3>DELFI GTFS Feed</h3>
<p>Please feel free to browse through stops inside DE not compliant with the Global ID.</p>
<Entities route = 'gtfs-stops-de-not-dhid'/>
</>

View File

@ -1,6 +1,5 @@
import React from 'react';
import '../style.css';
import Entities from '../components/entities';
const StopsRefined = () => {

View File

@ -1,3 +0,0 @@
h1 { color: purple; }
h2 { color: darkblue; }
h3 { color: blueviolet; }

View File

@ -63,21 +63,122 @@ export async function getStopsCountGtfsDeNotDhid(){
};
/*
*get stops-count-zhv
*get stops-count-gtfs-de-hb
*/
export async function getStopsCountZhv(){
//console.log('stops:getStopsCountZhv() Start...');
export async function getStopsCountGtfsDeHb(){
//console.log('stops:getStopsCountGtfsDeHb() Start...');
let count=null;
try {
//TODO handle errors: https://www.valentinog.com/blog/await-react/
const address = `${config.API}stops-count-zhv`;
const address = `${config.API}stops-count-gtfs-de-hb`;
const res = await axios.get(address);
count=res.data[0].count;
} catch (err) {
console.error('err.message: ' + err.message);
count=-1;
}
//console.log('stops:getStopsCountZhv() Done.');
//console.log('stops:getStopsCountGtfsDeHb() Done.');
return count;
};
/*
*get stops-count-gtfs-de-hb-not-dhid
*/
export async function getStopsCountGtfsDeHbNotDhid(){
//console.log('stops:getStopsCountGtfsDeHbNotDhid() Start...');
let count=null;
try {
//TODO handle errors: https://www.valentinog.com/blog/await-react/
const address = `${config.API}stops-count-gtfs-de-hb-not-dhid`;
const res = await axios.get(address);
count=res.data[0].count;
} catch (err) {
console.error('err.message: ' + err.message);
count=-1;
}
//console.log('stops:getStopsCountGtfsDeHbNotDhid() Done.');
return count;
};
/*
*get stops-count-gtfs-de-hh-not-dhid
*/
export async function getStopsCountGtfsDeHhNotDhid(){
//console.log('stops:getStopsCountGtfsDeHhNotDhid() Start...');
let count=null;
try {
//TODO handle errors: https://www.valentinog.com/blog/await-react/
const address = `${config.API}stops-count-gtfs-de-hh-not-dhid`;
const res = await axios.get(address);
count=res.data[0].count;
} catch (err) {
console.error('err.message: ' + err.message);
count=-1;
}
//console.log('stops:getStopsCountGtfsDeHhNotDhid() Done.');
return count;
};
/*
*get stops-count-gtfs-de-ni-not-dhid
*/
export async function getStopsCountGtfsDeNiNotDhid(){
//console.log('stops:getStopsCountGtfsDeNiNotDhid() Start...');
let count=null;
try {
//TODO handle errors: https://www.valentinog.com/blog/await-react/
const address = `${config.API}stops-count-gtfs-de-ni-not-dhid`;
const res = await axios.get(address);
count=res.data[0].count;
} catch (err) {
console.error('err.message: ' + err.message);
count=-1;
}
//console.log('stops:getStopsCountGtfsDeNiNotDhid() Done.');
return count;
};
/*
*get stops-count-gtfs-de-hh
*/
export async function getStopsCountGtfsDeHh(){
//console.log('stops:getStopsCountGtfsDeHh() Start...');
let count=null;
try {
//TODO handle errors: https://www.valentinog.com/blog/await-react/
const address = `${config.API}stops-count-gtfs-de-hh`;
const res = await axios.get(address);
count=res.data[0].count;
} catch (err) {
console.error('err.message: ' + err.message);
count=-1;
}
//console.log('stops:getStopsCountGtfsDeHh() Done.');
return count;
};
/*
*get stops-count-gtfs-de-ni
*/
export async function getStopsCountGtfsDeNi(){
//console.log('stops:getStopsCountGtfsDeNi() Start...');
let count=null;
try {
//TODO handle errors: https://www.valentinog.com/blog/await-react/
const address = `${config.API}stops-count-gtfs-de-ni`;
const res = await axios.get(address);
count=res.data[0].count;
} catch (err) {
console.error('err.message: ' + err.message);
count=-1;
}
//console.log('stops:getStopsCountGtfsDeNi() Done.');
return count;
};

3955
ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,36 +10,33 @@
],
"author": "Software Ingenieur Begerad <dialog@SwIngBe.de>",
"license": "GPL-3.0-or-later",
"engines": {
"node": ">=10"
},
"scripts": {
"start": "webpack serve --config config/webpack.dev.js",
"build": "webpack --config config/webpack.prod.js"
"build": "webpack --config config/webpack.prod.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"@babel/core": "7.21.4",
"@babel/preset-env": "7.21.4",
"@babel/preset-react": "7.18.6",
"babel-loader": "9.1.2",
"css-loader": "6.7.3",
"file-loader": "6.2.0",
"html-webpack-plugin": "5.5.1",
"style-loader": "3.3.2",
"svg-url-loader": "8.0.0",
"webpack": "5.80.0",
"webpack-cli": "5.0.1",
"webpack-dev-server": "4.13.3",
"webpack-merge": "5.8.0"
"@babel/core": "7.22.10",
"@babel/preset-env": "7.22.10",
"@babel/preset-react": "7.22.5",
"babel-loader": "9.1.3",
"html-webpack-plugin": "5.5.3",
"webpack": "5.88.2",
"webpack-cli": "5.1.4",
"webpack-dev-server": "4.15.1",
"webpack-merge": "5.9.0"
},
"dependencies": {
"axios": "1.3.6",
"css-loader": "6.8.1",
"file-loader": "6.2.0",
"leaflet": "1.9.3",
"prop-types": "15.8.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-leaflet": "4.2.1",
"react-leaflet-cluster": "2.1.0",
"react-router-dom": "6.10.0"
"react-router-dom": "6.15.0",
"style-loader": "3.3.3"
}
}

View File

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
<title>NAP Display</title>
<title>Delfi-Display</title>
</head>
<body>
<div id="root"></div>