Select all cities and order results

This commit is contained in:
Guntis Smaukstelis
2023-06-22 19:20:21 +03:00
parent 6ce4d139a8
commit bb817e5171
7 changed files with 116 additions and 26 deletions
+18 -5
View File
@@ -1,9 +1,11 @@
import moment from "moment"; import moment from "moment";
import { Accessor, Component, createResource, createSignal } from "solid-js"; import { Accessor, Component, createResource, createSignal } from "solid-js";
import { apiHost } from "../consts";
import { apiHost, ResultKeyVal, resultOrder, ResultOrderKeys } from "../consts";
import { CityChart } from "./CityChart"; import { CityChart } from "./CityChart";
import "../css/Result.css" import "../css/Result.css"
import { SelectOrder } from "./SelectOrder";
export const Result: Component<{ export const Result: Component<{
getCities: Accessor<Set<string>>, getCities: Accessor<Set<string>>,
@@ -12,7 +14,8 @@ export const Result: Component<{
getField: Accessor<string>, getField: Accessor<string>,
getKey: Accessor<string>, getKey: Accessor<string>,
}> = (props) => { }> = (props) => {
const cities = () => [...props.getCities()].join(",") const cities = () => [...props.getCities()].join(",");
const citiesStr = () => [...props.getCities()].join(", ");
const startStr = () => moment(props.getStart()).format("YYYY/MM/DD, HH:mm"); const startStr = () => moment(props.getStart()).format("YYYY/MM/DD, HH:mm");
const endStr = () => moment(props.getEnd()).format("YYYY/MM/DD, HH:mm"); const endStr = () => moment(props.getEnd()).format("YYYY/MM/DD, HH:mm");
const queryStart = () => moment(props.getStart()).format("YYYYMMDD_HHmm"); const queryStart = () => moment(props.getStart()).format("YYYYMMDD_HHmm");
@@ -28,16 +31,25 @@ export const Result: Component<{
} }
const [queryResource] = createResource(getTimestamp, fetchQuery); const [queryResource] = createResource(getTimestamp, fetchQuery);
const [getOrderKey, setOrderKey] = createSignal<ResultOrderKeys>("A -> Z");
return ( return (
<div> <div>
<h3>Aggregate by:</h3> <h3>Aggregate by:</h3>
<input type="button" value="Query Data" onClick={() => setTimestamp(Date.now())} /> <input
<p>cities: { cities() }</p> type="button"
class="primary"
value="Query Data"
onClick={() => setTimestamp(Date.now())}
/>
<p>cities: { citiesStr() }</p>
<p>time range: { startStr() } - { endStr() }</p> <p>time range: { startStr() } - { endStr() }</p>
<p>weather field: { props.getField() }</p> <p>weather field: { props.getField() }</p>
<p>aggregation field: { props.getKey() }</p> <p>aggregation field: { props.getKey() }</p>
<div class="resultTitle">
<h3>Result:</h3> <h3>Result:</h3>
<SelectOrder getter={getOrderKey} setter={setOrderKey} />
</div>
{ queryResource.loading && ( { queryResource.loading && (
<div> <div>
<span class="spinner"></span> <span class="spinner"></span>
@@ -53,7 +65,8 @@ export const Result: Component<{
{ queryResource() && ( { queryResource() && (
<div class="result-container"> <div class="result-container">
{ Object.entries(queryResource()) { Object.entries(queryResource())
.sort((a, b) => (a[0] as string) > (b[0] as string) ? 1 : -1) .map(keyVal => [...keyVal] as ResultKeyVal)
.sort((a, b) => resultOrder[getOrderKey()](a, b))
.map(cityData => <ExportCity city={cityData[0]} value={cityData[1]} />) .map(cityData => <ExportCity city={cityData[0]} value={cityData[1]} />)
}</div> }</div>
)} )}
+2 -1
View File
@@ -9,7 +9,7 @@ export const SelectAggregator: Component<{
}> = (props) => { }> = (props) => {
return ( return (
<div> <div>
<h3>Select aggregator</h3> <h3>Select field</h3>
<select onChange={(e) => props.setField(e.target.value)}> <select onChange={(e) => props.setField(e.target.value)}>
{ weatherField.map(field => { weatherField.map(field =>
<option <option
@@ -18,6 +18,7 @@ export const SelectAggregator: Component<{
>{field}</option> >{field}</option>
)} )}
</select> </select>
<h3>Select aggregator</h3>
<ul> <ul>
{ aggregateKey.map(key => { aggregateKey.map(key =>
<label><li><input <label><li><input
+25 -7
View File
@@ -1,22 +1,37 @@
import { Accessor, Component, Setter } from "solid-js"; import { Accessor, Component, createEffect, Setter } from "solid-js";
import { cityList } from "../consts"; import { cityList } from "../consts";
export const SelectCity: Component<{ export const SelectCity: Component<{
getCities: Accessor<Set<string>>, getCities: Accessor<Set<string>>,
setCities: Setter<Set<string>>, setCities: Setter<Set<string>>,
}> = (props) => { }> = ({ getCities, setCities }) => {
function handleSelect(e: MouseEvent) { function handleSelect(e: MouseEvent) {
if (!e.target) return; if (!e.target) return;
const target = e.target as HTMLInputElement; const target = e.target as HTMLInputElement;
const { checked: selected, value: city } = target; const { checked: selected, value: city } = target;
const cityList = new Set([...props.getCities()]); const selectedCities = new Set([...getCities()]);
if (selected) cityList.add(city); if (selected) selectedCities.add(city);
else cityList.delete(city); else selectedCities.delete(city);
props.setCities(cityList); setCities(selectedCities);
}
function selectAll(e: MouseEvent) {
if (!e.target) return;
const target = e.target as HTMLInputElement;
const selectedCities = target.checked
? new Set([...cityList])
: new Set([]);
setCities(selectedCities);
} }
return ( return (
<div>
Select all <input
type="checkbox"
onClick={selectAll}
/>
<ul>{cityList.map(city => <ul>{cityList.map(city =>
<label> <label>
<li> <li>
@@ -24,11 +39,14 @@ export const SelectCity: Component<{
type="checkbox" type="checkbox"
name="city" name="city"
value={city} value={city}
checked={getCities().has(city)}
onClick={handleSelect} onClick={handleSelect}
/> />
{city} {city}
</li> </li>
</label> </label>
)}</ul> )}
</ul>
</div>
); );
}; };
+23
View File
@@ -0,0 +1,23 @@
import { Accessor, Component, Setter } from "solid-js";
import { resultOrder, ResultOrderKeys } from "../consts";
export const SelectOrder: Component<{
getter: Accessor<ResultOrderKeys>,
setter: Setter<ResultOrderKeys>,
}> = ({ getter, setter }) => {
return (
<div>
Order by:
<select onChange={e => setter(e.target.value as ResultOrderKeys)}>
{ Object.keys(resultOrder).map(orderKey =>
<option
value={orderKey}
selected={orderKey === getter()}
>
{orderKey}
</option>
)}
</select>
</div>
);
};
+12
View File
@@ -5,3 +5,15 @@ export const cityList = ["Ainaži", "Alūksne", "Bauska", "Dagda", "Daugavgrīva
export const weatherField = ["tempMax", "tempMin", "tempAvg", "precipitation", "windAvg", "windMax", "visibilityMin", "visibilityAvg", "snowAvg", "atmPressire", "dewPoint", "humidity", "sunDuration", "phenomena"]; export const weatherField = ["tempMax", "tempMin", "tempAvg", "precipitation", "windAvg", "windMax", "visibilityMin", "visibilityAvg", "snowAvg", "atmPressire", "dewPoint", "humidity", "sunDuration", "phenomena"];
export const aggregateKey = ["min", "max", "avg", "sum", "list", "distinct"]; export const aggregateKey = ["min", "max", "avg", "sum", "list", "distinct"];
export type ResultKeyVal = [key: string, value: number | Array<any>];
export const resultOrder = {
"A -> Z": (a: ResultKeyVal, b: ResultKeyVal) => a[0] > b[0] ? 1 : -1,
"Z -> A": (a: ResultKeyVal, b: ResultKeyVal) => a[0] > b[0] ? -1 : 1,
"Min": (a: ResultKeyVal, b: ResultKeyVal) => a[1] > b[1] ? 1 : -1,
"Max": (a: ResultKeyVal, b: ResultKeyVal) => a[1] > b[1] ? -1 : 1,
};
type ResultOrder = typeof resultOrder;
export type ResultOrderKeys = keyof ResultOrder;
+11
View File
@@ -9,3 +9,14 @@
padding: 10px; padding: 10px;
text-align: center; text-align: center;
} }
.resultTitle {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 0;
}
.resultTitle h3 {
margin: 0;
}
+12
View File
@@ -11,3 +11,15 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace; monospace;
} }
.primary {
background-color: #ffcc66;
border: none;
font-weight: bold;
padding: 5px 10px;
cursor: pointer;
}
.primary:hover {
background-color: #ffb92d;
}