From 16ed47c6611d9c875cbeb006597a8f631ecf4730 Mon Sep 17 00:00:00 2001 From: Guntis Smaukstelis Date: Fri, 19 Jan 2024 20:32:20 +0200 Subject: [PATCH] Add delay and spinner for station map, common const and component for delay --- web/src/cities/result/QueryResult.tsx | 12 ++++-------- web/src/components/LoadingSpinner.tsx | 10 ++++++++++ web/src/components/chart/CityChart.tsx | 2 ++ web/src/consts.ts | 2 ++ web/src/country/result/QueryResult.tsx | 12 ++++-------- web/src/database/DateList.tsx | 12 ++++-------- web/src/database/FileContent.tsx | 12 ++++-------- web/src/database/FileNameList.tsx | 12 ++++-------- web/src/station/MapResult.tsx | 17 +++++++++++++++-- web/src/station/Result.tsx | 10 +++++----- 10 files changed, 54 insertions(+), 47 deletions(-) create mode 100644 web/src/components/LoadingSpinner.tsx diff --git a/web/src/cities/result/QueryResult.tsx b/web/src/cities/result/QueryResult.tsx index b0dbaae..e3c842e 100644 --- a/web/src/cities/result/QueryResult.tsx +++ b/web/src/cities/result/QueryResult.tsx @@ -2,9 +2,10 @@ import moment from "moment"; import { Accessor, Component, createResource, createSignal } from "solid-js"; import "../../css/Result.css" -import { apiHost } from "../../consts"; +import { FETCH_DELAY_MS, apiHost } from "../../consts"; import { isQueryResult } from "../helpers"; import { Result } from "./Result"; +import { LoadingSpinner } from "../../components/LoadingSpinner"; export const QueryResult: Component<{ getCities: Accessor>, @@ -21,7 +22,7 @@ export const QueryResult: Component<{ const fetchQuery = async (timestamp: number) => { if (cities() === "") return new Error("ERROR: Select cities!"); - await new Promise(resolve => setTimeout(resolve, 500)) + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)) const response = await fetch(`${apiHost}/api/query/city/${cities()}/${queryStart()}-${queryEnd()}/${props.getGranularity()}/${props.getField()}/${props.getKey()}`); const json = await response.json(); return json; @@ -37,12 +38,7 @@ export const QueryResult: Component<{ value="Query Data" onClick={() => setTimestamp(Date.now())} /> - { queryResource.loading && ( -
- - Loading query -
- )} + { queryResource.loading && } { queryResource.error && (
Error while querying: ${queryResource.error}
)} diff --git a/web/src/components/LoadingSpinner.tsx b/web/src/components/LoadingSpinner.tsx new file mode 100644 index 0000000..b2f6fd1 --- /dev/null +++ b/web/src/components/LoadingSpinner.tsx @@ -0,0 +1,10 @@ +import { Component } from "solid-js"; + +export const LoadingSpinner: Component<{ text: string; }> = ({ text }) => { + return ( +
+ + { text } +
+ ); +} \ No newline at end of file diff --git a/web/src/components/chart/CityChart.tsx b/web/src/components/chart/CityChart.tsx index 293d33b..447c2a4 100644 --- a/web/src/components/chart/CityChart.tsx +++ b/web/src/components/chart/CityChart.tsx @@ -13,6 +13,8 @@ export const CityChart: Component<{ const [getCanvas, setCanvas] = createSignal(); const [getIsLarge, setIsLarge] = createSignal(false); + console.log("props.data()", props.data()); + let chart: Chart | undefined; const data: [string, number | null][] = props.data().map(([dateStr, value]) => [ formatDateString(dateStr), diff --git a/web/src/consts.ts b/web/src/consts.ts index c568676..76cf957 100644 --- a/web/src/consts.ts +++ b/web/src/consts.ts @@ -6,6 +6,8 @@ export const apiHost = import.meta.env.MODE === "development" ? import.meta.env.VITE_API_HOST : `${protocol}//${host}:${port}`; // export const apiHost = import.meta.env.VITE_API_HOST; +export const FETCH_DELAY_MS = 500; // delays by 500ms for server requests, so user sees that something is loading + export const cityList = ["Ainaži", "Alūksne", "Bauska", "Dagda", "Daugavgrīva", "Daugavpils", "Dobele", "Gulbene", "Jelgava", "Kalnciems", "Kolka", "Kuldīga", "Lielpēči", "Liepāja", "Madona", "Mērsrags", "Pāvilosta", "Piedruja", "Priekuļi", "Rēzekne", "Rīga", "Rucava", "Rūjiena", "Saldus", "Sigulda", "Sīļi", "Skrīveri", "Skulte", "Stende", "Ventspils", "Vičaki", "Zīlāni", "Zosēni"]; export const weatherField = ["tempMax", "tempMin", "tempAvg", "precipitation", "windAvg", "windMax", "visibilityMin", "visibilityAvg", "snowAvg", "atmPressire", "dewPoint", "humidity", "sunDuration", "phenomena"]; diff --git a/web/src/country/result/QueryResult.tsx b/web/src/country/result/QueryResult.tsx index 4d9f3e2..d4fddd8 100644 --- a/web/src/country/result/QueryResult.tsx +++ b/web/src/country/result/QueryResult.tsx @@ -1,8 +1,9 @@ import moment from "moment"; import { Accessor, Component, createResource, createSignal } from "solid-js"; -import { apiHost } from "../../consts"; +import { FETCH_DELAY_MS, apiHost } from "../../consts"; import { Result } from "./Result"; +import { LoadingSpinner } from "../../components/LoadingSpinner"; export const QueryResult: Component<{ @@ -16,7 +17,7 @@ export const QueryResult: Component<{ const fetchQuery = async (timestamp: number) => { if (props.getFields().length === 0) return new Error("ERROR: Select weather parameters!"); - await new Promise(resolve => setTimeout(resolve, 500)) + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)) const response = await fetch(`${apiHost}/api/query/country/${queryStart()}-${queryEnd()}/${props.getFields().join(",")}`); const json = await response.json(); return json; @@ -32,12 +33,7 @@ export const QueryResult: Component<{ value="Query Data" onClick={() => setTimestamp(Date.now())} /> - { queryResource.loading && ( -
- - Loading query -
- )} + { queryResource.loading && } { queryResource.error && (
Error while querying: ${queryResource.error}
)} diff --git a/web/src/database/DateList.tsx b/web/src/database/DateList.tsx index 8ca7f15..34096c3 100644 --- a/web/src/database/DateList.tsx +++ b/web/src/database/DateList.tsx @@ -1,10 +1,11 @@ import moment from "moment"; import { Accessor, Component, createResource, createSignal, Setter } from "solid-js"; -import { apiHost } from "../consts"; +import { apiHost, FETCH_DELAY_MS } from "../consts"; import "../css/spinner.css"; import { Calendar } from "./Calendar"; +import { LoadingSpinner } from "../components/LoadingSpinner"; export const DateList: Component<{getDate: Accessor, setDate: Setter;}> = (props) => { const [getCurrentMonth, setCurrentMonth] = createSignal(new Date()); @@ -14,7 +15,7 @@ export const DateList: Component<{getDate: Accessor, setDate: Setter moment(getCurrentMonth()).subtract(1, "months").format("yyyyMM"), moment(getCurrentMonth()).add(1, "months").format("yyyyMM"), ]; - await new Promise(resolve => setTimeout(resolve, 500)) + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)) const response = await fetch(`${apiHost}/api/show/months/${months.join(",")}`); const json = await response.json(); return json; @@ -24,12 +25,7 @@ export const DateList: Component<{getDate: Accessor, setDate: Setter return (
- { datesResource.loading && ( -
- - Loading dates -
- )} + { datesResource.loading && } { datesResource.error && (
Error while loading dates: ${datesResource.error}
)} diff --git a/web/src/database/FileContent.tsx b/web/src/database/FileContent.tsx index 3425792..c791457 100644 --- a/web/src/database/FileContent.tsx +++ b/web/src/database/FileContent.tsx @@ -1,11 +1,12 @@ import { Accessor, Component, createResource, JSXElement } from "solid-js"; -import { apiHost } from "../consts"; +import { apiHost, FETCH_DELAY_MS } from "../consts"; import { PrettifyCSV } from "./PrettifyCSV"; +import { LoadingSpinner } from "../components/LoadingSpinner"; export const FileContent: Component<{getFileName: Accessor}> = (props) => { const fetchFileContent = async (fileName: string) => { if (fileName === "") return; - await new Promise(resolve => setTimeout(resolve, 500)) + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)) const response = await fetch(`${apiHost}/api/show/datetime/${fileName}`); const text = await response.json(); return text; @@ -16,12 +17,7 @@ export const FileContent: Component<{getFileName: Accessor}> = (props) = return (
- { contentResource.loading && ( -
- - load content -
- )} + { contentResource.loading && } { contentResource.error && (
Error while loading file content: ${contentResource.error}
)} diff --git a/web/src/database/FileNameList.tsx b/web/src/database/FileNameList.tsx index 7494fa1..db7d6d1 100644 --- a/web/src/database/FileNameList.tsx +++ b/web/src/database/FileNameList.tsx @@ -1,15 +1,16 @@ import moment from "moment"; import { Accessor, Component, createResource, Setter } from "solid-js"; -import { apiHost } from "../consts"; +import { apiHost, FETCH_DELAY_MS } from "../consts"; import "../css/spinner.css"; +import { LoadingSpinner } from "../components/LoadingSpinner"; export const FileNameList: Component<{ getDate: Accessor, setFileName: Setter, }> = (props) => { const fetchFileNames = async (fetchDate: Date) => { - await new Promise(resolve => setTimeout(resolve, 500)) + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)) const response = await fetch(`${apiHost}/api/show/date/${moment(fetchDate).format("YYYYMMDD")}`); const json = await response.json(); return json; @@ -23,12 +24,7 @@ export const FileNameList: Component<{ return (
- { fileNameResource.loading && ( -
- - loading {moment(props.getDate()).format("YYYYMMDD")} -
- )} + { fileNameResource.loading && } { fileNameResource.error && (
Error while loading file names: ${fileNameResource.error}
)} diff --git a/web/src/station/MapResult.tsx b/web/src/station/MapResult.tsx index 95aee7f..e1fb580 100644 --- a/web/src/station/MapResult.tsx +++ b/web/src/station/MapResult.tsx @@ -4,7 +4,8 @@ import { coordToCity } from "./coordToCity"; import { cityCoords } from "./cityCoords"; import mapUrl from "../assets/map_1000x570.webp"; import moment from "moment"; -import { apiHost } from "../consts"; +import { FETCH_DELAY_MS, apiHost } from "../consts"; +import { LoadingSpinner } from "../components/LoadingSpinner"; export const MapResult: Component<{ setCity: Setter, @@ -49,6 +50,8 @@ export const MapResult: Component<{ const [meteoValues] = createResource(citiesFieldDate, async ([cities, field, start, end]: [Set, string, Date, Date]) => { if (cities.size === 0) return; + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)); + const queryStart = moment(start).format("YYYYMMDD_HHmm"); const queryEnd = moment(end).format("YYYYMMDD_HHmm"); let aggregate: string = "avg"; @@ -74,7 +77,17 @@ export const MapResult: Component<{ ); }); - return ; + return ( +
+ { meteoValues.loading && } + +
+ ); } function drawOnMap( diff --git a/web/src/station/Result.tsx b/web/src/station/Result.tsx index b231d09..602aa12 100644 --- a/web/src/station/Result.tsx +++ b/web/src/station/Result.tsx @@ -1,5 +1,5 @@ import { Accessor, Component, createResource } from "solid-js"; -import { apiHost } from "../consts"; +import { FETCH_DELAY_MS, apiHost } from "../consts"; import moment from "moment"; import { CityChart } from "../components/chart/CityChart"; @@ -14,7 +14,7 @@ export const Result: Component<{ const fetchList = async ([city, field, getStart, getEnd]: [string | undefined, string, Date, Date]) => { if (city === undefined) return undefined; - await new Promise(resolve => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)); const response = await fetch(`${apiHost}/api/query/city/${city}/${queryStart()}-${queryEnd()}/hour/${field}/list`); const json = await response.json(); return json; @@ -22,7 +22,7 @@ export const Result: Component<{ const fetchMeteo = async ([city, getStart, getEnd]: [string | undefined, Date, Date]) => { if (city === undefined) return undefined; - await new Promise(resolve => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, FETCH_DELAY_MS)); const response = await fetch(`${apiHost}/api/query/city/${city}/${queryStart()}-${queryEnd()}/allFields`); const json = await response.json(); return json; @@ -63,10 +63,10 @@ export const Result: Component<{ } { listResource() && props.getCity() && !listResource.loading &&
-

{ props.getCity() }

+

{ props.getCity() }: { props.getField() }

listResource().query.cities[0]} - data={() => listResource().result[listResource().query.cities[0]]} + data={() => listResource().result[listResource().query.cities[0]] ?? []} query={() => listResource().query} />