diff options
Diffstat (limited to 'web/index.js')
| -rw-r--r-- | web/index.js | 97 |
1 files changed, 84 insertions, 13 deletions
diff --git a/web/index.js b/web/index.js index e8accf0..63292aa 100644 --- a/web/index.js +++ b/web/index.js | |||
| @@ -7,6 +7,50 @@ closeButton.addEventListener("click", () => { | |||
| 7 | dialog.close(); | 7 | dialog.close(); |
| 8 | }); | 8 | }); |
| 9 | 9 | ||
| 10 | function handlePeriodLimitPresetSelInput(selEl, inputEl) { | ||
| 11 | selEl.addEventListener("input", (event) => { | ||
| 12 | if (selEl.value === "custom") { | ||
| 13 | inputEl.classList.remove("hidden"); | ||
| 14 | } else { | ||
| 15 | inputEl.classList.add("hidden"); | ||
| 16 | } | ||
| 17 | }); | ||
| 18 | } | ||
| 19 | |||
| 20 | function getPeriodLimitPresetSelInput(selEl, inputEl) { | ||
| 21 | const relativeDateTime = (durationArgs) => Temporal.Now.plainDateTimeISO().add(durationArgs); | ||
| 22 | |||
| 23 | let durationArgs = {}; | ||
| 24 | switch (selEl.value) { | ||
| 25 | case "-1m": return relativeDateTime({ months: -1 }); | ||
| 26 | case "-2w": return relativeDateTime({ weeks: -2 }); | ||
| 27 | case "-1w": return relativeDateTime({ weeks: -1 }); | ||
| 28 | case "0": return relativeDateTime({ seconds: 0 }); | ||
| 29 | case "+1w": return relativeDateTime({ weeks: 1 }); | ||
| 30 | case "+2w": return relativeDateTime({ weeks: 2 }); | ||
| 31 | case "+1m": return relativeDateTime({ months: 1 }); | ||
| 32 | case "custom": return Temporal.PlainDateTime.from(inputEl.value); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | handlePeriodLimitPresetSelInput( | ||
| 37 | document.getElementById("check-period-begin-preset-select"), | ||
| 38 | document.getElementById("check-period-begin-input")); | ||
| 39 | handlePeriodLimitPresetSelInput( | ||
| 40 | document.getElementById("check-period-end-preset-select"), | ||
| 41 | document.getElementById("check-period-end-input")); | ||
| 42 | |||
| 43 | window.addEventListener("load", (event) => { | ||
| 44 | const oneWeek = Temporal.Duration.from({ weeks: 1 }); | ||
| 45 | const now = Temporal.Now.plainDateTimeISO(); | ||
| 46 | document.getElementById("check-period-begin-input").value = now.subtract(oneWeek).toString({ | ||
| 47 | smallestUnit: "minute", | ||
| 48 | }); | ||
| 49 | document.getElementById("check-period-end-input").value = now.add(oneWeek).toString({ | ||
| 50 | smallestUnit: "minute", | ||
| 51 | }); | ||
| 52 | }); | ||
| 53 | |||
| 10 | let map = L.map("map"); | 54 | let map = L.map("map"); |
| 11 | 55 | ||
| 12 | L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { | 56 | L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { |
| @@ -19,10 +63,27 @@ document.forms["gpx-upload-form"].addEventListener("submit", (event) => { | |||
| 19 | event.preventDefault(); | 63 | event.preventDefault(); |
| 20 | const gpxFileInput = document.getElementById("gpx-file-input"); | 64 | const gpxFileInput = document.getElementById("gpx-file-input"); |
| 21 | if (gpxFileInput.files.length !== 1) { | 65 | if (gpxFileInput.files.length !== 1) { |
| 22 | alert("Voor de upload moet er exact één GPX-bestand zijn geselecteerd"); | 66 | showDialog({ |
| 67 | title: "Geen bestand geselecteerd", | ||
| 68 | detail: "Voor de upload moet er exact één GPX-bestand zijn geselecteerd", | ||
| 69 | moreInfoEl: null, | ||
| 70 | }); | ||
| 23 | return; | 71 | return; |
| 24 | } | 72 | } |
| 25 | load(gpxFileInput.files[0]); | 73 | |
| 74 | const tzidHere = Temporal.Now.timeZoneId(); | ||
| 75 | const cpBegin = getPeriodLimitPresetSelInput(document.getElementById("check-period-begin-preset-select"), | ||
| 76 | document.getElementById("check-period-begin-input")).toZonedDateTime(tzidHere).toInstant(); | ||
| 77 | const cpEnd = getPeriodLimitPresetSelInput(document.getElementById("check-period-end-preset-select"), | ||
| 78 | document.getElementById("check-period-end-input")).toZonedDateTime(tzidHere).toInstant(); | ||
| 79 | |||
| 80 | load({ | ||
| 81 | gpxFile: gpxFileInput.files[0], | ||
| 82 | checkPeriod: { | ||
| 83 | begin: cpBegin, | ||
| 84 | end: cpEnd, | ||
| 85 | }, | ||
| 86 | }); | ||
| 26 | }); | 87 | }); |
| 27 | 88 | ||
| 28 | function el(name, attrs, ...children) { | 89 | function el(name, attrs, ...children) { |
| @@ -47,15 +108,22 @@ function tbl(rowcols) { | |||
| 47 | )))); | 108 | )))); |
| 48 | } | 109 | } |
| 49 | 110 | ||
| 50 | async function showProblem(rsp) { | 111 | function showDialog({ title, detail, moreInfoEl }) { |
| 51 | const problem = await rsp.json(); | 112 | document.getElementById("dialog-title").innerText = title; |
| 113 | document.getElementById("dialog-message").innerText = detail !== null ? detail : ""; | ||
| 114 | if (moreInfoEl !== null) { | ||
| 115 | document.getElementById("dialog-more-info").replaceChildren(moreInfoEl); | ||
| 116 | document.getElementById("dialog-more-info-container").classList.remove("hidden"); | ||
| 117 | } else { | ||
| 118 | document.getElementById("dialog-more-info").replaceChildren(); | ||
| 119 | document.getElementById("dialog-more-info-container").classList.add("hidden"); | ||
| 120 | } | ||
| 52 | 121 | ||
| 53 | document.getElementById("dialog-title").innerText = problem.title; | ||
| 54 | if (problem.detail) | ||
| 55 | document.getElementById("dialog-message").innerText = problem.detail; | ||
| 56 | else | ||
| 57 | document.getElementById("dialog-message").innerText = ""; | ||
| 58 | dialog.showModal(); | 122 | dialog.showModal(); |
| 123 | } | ||
| 124 | |||
| 125 | async function showProblem(rsp) { | ||
| 126 | const problem = await rsp.json(); | ||
| 59 | 127 | ||
| 60 | let rows = [ | 128 | let rows = [ |
| 61 | [txt("HTTP-statuscode"), | 129 | [txt("HTTP-statuscode"), |
| @@ -70,9 +138,12 @@ async function showProblem(rsp) { | |||
| 70 | rows.push([txt("Instantie"), | 138 | rows.push([txt("Instantie"), |
| 71 | el("code", {}, txt(problem.instance))]); | 139 | el("code", {}, txt(problem.instance))]); |
| 72 | } | 140 | } |
| 73 | document.getElementById("dialog-more-info").replaceChildren(tbl(rows)); | ||
| 74 | 141 | ||
| 75 | return; | 142 | showDialog({ |
| 143 | title: problem.title, | ||
| 144 | detail: problem.detail ? problem.detail : null, | ||
| 145 | moreInfoEl: tbl(rows), | ||
| 146 | }); | ||
| 76 | } | 147 | } |
| 77 | 148 | ||
| 78 | async function getSysinfo() { | 149 | async function getSysinfo() { |
| @@ -101,7 +172,7 @@ async function getSysinfo() { | |||
| 101 | document.getElementById("sysinfo-details").replaceChildren(tbl(rows)); | 172 | document.getElementById("sysinfo-details").replaceChildren(tbl(rows)); |
| 102 | } | 173 | } |
| 103 | 174 | ||
| 104 | async function load(gpxFile) { | 175 | async function load({ gpxFile, checkPeriod }) { |
| 105 | let compressedParts = []; | 176 | let compressedParts = []; |
| 106 | const compressedReader = gpxFile.stream().pipeThrough(new CompressionStream("deflate-raw")).getReader(); | 177 | const compressedReader = gpxFile.stream().pipeThrough(new CompressionStream("deflate-raw")).getReader(); |
| 107 | while (true) { | 178 | while (true) { |
| @@ -113,7 +184,7 @@ async function load(gpxFile) { | |||
| 113 | } | 184 | } |
| 114 | } | 185 | } |
| 115 | 186 | ||
| 116 | const rsp = await fetch(apiBaseUrl + "/gpx", { | 187 | const rsp = await fetch(apiBaseUrl + `/gpx?cpbegin=${encodeURI(checkPeriod.begin.toString({ smallestUnit: "minute" }))}&cpend=${encodeURI(checkPeriod.end.toString({ smallestUnit: "minute" }))}`, { |
| 117 | method: "POST", | 188 | method: "POST", |
| 118 | headers: { | 189 | headers: { |
| 119 | "Accept-Language": "nl-NL", | 190 | "Accept-Language": "nl-NL", |