Compare commits
No commits in common. "8b9ba7f81bb5943ba577e47cf45bf6e752f73300" and "395c837dd1ee76308eadf70cdad983a6eb3b756d" have entirely different histories.
8b9ba7f81b
...
395c837dd1
|
@ -11,7 +11,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.4.3",
|
"@sveltejs/vite-plugin-svelte": "^2.4.3",
|
||||||
"@sveltejs/vite-plugin-svelte-inspector": "^1.0.4",
|
|
||||||
"@tsconfig/svelte": "^5.0.0",
|
"@tsconfig/svelte": "^5.0.0",
|
||||||
"@vitejs/plugin-basic-ssl": "^1.0.1",
|
"@vitejs/plugin-basic-ssl": "^1.0.1",
|
||||||
"svelte": "^4.1.2",
|
"svelte": "^4.1.2",
|
||||||
|
@ -22,7 +21,6 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@urql/svelte": "^4.0.4",
|
"@urql/svelte": "^4.0.4",
|
||||||
"geojson": "^0.5.0",
|
|
||||||
"graphql": "^16.8.1",
|
"graphql": "^16.8.1",
|
||||||
"graphql-ws": "^5.14.1",
|
"graphql-ws": "^5.14.1",
|
||||||
"subscriptions-transport-ws": "^0.11.0",
|
"subscriptions-transport-ws": "^0.11.0",
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
import { Client, setContextClient, cacheExchange, fetchExchange, subscriptionExchange } from '@urql/svelte';
|
import { Client, setContextClient, cacheExchange, fetchExchange, subscriptionExchange } from '@urql/svelte';
|
||||||
import { createClient as createWsClient } from 'graphql-ws';
|
import { createClient as createWsClient } from 'graphql-ws';
|
||||||
import { SubscriptionClient } from 'subscriptions-transport-ws';
|
import { SubscriptionClient } from 'subscriptions-transport-ws';
|
||||||
import { createJourneyPlannerClientContext, createVehiclesClientContext } from './lib/entur';
|
|
||||||
|
|
||||||
createVehiclesClientContext();
|
let subscriptionClient = new SubscriptionClient('wss://api.entur.io/realtime/v1/vehicles/subscriptions', { reconnect: true})
|
||||||
createJourneyPlannerClientContext();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let subscriptionClient = new SubscriptionClient('wss://api.entur.io/realtime/v1/vehicles/subscriptions', { reconnect: true})
|
let wsClient = createWsClient({
|
||||||
|
url: 'wss://api.entur.io/realtime/v1/vehicles/subscriptions'
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
|
||||||
let client = new Client({
|
let client = new Client({
|
||||||
url: 'https://api.entur.io/realtime/v1/vehicles/graphql',
|
url: 'https://api.entur.io/realtime/v1/vehicles/graphql',
|
||||||
|
@ -19,13 +20,21 @@
|
||||||
subscriptionExchange({
|
subscriptionExchange({
|
||||||
forwardSubscription(request) {
|
forwardSubscription(request) {
|
||||||
return subscriptionClient.request(request);
|
return subscriptionClient.request(request);
|
||||||
|
/*
|
||||||
|
const input = { ...request, query: request.query || "" };
|
||||||
|
return {
|
||||||
|
subscribe(sink) {
|
||||||
|
const unsubscribe = wsClient.subscribe(input, sink);
|
||||||
|
return { unsubscribe };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
setContextClient(client)
|
setContextClient(client)
|
||||||
*/
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: rgba(255, 255, 255, 0.87);
|
||||||
|
background-color: #242424;
|
||||||
|
|
||||||
font-synthesis: none;
|
font-synthesis: none;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { GeoJSON, LineLayer, MarkerLayer } from "svelte-maplibre";
|
|
||||||
import { getJourneyPlannerClientContext, quaysToGeoJSON } from "./entur";
|
|
||||||
import { gql, queryStore } from "@urql/svelte";
|
|
||||||
import type { GeoJSON as IGeoJSON } from "geojson";
|
|
||||||
|
|
||||||
export let lineRef: string | null = null;
|
|
||||||
console.log(lineRef + "hi")
|
|
||||||
|
|
||||||
$: queryResult = queryStore({
|
|
||||||
client: getJourneyPlannerClientContext(),
|
|
||||||
query: gql`
|
|
||||||
query ($line: ID!) {
|
|
||||||
line(id: $line) {
|
|
||||||
publicCode
|
|
||||||
name
|
|
||||||
journeyPatterns {
|
|
||||||
directionType
|
|
||||||
quays {
|
|
||||||
longitude
|
|
||||||
latitude
|
|
||||||
name
|
|
||||||
publicCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: { line: lineRef }
|
|
||||||
})
|
|
||||||
|
|
||||||
let data: IGeoJSON;
|
|
||||||
|
|
||||||
$: if ($queryResult.data) {
|
|
||||||
data = quaysToGeoJSON(...$queryResult.data.line.journeyPatterns.map((x: any) => x.quays)) as IGeoJSON
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
h1 {
|
|
||||||
z-index: 1000;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
z-index: 100;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0.5em;
|
|
||||||
left: 5em;
|
|
||||||
right: 5em;
|
|
||||||
max-height: 10em;
|
|
||||||
overflow-y: scroll;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{#if lineRef != null}
|
|
||||||
<GeoJSON data={data}>
|
|
||||||
<LineLayer
|
|
||||||
|
|
||||||
layout={{ 'line-cap': 'round', 'line-join': 'round' }}
|
|
||||||
paint={{
|
|
||||||
'line-width': 5,
|
|
||||||
'line-dasharray': [5, 2],
|
|
||||||
'line-color': '#008800',
|
|
||||||
'line-opacity': 0.8,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<MarkerLayer applyToClusters={false} let:feature>
|
|
||||||
<span>{feature.properties?.name ?? "N/A"}</span>
|
|
||||||
</MarkerLayer>
|
|
||||||
</GeoJSON>
|
|
||||||
{/if}
|
|
|
@ -1,34 +1,18 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Control, ControlButton, ControlGroup, LineLayer, MapLibre, Marker, NavigationControl, Popup, mapContext, GeoJSON, MarkerLayer } from 'svelte-maplibre';
|
import { Control, ControlButton, ControlGroup, MapLibre, Marker, NavigationControl, Popup, mapContext } from 'svelte-maplibre';
|
||||||
import VehicleMarker from "./VehicleMarker.svelte"
|
import VehicleMarker from "./VehicleMarker.svelte"
|
||||||
import {writable, type Writable} from 'svelte/store';
|
import {writable} from 'svelte/store';
|
||||||
import { queryStore, gql, getContextClient, subscriptionStore } from '@urql/svelte';
|
import { queryStore, gql, getContextClient, subscriptionStore } from '@urql/svelte';
|
||||||
import { getJourneyPlannerClientContext, getVehiclesClientContext, quaysToGeoJSON } from './entur';
|
|
||||||
import { buses, selectedLine } from './store';
|
|
||||||
import LineMarker from './LineMarker.svelte';
|
|
||||||
import type { GeoJSON as IGeoJSON } from 'geojson';
|
|
||||||
|
|
||||||
interface Vehicle {
|
|
||||||
vehicleId: string;
|
|
||||||
location: {longitude: number, latitude: number};
|
|
||||||
bearing: number;
|
|
||||||
line: {lineRef: string, lineName: string, publicCode: string};
|
|
||||||
originName: string;
|
|
||||||
destinationName: string;
|
|
||||||
occupancy: string;
|
|
||||||
delay: number;
|
|
||||||
vehicleStatus: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
$: bearing = 0.0;
|
$: bearing = 0.0;
|
||||||
setInterval(() => bearing = 0, 100)
|
setInterval(() => bearing = 0, 100)
|
||||||
|
|
||||||
$: iconSize = 35;
|
$: iconSize = 30;
|
||||||
|
|
||||||
let dataStore: Writable<Record<string, Vehicle>> = writable({});
|
let dataStore = writable({});
|
||||||
|
|
||||||
let vehiclesInit = queryStore({
|
let vehiclesInit = queryStore({
|
||||||
client: getVehiclesClientContext(),
|
client: getContextClient(),
|
||||||
query: gql`
|
query: gql`
|
||||||
query {
|
query {
|
||||||
vehicles(codespaceId:"SKY") {
|
vehicles(codespaceId:"SKY") {
|
||||||
|
@ -57,7 +41,7 @@ import { buses, selectedLine } from './store';
|
||||||
|
|
||||||
vehiclesInit.subscribe((v) => {
|
vehiclesInit.subscribe((v) => {
|
||||||
if (v.data) {
|
if (v.data) {
|
||||||
for (const veh of v.data.vehicles.filter((x: Vehicle) => ["AT_ORIGIN", "IN_PROGRESS", "OFF_ROUTE"].includes(x.vehicleStatus))) {
|
for (const veh of v.data.vehicles.filter(x => ["AT_ORIGIN", "IN_PROGRESS", "OFF_ROUTE"].includes(x.vehicleStatus))) {
|
||||||
dataStore.update((d: any) => {
|
dataStore.update((d: any) => {
|
||||||
d[veh.vehicleId] = veh;
|
d[veh.vehicleId] = veh;
|
||||||
return d;
|
return d;
|
||||||
|
@ -67,10 +51,10 @@ vehiclesInit.subscribe((v) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const vehicles = subscriptionStore({
|
const vehicles = subscriptionStore({
|
||||||
client: getVehiclesClientContext(),
|
client: getContextClient(),
|
||||||
query: gql`
|
query: gql`
|
||||||
subscription {
|
subscription {
|
||||||
vehicles(codespaceId: "SKY") {
|
vehicles(codespaceId:"SKY") {
|
||||||
vehicleId
|
vehicleId
|
||||||
line {
|
line {
|
||||||
lineRef
|
lineRef
|
||||||
|
@ -101,44 +85,10 @@ vehiclesInit.subscribe((v) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$: queryResult = queryStore({
|
|
||||||
client: getJourneyPlannerClientContext(),
|
|
||||||
query: gql`
|
|
||||||
query ($line: ID!) {
|
|
||||||
line(id: $line) {
|
|
||||||
publicCode
|
|
||||||
name
|
|
||||||
journeyPatterns {
|
|
||||||
directionType
|
|
||||||
quays {
|
|
||||||
longitude
|
|
||||||
latitude
|
|
||||||
name
|
|
||||||
publicCode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: { line: $selectedLine }
|
|
||||||
})
|
|
||||||
|
|
||||||
let data: IGeoJSON;
|
|
||||||
|
|
||||||
$: if ($queryResult.data) {
|
|
||||||
data = quaysToGeoJSON(...$queryResult.data.line.journeyPatterns.map((x: any) => x.quays)) as IGeoJSON
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
div.quay {
|
|
||||||
z-index: -1;
|
|
||||||
padding: 0.1em;
|
|
||||||
background-color: #baddad;
|
|
||||||
border: 1px dotted #333;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -162,34 +112,14 @@ vehiclesInit.subscribe((v) => {
|
||||||
<ControlButton on:click={() => iconSize = 20}>S</ControlButton>
|
<ControlButton on:click={() => iconSize = 20}>S</ControlButton>
|
||||||
</ControlGroup>
|
</ControlGroup>
|
||||||
</Control>
|
</Control>
|
||||||
<Control position="bottom-right">
|
|
||||||
<ControlGroup>
|
|
||||||
<ControlButton>{$buses}</ControlButton>
|
|
||||||
</ControlGroup>
|
|
||||||
</Control>
|
|
||||||
|
|
||||||
{#if $selectedLine != null}
|
|
||||||
<p id="foo">
|
|
||||||
<GeoJSON {data}>
|
|
||||||
<LineLayer
|
|
||||||
paint={{'line-width': 5, 'line-color': 'orange'}}
|
|
||||||
beforeLayerType={(l) => {console.log(l.type); return false}}
|
|
||||||
/>
|
|
||||||
<MarkerLayer let:feature>
|
|
||||||
<div class="quay">{feature.properties?.name ?? ""}</div>
|
|
||||||
</MarkerLayer>
|
|
||||||
</GeoJSON>
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if $vehicles}
|
{#if $vehicles}
|
||||||
{#each Object.entries($dataStore) as [id, vehicle]}
|
{#each Object.entries($dataStore) as [id, vehicle]}
|
||||||
<VehicleMarker
|
<VehicleMarker
|
||||||
lngLat={[vehicle.location.longitude, vehicle.location.latitude]}
|
lngLat={[vehicle.location.longitude, vehicle.location.latitude]}
|
||||||
lineRef={vehicle.line.lineRef}
|
|
||||||
lineNumber={vehicle.line.publicCode}
|
lineNumber={vehicle.line.publicCode}
|
||||||
lineName={vehicle.line.lineName}
|
lineName={vehicle.line.lineName}
|
||||||
bearing={vehicle.bearing}
|
bearing={vehicle.bearing + map?.getBearing() % 360}
|
||||||
origin={vehicle.originName}
|
origin={vehicle.originName}
|
||||||
destination={vehicle.destinationName}
|
destination={vehicle.destinationName}
|
||||||
iconSize={iconSize}
|
iconSize={iconSize}
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Marker, Popup } from 'svelte-maplibre';
|
import { Marker, Popup } from 'svelte-maplibre';
|
||||||
import Delay from './micro/Delay.svelte';
|
|
||||||
import Bus from './micro/Bus.svelte';
|
|
||||||
import { buses, selectedLine } from './store';
|
|
||||||
import { onDestroy } from 'svelte';
|
|
||||||
|
|
||||||
export let lngLat: [number, number];
|
export let lngLat: [number, number];
|
||||||
export let lineRef: string | null = null;
|
|
||||||
export let lineNumber: string;
|
export let lineNumber: string;
|
||||||
export let lineName: string = "N/A";
|
export let lineName: string = "N/A";
|
||||||
export let bearing: number = 0.0;
|
export let bearing: number = 0.0;
|
||||||
|
@ -16,43 +11,34 @@ export let iconSize: number = 30;
|
||||||
export let delay: number = 0;
|
export let delay: number = 0;
|
||||||
export let occupancy: string = "Unknown";
|
export let occupancy: string = "Unknown";
|
||||||
|
|
||||||
$buses += 1
|
console.log("lineNumber: %s", lineNumber)
|
||||||
onDestroy(() => {
|
|
||||||
$buses -= 1
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const clickHandler = () => {
|
|
||||||
if ($selectedLine == lineRef)
|
|
||||||
selectedLine.set(null)
|
|
||||||
else
|
|
||||||
selectedLine.set(lineRef)
|
|
||||||
console.log("click\t%s", $selectedLine)
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
svg text {
|
||||||
div.popover-content {
|
font-weight: 600;
|
||||||
color: black;
|
font-size: 1.25rem;
|
||||||
background-color: white;
|
color: black;
|
||||||
}
|
background-color: white;;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<Marker {lngLat} on:click={clickHandler}>
|
<Marker {lngLat}>
|
||||||
<Bus {iconSize} {bearing} face={lineNumber} />
|
<svg width={iconSize} height={iconSize} viewBox="0 0 50 50">
|
||||||
|
<g transform="rotate({bearing}, 25, 25)">
|
||||||
|
<circle cx="25" cy="25" r="24" stroke="black" stroke-width="3" fill="red" />
|
||||||
|
<circle cx="25" cy="5" r="5" stroke="black" stroke-width="1.5" fill="white" />
|
||||||
|
</g>
|
||||||
|
<text x="25" y="32.5" text-anchor="middle">{lineNumber ?? "🚍"}</text>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
|
||||||
<Popup openOn="hover" offset={[0, -10]}>
|
<Popup openOn="hover" offset={[0, -10]}>
|
||||||
<div class="popover-content">
|
<h4>{lineNumber}: {lineName}</h4>
|
||||||
<h4>{lineNumber}: {lineName}</h4>
|
<p>Going from <i>{origin}</i> to <i>{destination}</i></p>
|
||||||
<p>
|
<ul>
|
||||||
Going from <i>{origin}</i> to <i>{destination}</i>
|
<li>Occupancy: {occupancy}</li>
|
||||||
<br />
|
<li>Delay: {delay}</li>
|
||||||
<Delay {delay} />
|
</ul>
|
||||||
<br />
|
|
||||||
{occupancy}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</Popup>
|
</Popup>
|
||||||
</Marker>
|
</Marker>
|
|
@ -1,83 +0,0 @@
|
||||||
import { Client, cacheExchange, fetchExchange, subscriptionExchange } from "@urql/svelte";
|
|
||||||
import { SubscriptionClient } from "subscriptions-transport-ws";
|
|
||||||
import { setContext, getContext } from "svelte";
|
|
||||||
|
|
||||||
|
|
||||||
export function createVehiclesClientContext() {
|
|
||||||
let subscriptionClient = new SubscriptionClient('wss://api.entur.io/realtime/v1/vehicles/subscriptions', { reconnect: true})
|
|
||||||
|
|
||||||
let client = new Client({
|
|
||||||
url: 'https://api.entur.io/realtime/v1/vehicles/graphql',
|
|
||||||
exchanges: [
|
|
||||||
fetchExchange,
|
|
||||||
cacheExchange,
|
|
||||||
subscriptionExchange({
|
|
||||||
forwardSubscription(request) {
|
|
||||||
return subscriptionClient.request(request);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
setContext("entur-graphql-vehiclepositions-client", client)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getVehiclesClientContext(): Client {
|
|
||||||
return getContext("entur-graphql-vehiclepositions-client")
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createJourneyPlannerClientContext() {
|
|
||||||
let client = new Client({
|
|
||||||
url: 'https://api.entur.io/journey-planner/v3/graphql',
|
|
||||||
exchanges: [
|
|
||||||
fetchExchange,
|
|
||||||
cacheExchange,
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
setContext("entur-graphql-journeyplannet-client", client)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getJourneyPlannerClientContext(): Client {
|
|
||||||
return getContext("entur-graphql-journeyplannet-client")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export interface Quay {
|
|
||||||
longitude: number;
|
|
||||||
latitude: number;
|
|
||||||
name: string;
|
|
||||||
publicCode: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function quaysToGeoJSON(...quayCollections: Array<Array<Quay>>) {
|
|
||||||
const multilineString = {
|
|
||||||
type: "Feature",
|
|
||||||
properties: {},
|
|
||||||
geometry: {
|
|
||||||
type: "MultiLineString",
|
|
||||||
coordinates: quayCollections.map((quays => quays.map(quay => [quay.longitude, quay.latitude]))),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const features = quayCollections.map(quays =>
|
|
||||||
quays.map(quay => {
|
|
||||||
return {
|
|
||||||
type: "Feature",
|
|
||||||
properties: {
|
|
||||||
name: quay.name + (quay.publicCode ? (" " + quay.publicCode) : "")
|
|
||||||
},
|
|
||||||
geometry: {
|
|
||||||
type: "Point",
|
|
||||||
coordinates: [quay.longitude, quay.latitude]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "FeatureCollection",
|
|
||||||
features: [
|
|
||||||
multilineString,
|
|
||||||
...features.flat(1)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
export let iconSize = 35;
|
|
||||||
export let bearing = 0;
|
|
||||||
export let face: string = "";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
svg {
|
|
||||||
z-index: -1000;
|
|
||||||
}
|
|
||||||
text {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
color: darkgray;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<svg width={iconSize * 1.2} height={iconSize * 1.2} viewBox="-10 -10 70 70">
|
|
||||||
<g transform="rotate({bearing}, 25, 25)">
|
|
||||||
<!--
|
|
||||||
<circle cx="25" cy="25" r="24" stroke="black" stroke-width="3" fill="red" />
|
|
||||||
<circle cx="25" cy="5" r="5" stroke="black" stroke-width="1.5" fill="white" />
|
|
||||||
-->
|
|
||||||
<path d="M 25 0 l -25 10 v 40 l 25 -10 l 25 10 v -40 l -25 -10" fill="green" stroke="black" stroke-width="3" />
|
|
||||||
</g>
|
|
||||||
<text x="25" y="32.5" text-anchor="middle" fill="white" stroke="black" stroke-width="0.5">{face ?? "🚍"}</text>
|
|
||||||
</svg>
|
|
|
@ -1,22 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
/** The delay in seconds.*/
|
|
||||||
export let delay: number;
|
|
||||||
|
|
||||||
let delay_min = Math.round(delay / 60);
|
|
||||||
let delay_abs = Math.abs(delay_min);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
The bus is
|
|
||||||
{#if delay_min == 1}
|
|
||||||
<span>one minute delayed.</span>
|
|
||||||
{:else if delay_min > 1}
|
|
||||||
<span>{delay_abs} minutes delayed.</span>
|
|
||||||
{:else if delay_min == -1}
|
|
||||||
<span>one minute ahead of schedule.</span>
|
|
||||||
{:else if delay_min < -1}
|
|
||||||
<span>{delay_abs} minutes ahead of schedule.</span>
|
|
||||||
{:else}
|
|
||||||
<span>on time.</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { writable, type Writable } from "svelte/store";
|
|
||||||
|
|
||||||
export const buses = writable(0);
|
|
||||||
|
|
||||||
export const selectedLine: Writable<string|null> = writable(null);
|
|
|
@ -4,11 +4,4 @@ export default {
|
||||||
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
|
||||||
// for more information about preprocessors
|
// for more information about preprocessors
|
||||||
preprocess: vitePreprocess(),
|
preprocess: vitePreprocess(),
|
||||||
vitePlugin: {
|
|
||||||
inspector: {
|
|
||||||
toggleKeyCombo: 'meta-shift',
|
|
||||||
showToggleButton: 'always',
|
|
||||||
toggleButtonPos: 'bottom-right'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||||
import basicSsl from '@vitejs/plugin-basic-ssl'
|
import basicSsl from '@vitejs/plugin-basic-ssl'
|
||||||
import { svelteInspector } from '@sveltejs/vite-plugin-svelte-inspector'
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
svelte(),
|
svelte(),
|
||||||
//basicSsl(),
|
//basicSsl(),
|
||||||
/*svelteInspector({
|
|
||||||
showToggleButton: 'always',
|
|
||||||
toggleButtonPos: 'top-right',
|
|
||||||
openKey: 'meta-shift'
|
|
||||||
})*/
|
|
||||||
],
|
],
|
||||||
base: "",
|
base: "",
|
||||||
})
|
})
|
||||||
|
|
|
@ -232,7 +232,7 @@
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte-inspector@^1.0.4":
|
"@sveltejs/vite-plugin-svelte-inspector@^1.0.4":
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-1.0.4.tgz#c99fcb73aaa845a3e2c0563409aeb3ee0b863add"
|
resolved "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-1.0.4.tgz"
|
||||||
integrity sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==
|
integrity sha512-zjiuZ3yydBtwpF3bj0kQNV0YXe+iKE545QGZVTaylW3eAzFr+pJ/cwK8lZEaRp4JtaJXhD5DyWAV4AxLh6DgaQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
|
@ -594,11 +594,6 @@ geojson-vt@^3.2.1:
|
||||||
resolved "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz"
|
resolved "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz"
|
||||||
integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==
|
integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==
|
||||||
|
|
||||||
geojson@^0.5.0:
|
|
||||||
version "0.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/geojson/-/geojson-0.5.0.tgz#3cd6c96399be65b56ee55596116fe9191ce701c0"
|
|
||||||
integrity sha512-/Bx5lEn+qRF4TfQ5aLu6NH+UKtvIv7Lhc487y/c8BdludrCTpiWf9wyI0RTyqg49MFefIAvFDuEi5Dfd/zgNxQ==
|
|
||||||
|
|
||||||
get-stream@^6.0.1:
|
get-stream@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz"
|
||||||
|
|
Loading…
Reference in New Issue