Implementation of:

- Authenticated PIS
  - Report Issue
  - About Page
This commit is contained in:
Fred Boniface 2023-06-26 15:34:01 +01:00
parent 86f60814d8
commit e2d107caa8
8 changed files with 253 additions and 36 deletions

View File

@ -0,0 +1,10 @@
<img src="/images/logo/wide_logo.svg" alt="Logo">
<style>
img {
width: 50%;
max-width: 250px;
margin-top: 55px;
margin-bottom: 55px;
}
</style>

View File

@ -11,7 +11,9 @@
{title: "Privacy Policy", path: "/more/privacy"}, {title: "Privacy Policy", path: "/more/privacy"},
{title: "Component Versions", path: "/more/versions"}, {title: "Component Versions", path: "/more/versions"},
{title: "Statictics", path: "/more/statistics"}, {title: "Statictics", path: "/more/statistics"},
{title: "Settings", path: "/more/settings"} {title: "Settings", path: "/more/settings"},
{title: "Report Issue", path: "/more/report"},
{title: "About", path: "/more/about"}
] ]
</script> </script>

View File

@ -0,0 +1,26 @@
<script>
import LargeLogo from "$lib/images/large-logo.svelte";
import Header from "$lib/navigation/header.svelte";
import Nav from "$lib/navigation/nav.svelte";
const title = "About";
</script>
<Header {title}/>
<LargeLogo />
<p class="neg">&copy; 2022-2023 Frederick Boniface</p>
<p>OwlBoard was created by train-crew for train-crew</p>
<p>I created OwlBoard in 2022 to freely give fast and easy access to the information
that we need every day.</p>
<p>Data sourced from: National Rail Enquiries, OwlBoard Project and Network Rail.</p>
<p>OwlBoard components are available under various Open Source licenses, see the
<a href="https://git.fjla.uk/OwlBoard" target="_blank">code repository</a>
for more information.
</p>
<Nav />
<style>
.neg {
margin-top: -40px;
margin-bottom: 40px;
}
</style>

View File

@ -0,0 +1,140 @@
<script>
import Header from "$lib/navigation/header.svelte";
import Island from "$lib/islands/island.svelte";
import Nav from "$lib/navigation/nav.svelte";
import { onMount } from "svelte";
const title = "Report Issue";
let reportType = "", reportSubject = "", reportMsg = "", reportCollected
onMount(async () => {
reportCollected = {
userAgent: navigator.userAgent,
browser: navigator.appName,
version: navigator.appVersion,
platform: navigator.platform,
viewport: `${window.innerWidth} x ${window.innerHeight}`,
};
})
let preFlight = false;
async function submit() {
console.log(reportType,reportSubject,reportMsg)
preFlight = true;
}
async function send() {
console.log("SEND DATA REQUESTED")
const formData = JSON.stringify({
labels: [reportType],
subject: reportSubject,
msg: `User Agent: ${reportCollected.userAgent}\n` +
`Browser: ${reportCollected.browser}\n` +
`BrowserVersion: ${reportCollected.version}\n` +
`Platform: ${reportCollected.platform}\n` +
`Viewport: ${reportCollected.viewport}\n\n\n` +
`User Message:\n` +
`${reportMsg}`
})
const url = `https://owlboard.info/api/v1/issue`
const options = {
method: "POST",
body: formData
}
const res = await fetch(url, options)
console.log(formData)
}
async function cancel() {
preFlight = false;
}
</script>
<Header {title} />
{#if !preFlight}
<p>Any data that you enter here will be visible publicly
<a href="https://git.fjla.uk/OwlBoard/backend/issues" target="_blank">here</a>
</p>
<p>You will be shown all of the collected data before the form is submitted.</p>
<form on:submit={submit}>
<select class="formInputs" name="type" bind:value={reportType} placeholder="Choose Category">
<option value="bug">Problem</option>
<option value="enhancement">Feature Request</option>
<option value="question">Question</option>
<option value="user-support">Unable to sign up</option>
</select>
<br>
<input class="formInputs" type="text" bind:value={reportSubject} placeholder="Subject">
<br>
<textarea class="formInputs" bind:value={reportMsg} placeholder="Enter your message..."/>
<br>
<button type="submit">Submit</button>
<button type="reset">Reset</button>
</form>
{:else}
<Island>
<h2>Device Data:</h2>
<p><span class="dataType">User Agent: </span>{reportCollected.userAgent}</p>
<p><span class="dataType">Browser: </span>{reportCollected.browser} - {reportCollected.version}</p>
<p><span class="dataType">Platform: </span>{reportCollected.platform}</p>
<p><span class="dataType">Viewport: </span> {reportCollected.viewport}</p>
<h2>Reported Data:</h2>
<p><span class="dataType">Report Type: </span>{reportType}</p>
<p>{reportSubject}</p>
<p>{reportMsg}</p>
<button class="overlayButtons" on:click={send}>Send</button>
<button class="overlayButtons" on:click={cancel}>Cancel</button>
</Island>
{/if}
<Nav />
<style>
select {
text-align: center;
border: none;
border-radius: 50px;
height: 30px;
background-color: white;
}
.formInputs {
margin: 10px;
font-family: urwgothic, sans-serif;
font-size: 16px;
border: none;
width: 50%;
max-width: 250px;
min-width: 100px;
}
input {
text-align: center;
border-radius: 50px;
height: 30px;
}
textarea {
text-align: left;
border-radius: 10px;
padding-left: 5px;
padding-right: 5px;
height: 30vh;
min-height: 150px;
max-height: 400px;
}
button {
background-color: var(--overlay-color);
color: white;
font-family: urwgothic, sans-serif;
font-size: 16px;
border: none;
border-radius: 50px;
width: 25%;
height: 30px;
max-width: 100px;
}
h2 {color: white;}
.dataType {color: white;}
.overlayButtons {
background-color: var(--main-bg-color);
}
</style>

View File

@ -1,7 +1,9 @@
<script> <script>
import Header from '$lib/navigation/header.svelte' import Header from '$lib/navigation/header.svelte'
import Loading from '$lib/navigation/loading.svelte';
import Nav from '$lib/navigation/nav.svelte' import Nav from '$lib/navigation/nav.svelte'
const title = "Statistics" const title = "Statistics"
let isLoading = true;
let update_timetable = "", update_corpus="", let update_timetable = "", update_corpus="",
update_pis = "", count_ldbws_api="", update_pis = "", count_ldbws_api="",
@ -14,8 +16,11 @@
</script> </script>
<Header {title} /> <Header {title} />
{#if isLoading}
<Loading />
{:else}
<h2>Last Update</h2> <h2>Last Update</h2>
<p>Timetable Data: <span>{update_timetable}</span></p> <p>Timetable Data: <span>{update_timetable}</span></p>
<p>Location Reference Data: <span>{update_corpus}</span></p> <p>Location Reference Data: <span>{update_corpus}</span></p>
@ -37,5 +42,6 @@
<p>Stations: <span>{length_stations}</span></p> <p>Stations: <span>{length_stations}</span></p>
<p>PIS: <span>{length_pis}</span></p> <p>PIS: <span>{length_pis}</span></p>
<p>Timetable: <span>{length_timetable}</span></p> <p>Timetable: <span>{length_timetable}</span></p>
{/if}
<Nav /> <Nav />

View File

@ -1,27 +1,28 @@
<script> <script>
import Header from '$lib/navigation/header.svelte' import Header from '$lib/navigation/header.svelte'
import Island from '$lib/islands/island.svelte';
import Loading from '$lib/navigation/loading.svelte';
import Nav from '$lib/navigation/nav.svelte' import Nav from '$lib/navigation/nav.svelte'
import LargeLogo from '$lib/images/large-logo.svelte';
const title = "Versions" const title = "Versions"
const variable = {title:""};
let web_ver = "Unknown", srv_ver = "Unknown", dbm_ver = "Unknown" let web_ver = "Unknown", srv_ver = "Unknown", dbm_ver = "Unknown",
isLoading = true;
</script> </script>
<Header {title} /> <Header {title} />
<img src="/images/logo/wide_logo.svg" alt="Logo"> <LargeLogo />
{#if isLoading}
<Loading/>
{:else}
<Island>
<p>Web-app Version<br>{web_ver}</p> <p>Web-app Version<br>{web_ver}</p>
<p>API Server Version<br>{srv_ver}</p> <p>API Server Version<br>{srv_ver}</p>
<p>DBManager Version<br>{dbm_ver}</p> <p>DBManager Version<br>{dbm_ver}</p>
</Island>
<Nav /> {/if}
<Nav />
<style>
img {
width: 50%;
max-width: 250px;
margin-top: 55px;
margin-bottom: 85px;
}
</style>

View File

@ -2,29 +2,41 @@
import Header from '$lib/navigation/header.svelte' import Header from '$lib/navigation/header.svelte'
import Nav from '$lib/navigation/nav.svelte' import Nav from '$lib/navigation/nav.svelte'
import Island from '$lib/islands/island.svelte'; import Island from '$lib/islands/island.svelte';
import Loading from '$lib/navigation/loading.svelte';
import { uuid } from '$lib/stores/uuid';
const title = "PIS Finder" const title = "PIS Finder"
const variables = {title: "Results"} const variables = {title: "Results"}
let entryPIS = ""; let entryPIS = "";
let entryStartCRS = ""; let entryStartCRS = "";
let entryEndCRS = ""; let entryEndCRS = "";
let data = [{operator: "gw", code: 4332, stops: ["bri","fit","bpw","yae","cdu","cnm","asc","wos","wof","mvl","gmv"]}, let data = [];
{operator: "xc", code: 3432, stops: ["bri","bpw","cnm","wos","wof","mvl","gmv"]}];
let error = false; let error = false;
let errMsg = "Unknown Error" let errMsg = "Unknown Error"
let isLoading = false
async function findByStartEnd() { async function findByStartEnd() {
isLoading = true
const url = `https://owlboard.info/api/v2/pis/byStartEnd/${entryStartCRS}/${entryEndCRS}` const url = `https://owlboard.info/api/v2/pis/byStartEnd/${entryStartCRS}/${entryEndCRS}`
fetchData(url); await fetchData(url);
isLoading = false
} }
async function findByPis() { async function findByPis() {
isLoading = true
const url = `https://owlboard.info/api/v2/pis/byCode/${entryPIS}` const url = `https://owlboard.info/api/v2/pis/byCode/${entryPIS}`
fetchData(url); await fetchData(url);
isLoading = false;
} }
async function fetchData(url) { async function fetchData(url) {
const res = await fetch(url); // Enable Auth const options = {
method: "GET",
headers: {
"uuid": $uuid
}
}
const res = await fetch(url, options); // Enable Auth
if (res.status == 401) { if (res.status == 401) {
errMsg = "You must be logged in to the staff version" errMsg = "You must be logged in to the staff version"
error = true error = true
@ -54,6 +66,10 @@
<Header {title} /> <Header {title} />
{#if isLoading}
<Loading/>
{/if}
{#if error} {#if error}
<Island {variables}> <Island {variables}>
<p class="error">{errMsg}</p> <p class="error">{errMsg}</p>
@ -68,15 +84,16 @@
</tr> </tr>
{#each data as item} {#each data as item}
<tr> <tr>
<td class="toc">{item.operator.toUpperCase()}</td> <td class="toc toc-data">{item.operator || "-"}</td>
<td class="code">{item.code}</td> <td class="code">{item.code}</td>
<td class="stops stops-data">{item.stops.join(", ").toUpperCase() + " "}</td> <td class="stops stops-data">{item.stops.join(" ")}</td>
</tr> </tr>
{/each} {/each}
</table> </table>
</Island> </Island>
{:else} {:else}
<p>To search by headcode use the Train Finder on the homepage</p> <p>To search by headcode use the Train Finder on the homepage</p>
<p>This feature is only supported for GWR West & Sleeper services</p>
<p class="label">Find By Start/End CRS:</p> <p class="label">Find By Start/End CRS:</p>
<form on:submit={findByStartEnd}> <form on:submit={findByStartEnd}>
<input type="text" maxlength="3" autocomplete="off" placeholder="Start" bind:value={entryStartCRS}> <input type="text" maxlength="3" autocomplete="off" placeholder="Start" bind:value={entryStartCRS}>
@ -140,9 +157,13 @@
.code { .code {
width: 20%; width: 20%;
} }
.toc-data {
text-transform: uppercase;
}
.stops-data { .stops-data {
text-align: left; text-align: left;
font-family: firamono, monospace; font-family: firamono, monospace;
text-transform: uppercase;
} }
.error { .error {
color: white; color: white;

View File

@ -1,12 +1,15 @@
<script> <script>
import Header from '$lib/navigation/header.svelte' import Header from '$lib/navigation/header.svelte'
import Nav from '$lib/navigation/nav.svelte' import Loading from '$lib/navigation/loading.svelte';
import Nav from '$lib/navigation/nav.svelte';
import { uuid } from '$lib/stores/uuid';
import { onMount } from 'svelte' import { onMount } from 'svelte'
let title = "Timetable Results" let title = "Timetable Results"
let id = "" let id = ""
let data = []; let data = [];
let isLoading = true;
$: { $: {
if (id) { if (id) {
@ -21,26 +24,34 @@
} }
onMount(async () => { onMount(async () => {
isLoading = true;
id = await getHeadcode() || ""; id = await getHeadcode() || "";
data = await fetchData(id); data = await fetchData(id);
await data; isLoading = false;
}) })
async function fetchData(id = "") { async function fetchData(id = "") {
const date = 'now'; const date = 'now';
const searchType = 'headcode' const searchType = 'headcode'
const options = {
method: "GET",
headers: {
"uuid": $uuid
}
}
const url = `https://owlboard.info/api/v2/timetable/train/${date}/${searchType}/${id}` const url = `https://owlboard.info/api/v2/timetable/train/${date}/${searchType}/${id}`
const res = await fetch(url); const res = await fetch(url, options);
return await res.json(); return await res.json();
} }
</script> </script>
<svelte:head>
<title>OwlBoard {title}</title>
</svelte:head>
<Header {title} /> <Header {title} />
{#if isLoading}
<Loading />
{/if}
{#each data as service} {#each data as service}
{#if service.stops[0]['publicDeparture']} {#if service.stops[0]['publicDeparture']}
<h2>GW: {service.stops[0]['publicDeparture']} {service.stops[0]['tiploc']} to {service.stops[service['stops'].length -1]['tiploc']}</h2> <h2>GW: {service.stops[0]['publicDeparture']} {service.stops[0]['tiploc']} to {service.stops[service['stops'].length -1]['tiploc']}</h2>