Add delay and spinner for station map, common const and component for delay

This commit is contained in:
Guntis Smaukstelis
2024-01-19 20:32:20 +02:00
parent ad03f43f66
commit 16ed47c661
10 changed files with 54 additions and 47 deletions
+4 -8
View File
@@ -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<Set<string>>,
@@ -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 && (
<div>
<span class="spinner"></span>
<span style={{ "padding-left": "16px" }}>Loading query</span>
</div>
)}
{ queryResource.loading && <LoadingSpinner text="Loading query" /> }
{ queryResource.error && (
<div>Error while querying: ${queryResource.error}</div>
)}
+10
View File
@@ -0,0 +1,10 @@
import { Component } from "solid-js";
export const LoadingSpinner: Component<{ text: string; }> = ({ text }) => {
return (
<div>
<span class="spinner"></span>
<span style={{ "padding-left": "16px" }}>{ text }</span>
</div>
);
}
+2
View File
@@ -13,6 +13,8 @@ export const CityChart: Component<{
const [getCanvas, setCanvas] = createSignal<HTMLCanvasElement>();
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),
+2
View File
@@ -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"];
+4 -8
View File
@@ -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 && (
<div>
<span class="spinner"></span>
<span style={{ "padding-left": "16px" }}>Loading query</span>
</div>
)}
{ queryResource.loading && <LoadingSpinner text="Loading query" /> }
{ queryResource.error && (
<div>Error while querying: ${queryResource.error}</div>
)}
+4 -8
View File
@@ -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<Date>, setDate: Setter<Date>;}> = (props) => {
const [getCurrentMonth, setCurrentMonth] = createSignal(new Date());
@@ -14,7 +15,7 @@ export const DateList: Component<{getDate: Accessor<Date>, setDate: Setter<Date>
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<Date>, setDate: Setter<Date>
return (
<div>
{ datesResource.loading && (
<div>
<span class="spinner"></span>
<span style={{ "padding-left": "16px" }}>Loading dates</span>
</div>
)}
{ datesResource.loading && <LoadingSpinner text="Loading calendar..." /> }
{ datesResource.error && (
<div>Error while loading dates: ${datesResource.error}</div>
)}
+4 -8
View File
@@ -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<string>}> = (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<string>}> = (props) =
return (
<div>
{ contentResource.loading && (
<div>
<span class="spinner"></span>
<span style={{ "padding-left": "16px" }}>load content</span>
</div>
)}
{ contentResource.loading && <LoadingSpinner text="Loading date-time weather" /> }
{ contentResource.error && (
<div>Error while loading file content: ${contentResource.error}</div>
)}
+4 -8
View File
@@ -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<Date>,
setFileName: Setter<string>,
}> = (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 (
<div>
{ fileNameResource.loading && (
<div>
<span class="spinner"></span>
<span style={{ "padding-left": "16px" }}>loading {moment(props.getDate()).format("YYYYMMDD")}</span>
</div>
)}
{ fileNameResource.loading && <LoadingSpinner text={"Loading date: "+moment(props.getDate()).format("YYYYMMDD")} /> }
{ fileNameResource.error && (
<div>Error while loading file names: ${fileNameResource.error}</div>
)}
+15 -2
View File
@@ -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<string | undefined>,
@@ -49,6 +50,8 @@ export const MapResult: Component<{
const [meteoValues] = createResource(citiesFieldDate, async ([cities, field, start, end]: [Set<string>, 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 <canvas ref={setCanvas} width={1000} height={570} />;
return (
<div>
{ meteoValues.loading && <LoadingSpinner text="Drawing map..." /> }
<canvas
ref={setCanvas}
style={{ display: meteoValues.loading ? "none" : "block" }}
width={1000}
height={570}
/>
</div>
);
}
function drawOnMap(
+5 -5
View File
@@ -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 &&
<div>
<h3>{ props.getCity() }</h3>
<h3>{ props.getCity() }: { props.getField() }</h3>
<CityChart
city={() => listResource().query.cities[0]}
data={() => listResource().result[listResource().query.cities[0]]}
data={() => listResource().result[listResource().query.cities[0]] ?? []}
query={() => listResource().query}
/>
</div>