Select all cities and order results
This commit is contained in:
@@ -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>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -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>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user