Making some progress
This commit is contained in:
parent
c41d4b4cec
commit
7d74fcc3e0
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -7,6 +7,7 @@
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<!--<link rel='stylesheet' href='/global.css'>-->
|
||||
<link rel='stylesheet' href='/build/bundle.css'>
|
||||
|
||||
<script defer src='/build/bundle.js'></script>
|
||||
|
@ -5,6 +5,7 @@
|
||||
// Import the list of routes
|
||||
import routes from './routes'
|
||||
import Header from "./components/Header.svelte";
|
||||
let currentPage;
|
||||
|
||||
function conditionsFailed(event) {
|
||||
// eslint-disable-next-line no-console
|
||||
@ -15,6 +16,8 @@
|
||||
function routeLoaded(event) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info('Caught event routeLoaded', event.detail)
|
||||
currentPage = event.detail.name;
|
||||
console.log('currentPage', currentPage);
|
||||
}
|
||||
|
||||
// Handles event bubbling up from nested routes
|
||||
@ -27,9 +30,25 @@
|
||||
|
||||
|
||||
<style lang="scss" global>
|
||||
@import "./css/custom.scss";
|
||||
@import "node_modules/spectre.css/src/spectre.scss";
|
||||
/* @import "./css/custom.scss";*/
|
||||
/*@import './fonts/fonts.css';
|
||||
@import './fonts/gotham.css';*/
|
||||
@import './fonts/fujicons.css';
|
||||
|
||||
.up,
|
||||
.ontime,
|
||||
.trendUp {
|
||||
color: #4CAF50 !important;
|
||||
}
|
||||
|
||||
.down,
|
||||
.delayed,
|
||||
.trendDown {
|
||||
color: #F44336 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<Header/>
|
||||
<Header page={currentPage}/>
|
||||
<Router {routes} on:conditionsFailed={conditionsFailed} on:routeLoaded={routeLoaded} on:routeEvent={routeEvent} />
|
||||
|
@ -1,32 +1,51 @@
|
||||
<script>
|
||||
import {link, push, pop, replace, location, querystring} from 'svelte-spa-router';
|
||||
import active from 'svelte-spa-router/active'
|
||||
import {pop} from 'svelte-spa-router';
|
||||
|
||||
export let page;
|
||||
let titleText = 'Traintimes';
|
||||
let currentMode = 1;
|
||||
$: currentMode = (page === 'Home') ? 0 : 1;
|
||||
|
||||
$: titleText = $location;
|
||||
function goBack() {
|
||||
console.log('>> Header:goBack');
|
||||
pop();
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/*#appbar-more-vert {
|
||||
width: 31px;
|
||||
height: 31px;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#appbar-more-vert {
|
||||
line-height: 31px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
}*/
|
||||
</style>
|
||||
|
||||
<header id="header">
|
||||
<div class="mui-appbar mui--appbar-line-height mui--z2">
|
||||
<header class="navbar bg-primary">
|
||||
|
||||
<section class="navbar-section">
|
||||
{#if currentMode === 1}
|
||||
<div class='mui-col-xs-1 mui-col-md-1 mui--appbar-height'>
|
||||
<a on:click={goBack} class="">
|
||||
<i class="fa-3x fa fa-back mui--align-middle" style="color:white;"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<span on:click={goBack} class="" >
|
||||
<i class="fa-2x fa fa-back" style="color:white;"></i>
|
||||
</span>
|
||||
{/if}
|
||||
<div class='mui-col-xs-11 mui-col-md-11 mui--appbar-height titleBar'>{titleText}</div>
|
||||
|
||||
</div>
|
||||
|
||||
<span class="text-bold navbar-brand mx-2 text-uppercase">{titleText}</span>
|
||||
</section>
|
||||
|
||||
|
||||
<section class="navbar-section">
|
||||
<a href="/#/settings" class="btn btn-link text-secondary">Settings</a>
|
||||
<a href="/#/favourites" class="btn btn-link text-secondary">Favourites</a>
|
||||
</section>
|
||||
|
||||
|
||||
</header>
|
||||
|
60
src/components/SettingsEditor.svelte
Normal file
60
src/components/SettingsEditor.svelte
Normal file
@ -0,0 +1,60 @@
|
||||
<script>
|
||||
import SettingsInput from "./SettingsInput.svelte";
|
||||
|
||||
let startStation;
|
||||
let destStation;
|
||||
let deleteEnabled = false;
|
||||
|
||||
function deleteItem(){
|
||||
console.log('>> Delete item');
|
||||
}
|
||||
|
||||
function closeEditor() {
|
||||
console.log('>> Close item');
|
||||
|
||||
}
|
||||
|
||||
function saveEditor() {
|
||||
console.log('>> Save editor');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
<span>SettingsEditor</span>
|
||||
<div class="mui-container ">
|
||||
<div class="mui-row card">
|
||||
<div class="mui--text-headline">New Route</div>
|
||||
<div class="mui--align-middle">
|
||||
<div class='mui-col-xs-12 mui-col-md-5'>
|
||||
<SettingsInput bind:returnValue={startStation} label="Departure Station" name="startStation"/>
|
||||
</div>
|
||||
<div class='mui-col-xs-12 mui-col-md-2'>
|
||||
<i class="fa fa-thick-arrow fa-2x mui--align-middle">
|
||||
</div>
|
||||
<div class='mui-col-xs-12 mui-col-md-5'>
|
||||
<SettingsInput bind:returnValue={destStation} label="Destination Station" name="destStation"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="my text-right">
|
||||
<button class="btn btn-danger btn-sm" id="delete" type="button" disabled={deleteEnabled} on:click={deleteItem}>
|
||||
Delete
|
||||
</button>
|
||||
<button class="btn btn-sm" type="button" on:click={closeEditor}>
|
||||
Close
|
||||
</button>
|
||||
<button class="btn btn-primary btn-sm" id="save" type="button" on:click={saveEditor}>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
52
src/components/SettingsInput.svelte
Normal file
52
src/components/SettingsInput.svelte
Normal file
@ -0,0 +1,52 @@
|
||||
<script>
|
||||
import {debounce} from '../libs/utils';
|
||||
import {onMount} from 'svelte';
|
||||
import {searchStation} from '../libs/stations';
|
||||
|
||||
export let returnValue;
|
||||
export let value;
|
||||
|
||||
export let name;
|
||||
export let label;
|
||||
|
||||
let debouncedDoSearch;
|
||||
let searchResults = [];
|
||||
|
||||
// $: visible = (searchResults.length > 0) ?
|
||||
|
||||
onMount(async () => {
|
||||
debouncedDoSearch = debounce(doSearch, 500);
|
||||
});
|
||||
|
||||
function doSearch() {
|
||||
returnValue = '';
|
||||
if (value.length >= 2)
|
||||
searchResults = searchStation(value);
|
||||
}
|
||||
|
||||
function selectItem(e) {
|
||||
let [id, name] = e.target.dataset.content.split(',');
|
||||
|
||||
returnValue = id;
|
||||
value = name;
|
||||
|
||||
searchResults = [];
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
<span class="mui-dropdown--right">
|
||||
<label for={name}>{label}</label>
|
||||
<input {name} on:keyup={debouncedDoSearch} bind:value />
|
||||
{#if searchResults.length > 0}
|
||||
<ul class="mui-dropdown__menu mui--is-open">
|
||||
{#each searchResults as item, index}
|
||||
<li><div on:click={selectItem} data-content="{item}">{item[1]} ({item[0]})</div></li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</span>
|
12
src/components/SettingsList.svelte
Normal file
12
src/components/SettingsList.svelte
Normal file
@ -0,0 +1,12 @@
|
||||
<script>
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
background: #f55a4e;
|
||||
padding: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<span>SettingsList</span>
|
@ -1,17 +1,90 @@
|
||||
<script>
|
||||
import {onMount, onDestroy} from 'svelte';
|
||||
import axios from 'axios';
|
||||
import {push} from 'svelte-spa-router';
|
||||
|
||||
import reducer from '../libs/reducer';
|
||||
|
||||
export let fromStation;
|
||||
export let destStation;
|
||||
|
||||
let list = []
|
||||
let otherDetails = {};
|
||||
let baseUrl = 'http://localhost:8100';
|
||||
let doUpdate = true;
|
||||
onMount(async () => {
|
||||
|
||||
await fetchData();
|
||||
});
|
||||
|
||||
async function fetchData() {
|
||||
if (doUpdate === true) {
|
||||
const routeUrl = `/gettrains?from=${fromStation}&to=${destStation}`
|
||||
const url = baseUrl.concat(routeUrl)
|
||||
await axios.get(url)
|
||||
.then((d) => {
|
||||
list = reducer.reduceTrainTimetable(d.data)
|
||||
otherDetails = reducer.reduceOtherDetails(d.data)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function viewService(e) {
|
||||
push(`/service/${e}`);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
background: #f55a4e;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<span>TimetableList</span>
|
||||
{fromStation} to {destStation}
|
||||
<section>
|
||||
{#if otherDetails.nrMessagesExist === true}
|
||||
<div class="mui--bg-danger mui--text-white nrccAlert" style="padding:2px;">
|
||||
<ul>
|
||||
{#each otherDetails.nrMessages as item}
|
||||
<li><i class="fa fa-info mui--align-middle"></i> {item.msg}
|
||||
{#if item.link}
|
||||
<a href={item.link}>{item.linkText}</a>
|
||||
{/if}
|
||||
|
||||
</li>
|
||||
{/each}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if list.length > 0}
|
||||
|
||||
{#each list as item}
|
||||
<div class="mui-row card mui--align-bottom">
|
||||
<div class="mui-col-xs-5 mui-col-md-4 mui--align-middle">
|
||||
<span on:click={viewService(item.serviceIdUrlSafe)}>{item.location}</span>
|
||||
<span class="mui--text-accent">{item.carriageCount}</span>
|
||||
<div>
|
||||
{#if item.via}
|
||||
<em class="mui--text-accent via">{item.via}</em>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mui-col-xs-2 mui-col-md-3 mui--text-center mui--align-middle time">{item.time}</div>
|
||||
|
||||
{#if item.isCancelled}
|
||||
<div class="mui-col-xs-5 mui-col-md-5 mui--text-center mui--align-middle delayed"><i class="fa fa-alert fa-1x mui--align-middle"></i>{item.cancel}</div>
|
||||
{:else}
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--text-center mui--align-middle {item.statusMode}">{item.status}</div>
|
||||
<div class="mui-col-xs-2 mui-col-md-2 mui--text-center mui--align-middle">{item.platform}</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
|
||||
{/if}
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
let status;
|
||||
let timetablePath;
|
||||
let interval = 0;
|
||||
let due = 0;
|
||||
|
||||
$: {
|
||||
status = (trainData.eta === 'On time') ? 'ontime' : 'delayed';
|
||||
@ -28,31 +29,47 @@
|
||||
onMount(async () => {
|
||||
if (LocalStorage.exists(`${startStation}${destStation}`)) {
|
||||
const fromLS = JSON.parse(LocalStorage.load(`${startStation}${destStation}`));
|
||||
trainData = {...trainData, ...fromLS};
|
||||
}
|
||||
|
||||
trainData = {...trainData, ...fromLS.trainData};
|
||||
due = fromLS.due;
|
||||
startStationName = fromLS.startStationName;
|
||||
destStationName = fromLS.destStationName;
|
||||
url = fromLS.url;
|
||||
} else {
|
||||
startStationName = findStation(startStation);
|
||||
destStationName = findStation(destStation);
|
||||
url = `${baseUrl}/getnexttraintimes?from=${startStation}&to=${destStation}`;
|
||||
|
||||
}
|
||||
|
||||
const now = new Date().getTime();
|
||||
if (now > due) {
|
||||
updateTrain();
|
||||
} else {
|
||||
interval = 0
|
||||
interval = setTimeout(updateTrain, due - now);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
clearInterval(interval);
|
||||
LocalStorage.save(`${startStation}${destStation}`, JSON.stringify(trainData));
|
||||
const store = {due, trainData, startStationName, destStationName, url};
|
||||
LocalStorage.save(`${startStation}${destStation}`, JSON.stringify(store));
|
||||
});
|
||||
|
||||
function onClick() {
|
||||
console.log('Onclick', timetablePath);
|
||||
push(timetablePath);
|
||||
}
|
||||
|
||||
async function updateTrain() {
|
||||
console.log(`Update: ${startStation} / ${destStation}`)
|
||||
const now = new Date()
|
||||
|
||||
const hours = now.getHours()
|
||||
const limit = (hours < 6) ? 3600000 : 95000
|
||||
const mod = limit - (now.getTime() % limit)
|
||||
due = now.getTime() + mod;
|
||||
|
||||
await getTrain()
|
||||
clearTimeout(interval)
|
||||
interval = 0
|
||||
@ -76,14 +93,29 @@
|
||||
margin: 6px 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.TRcard {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
min-height: 48px;
|
||||
margin: 0.5rem 8px;
|
||||
border-bottom-color: #666666;
|
||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2),
|
||||
0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||
vertical-align: middle;
|
||||
padding: 0.5rem 0;
|
||||
border-radius: 0.1rem;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<div class="mui-row card">
|
||||
<div class='mui-col-xs-7 mui-col-md-7 entry'>
|
||||
<div class="columns TRcard">
|
||||
<div class='column col-7 entry'>
|
||||
<div>{startStationName}</div>
|
||||
<div>{destStationName}</div>
|
||||
</div>
|
||||
<div class='mui-col-xs-5 mui-col-md-5 mui--text-right'>
|
||||
<span class="mui-btn mui-btn--flat time {status}" on:click={onClick}>{displayTime}</span>
|
||||
<div class='column col-5 text-right entry'>
|
||||
<span class="btn {status}" on:click={onClick}>{displayTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,12 +1,64 @@
|
||||
<script>
|
||||
import {onMount, onDestroy} from 'svelte';
|
||||
import {minuteFloor, LocalStorage} from '../libs/utils'
|
||||
import axios from 'axios';
|
||||
import reducer from '../libs/reducer';
|
||||
|
||||
export let serviceId;
|
||||
|
||||
let list = [];
|
||||
let baseUrl = 'http://localhost:8100';
|
||||
let doUpdate = true;
|
||||
let serviceInterval;
|
||||
|
||||
onMount(async () => {
|
||||
fetchServiceData();
|
||||
|
||||
serviceInterval = setInterval(() => {
|
||||
console.log('Do service update')
|
||||
fetchServiceData()
|
||||
}, 120000);
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
clearInterval(serviceInterval);
|
||||
});
|
||||
|
||||
function fetchServiceData() {
|
||||
console.log('>> TrainService: fetchServiceData');
|
||||
// http://localhost:8100/getservice?serviceid=TDKWvQdeuviRyNYP7lk7gA
|
||||
if (doUpdate === true) {
|
||||
const routeUrl = `/getservice?serviceid=${serviceId}`
|
||||
const url = baseUrl.concat(routeUrl)
|
||||
axios.get(url)
|
||||
.then((d) => {
|
||||
console.log(d);
|
||||
list = reducer.reduceTrainService(d.data);
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
background: #f55a4e;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<span>TrainService</span>
|
||||
<section>
|
||||
<div class="mui-row card mui--align-bottom">
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Station</div>
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Due</div>
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Estimated</div>
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">Arrived</div>
|
||||
</div>
|
||||
{#if list.length > 0}
|
||||
{#each list as item}
|
||||
<div class="mui-row card mui--align-bottom {item.classCancel}">
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">{item.locationName}</div>
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle">{item.st}</div>
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle {item.etMode}">{item.et}</div>
|
||||
<div class="mui-col-xs-3 mui-col-md-3 mui--align-middle {item.atMode}">{item.at}</div>
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
</section>
|
||||
|
132
src/libs/reducer.js
Normal file
132
src/libs/reducer.js
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Created by WebStorm.
|
||||
* User: martin
|
||||
* Date: 20/04/2020
|
||||
* Time: 12:01
|
||||
|
||||
*/
|
||||
|
||||
const reducer = {
|
||||
reduceOtherDetails (data) {
|
||||
const nrMessages = [];
|
||||
// we have national rail messages so put a box at the top
|
||||
// <div class="mui--bg-danger .mui--text-white" style="height:10px;"></div>
|
||||
let index = 0;
|
||||
const anchorRegex = /<\s*[aA].*?href\s*=\s*(?:"|')(.*?)(?:"|')[^>]*>(.*?)<\s*?\/\s*?[aA]\s*?>/;
|
||||
|
||||
if (typeof data.nrccMessages === 'object' && data.nrccMessages !== null)
|
||||
for (const item of data.nrccMessages) {
|
||||
const newObj = { 'index': 0, 'msg': '', 'link': null, 'linkText': '' };
|
||||
|
||||
let msg = item.value.replace(' ">', '">').replace('</A>', '</a>').replace('<A ', '<a ').replace(/<\/*[pP]>/gi, '');
|
||||
const anchor = anchorRegex.exec(item.value);
|
||||
msg = msg.replace(anchorRegex, '');
|
||||
|
||||
newObj.index = index;
|
||||
newObj.msg = msg;
|
||||
if (anchor !== null) {
|
||||
newObj.link = anchor[1];
|
||||
newObj.linkText = anchor[2];
|
||||
}
|
||||
|
||||
nrMessages.push(newObj);
|
||||
index++;
|
||||
}
|
||||
|
||||
return { nrMessages, 'nrMessagesExist': nrMessages.length > 0 };
|
||||
},
|
||||
reduceTrainTimetable (data) {
|
||||
const services = [];
|
||||
let ws = '';
|
||||
const symbol = ['💠', '🚉'];
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
console.log('>> reduceTrainService');
|
||||
console.log(data);
|
||||
if (typeof data.trainServices === 'object' && data.trainServices !== null)
|
||||
for (const item of data.trainServices) {
|
||||
// console.log(item)
|
||||
const dest = item.destination[0];
|
||||
const via = dest.via !== null ? dest.via : '';
|
||||
const platform = item.platform !== null ? item.platform : `${symbol[0]}`;
|
||||
// 🚉 💠
|
||||
// const time = item.sta !== null ? item.sta : `<em class="mui--text-accent-secondary">D</em> ${item.std}`
|
||||
const time = item.sta !== null ? item.sta : `D ${item.std}`;
|
||||
const isDeparture = item.sta === null;
|
||||
const status = item.eta !== null ? item.eta : item.etd;
|
||||
const trainLength = item.length;
|
||||
|
||||
const carriageCount = (trainLength > 0) ? ` (${trainLength} 🚃) ` : '';
|
||||
|
||||
const statusMode = (status.toLowerCase() === 'on time') ? 'ontime' : 'delayed';
|
||||
const delayReason = (item.delayReason !== null) ? item.delayReason : '';
|
||||
|
||||
const cancelReason = (item.cancelReason !== null) ? item.cancelReason : 'No reason given 🤷';
|
||||
|
||||
const serviceIdUrlSafe = item.serviceIdUrlSafe;
|
||||
|
||||
services.push({ 'location': dest.locationName, 'time': time, 'status': status, 'platform': platform, 'cancel': cancelReason, 'type': 'train', 'delay': delayReason, 'carriageCount': carriageCount, 'via': via, 'statusMode': statusMode, 'isCancelled': item.isCancelled, 'isDeparture': isDeparture, 'serviceIdUrlSafe': serviceIdUrlSafe });
|
||||
if (!item.isCancelled)
|
||||
ws = `${ws}<tr><td data-id="${item.serviceIdUrlSafe}" class="station">${dest.locationName}${carriageCount}${via}</td>
|
||||
<td class="mui--text-center time">${time}</td>
|
||||
<td class="mui--text-center ${statusMode}">${status}</td>
|
||||
<td class="mui--text-center">${platform}</td>
|
||||
</tr>${delayReason}`;
|
||||
else
|
||||
ws = `${ws}<tr><td>${dest.locationName} ${via}</td><td>${time}</td>
|
||||
<td colspan="2" class="delayed">❌ ${cancelReason}</td></tr>`;
|
||||
}
|
||||
|
||||
if (typeof data.busServices === 'object' && data.busServices !== null)
|
||||
for (const item of data.busServices) {
|
||||
const dest = item.destination[0];
|
||||
const via = dest.via !== null ? dest.via : '';
|
||||
const platform = item.platform !== null ? item.platform : '';
|
||||
const time = item.sta !== null ? item.sta : `D ${item.std}`;
|
||||
const status = item.eta !== null ? item.eta : item.etd;
|
||||
services.push({ 'location': dest.locationName, 'time': time, 'status': status, 'platform': platform, 'cancel': item.cancelReason, 'type': 'bus', 'via': via });
|
||||
}
|
||||
}
|
||||
console.log(services);
|
||||
|
||||
return services;
|
||||
},
|
||||
reduceTrainService (d) {
|
||||
let callingpoints = [];
|
||||
|
||||
const departureTime = d.sta || d.std;
|
||||
const departureStatus = d.eta || d.etd;
|
||||
|
||||
const currentLocation = { 'locationName': d.locationName, 'crs': d.crs, 'st': d.sta, 'et': d.eta, 'at': d.ata, 'isCancelled': d.isCancelled, 'length': d.length, 'detachFront': d.detachFront, 'adhocAlerts': d.adhocAlerts };
|
||||
|
||||
if (d.previousCallingPoints !== null)
|
||||
callingpoints = callingpoints.concat(d.previousCallingPoints[0].callingPoint);
|
||||
|
||||
callingpoints.push(currentLocation);
|
||||
|
||||
if (d.subsequentCallingPoints !== null)
|
||||
callingpoints = callingpoints.concat(d.subsequentCallingPoints[0].callingPoint);
|
||||
|
||||
callingpoints = callingpoints.map((item) => {
|
||||
// console.log(item)
|
||||
item.et = (item.et === null) ? '' : item.et;
|
||||
item.at = (item.at === null) ? '' : item.at;
|
||||
|
||||
item.etMode = (item.et.toLowerCase() === 'on time') ? 'ontime' : 'delayed';
|
||||
item.atMode = (item.at.toLowerCase() === 'on time') ? 'ontime' : 'delayed';
|
||||
item.delayReason = (item.delayReason !== null) ? item.delayReason : '';
|
||||
item.cancelReason = (item.cancelReason !== null) ? item.cancelReason : 'No reason given 🤷';
|
||||
item.classCancel = (item.isCancelled) ? 'cancelledRow' : '';
|
||||
|
||||
if (item.st === null && (item.et === null || item.et === '')) {
|
||||
item.st = `D ${departureTime}`;
|
||||
item.et = departureStatus;
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
|
||||
return callingpoints;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = reducer;
|
File diff suppressed because one or more lines are too long
@ -117,4 +117,73 @@ else
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { partOfDay, toHour, hourFloor, distance, maybePluralize, minuteFloor, LocalStorage };
|
||||
/**
|
||||
*
|
||||
* @param fn
|
||||
* @param time
|
||||
* @returns {Function}
|
||||
* @private
|
||||
*/
|
||||
function debounce(fn, time) {
|
||||
let timeout;
|
||||
|
||||
return function (...args) { // <-- not an arrow function
|
||||
const functionCall = () => fn.apply(this, args);
|
||||
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(functionCall, time);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param callback
|
||||
* @param limit
|
||||
* @returns {Function}
|
||||
* @private
|
||||
*/
|
||||
function throttle (callback, limit) {
|
||||
var wait = false;
|
||||
|
||||
return function () {
|
||||
if (!wait) {
|
||||
callback.apply(null, arguments);
|
||||
wait = true;
|
||||
setTimeout(function () {
|
||||
wait = false;
|
||||
}, limit);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param func
|
||||
* @returns {function(): *}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function once(func) {
|
||||
var alreadyCalled = false;
|
||||
var result;
|
||||
|
||||
return function() {
|
||||
if (!alreadyCalled) {
|
||||
result = func.apply(this, arguments);
|
||||
alreadyCalled = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
function isEmpty(obj) {
|
||||
for(const key in obj)
|
||||
if(obj.hasOwnProperty(key)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = { partOfDay, toHour, hourFloor, distance, maybePluralize, minuteFloor, debounce, throttle, once, isEmpty, LocalStorage };
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
</script>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="container">
|
||||
<TrainRoute destStation="glq" startStation="dbe"/>
|
||||
<TrainRoute destStation="dbe" startStation="glq"/>
|
||||
<TrainRoute destStation="glc" startStation="ptk"/>
|
||||
|
@ -1,12 +1,17 @@
|
||||
<script>
|
||||
import TrainService from "../components/TrainService.svelte";
|
||||
|
||||
export let params = {};
|
||||
|
||||
let serviceId = params.serviceId;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* {
|
||||
background: #f55a4e;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<span>Service</span>
|
||||
<div class="mui--appbar-height"></div>
|
||||
<div class="mui-container">
|
||||
<TrainService {serviceId}/>
|
||||
</div>
|
||||
|
||||
|
16
src/pages/Settings.svelte
Normal file
16
src/pages/Settings.svelte
Normal file
@ -0,0 +1,16 @@
|
||||
<script>
|
||||
import SettingsEditor from "../components/SettingsEditor.svelte";
|
||||
import SettingsList from "../components/SettingsList.svelte";
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<span>Settings</span>
|
||||
|
||||
<SettingsEditor/>
|
||||
<SettingsList/>
|
||||
</div>
|
@ -7,29 +7,20 @@
|
||||
|
||||
let fromStationName;
|
||||
let destStationName;
|
||||
let fromStation;
|
||||
let destStation;
|
||||
let fromStation = params.fromStation;
|
||||
let destStation= params.destStation;
|
||||
|
||||
onMount(async () => {
|
||||
|
||||
console.log('>> Timetable:', params);
|
||||
|
||||
fromStation = params.fromStation;
|
||||
destStation = params.destStation;
|
||||
fromStationName = findStation(fromStation);
|
||||
destStationName = findStation(destStation);
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
console.log('>> onDestroy Timetable')
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
<div class="mui--appbar-height"></div>
|
||||
<div class="mui-container">
|
||||
|
||||
<div class="container">
|
||||
<div>
|
||||
<div class="mui--text-center mui--text-accent">{fromStationName} TO {destStationName}</div>
|
||||
<TimetableList {fromStation} {destStation}/>
|
||||
|
@ -10,12 +10,14 @@
|
||||
import Home from './pages/Home.svelte';
|
||||
import Service from './pages/Service.svelte';
|
||||
import Timetable from './pages/Timetable.svelte';
|
||||
import Settings from './pages/Settings.svelte';
|
||||
import NotFound from './pages/NotFound.svelte';
|
||||
|
||||
const routes = new Map();
|
||||
routes.set('/', Home);
|
||||
routes.set('/timetable/:fromStation/:destStation', Timetable);
|
||||
routes.set('/service/:serviceId', Service);
|
||||
routes.set('/settings', Settings);
|
||||
routes.set('*', NotFound);
|
||||
|
||||
export default routes;
|
||||
|
Loading…
Reference in New Issue
Block a user