diff --git a/web/src/App.tsx b/web/src/App.tsx index 10b293d..466f891 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -7,12 +7,19 @@ import { FileManager } from './fileManager/FileManager'; console.log("env:", import.meta.env.MODE); console.log("api host:", import.meta.env.VITE_API_HOST); -type Section = "aggregator" | "fileManager"; +type Section = "aggregator" | "mapView" | "fileManager"; const App: Component = () => { const [getSection, setSection] = createSignal
("aggregator"); - const section = () => getSection() === "aggregator" ? : ; + const section = () => { + switch(getSection()) { + case "fileManager": return ; + case "aggregator": + default: + return ; + } + } return (
diff --git a/web/src/aggregator/Aggregator.tsx b/web/src/aggregator/Aggregator.tsx index 96c1bee..bc8e3f6 100644 --- a/web/src/aggregator/Aggregator.tsx +++ b/web/src/aggregator/Aggregator.tsx @@ -1,7 +1,7 @@ import moment from "moment"; import { createSignal } from "solid-js"; +import { QueryResult } from "./result/QueryResult"; -import { Result } from "./Result"; import { SelectCity } from "./SelectCity"; import { SelectField } from "./SelectField"; import { SelectGranularity } from "./SelectGranularity"; @@ -16,7 +16,7 @@ export function Aggregator() { const [getStart, setStart] = createSignal(dayAgo); const [getEnd, setEnd] = createSignal(nowRounded); const [getField, setField] = createSignal("tempMax"); - const [getKey, setKey] = createSignal("list"); + const [getKey, setKey] = createSignal("max"); const [getGranularity, setGranularity] = createSignal("hour"); return ( @@ -42,7 +42,7 @@ export function Aggregator() {
- ResultKeyVal[] }> = ({ data }) => { + const [getCanvas, setCanvas] = createSignal(); + const [getImg, setImg] = createSignal(new Image()); + let lastCoords: [string, {x: number, y: number }, number][] = []; + + onMount(() => { + const ctx = getCanvas()!.getContext("2d")!; + const img = new Image(); + img.onload = () => { + setImg(img); + drawOnMap(ctx, img, lastCoords); + }; + img.src = "src/assets/map_1920x1080.webp"; + }); + + createEffect(() => { + const ctx = getCanvas()!.getContext("2d")!; + const coordsAndData: [string, {x: number, y: number }, number][] = data() + .map(([city, value]) => [ + city, + cityCoords[city as keyof typeof cityCoords], + typeof value === "number" ? value : -99, + ]); + lastCoords = coordsAndData; + drawOnMap(ctx, getImg(), coordsAndData); + }); + + return ( + + ); +} + +function drawOnMap( + ctx: CanvasRenderingContext2D, + img: HTMLImageElement, + coords: [string, {x: number, y: number }, number][] +): void { + const size = 80; + ctx.font = "bold 30px Arial"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + + ctx.drawImage(img, 0, 0); + coords.forEach(([, {x, y}, value]) => { + ctx.beginPath(); + ctx.fillStyle = "#FFFFFF"; + ctx.rect(x, y, size, size); + ctx.fill(); + ctx.fillStyle = "#000000"; + ctx.fillText(`${value}`, x + size/2, y + size/2); + }); +} \ No newline at end of file diff --git a/web/src/aggregator/map/cityCoords.ts b/web/src/aggregator/map/cityCoords.ts new file mode 100644 index 0000000..449eb18 --- /dev/null +++ b/web/src/aggregator/map/cityCoords.ts @@ -0,0 +1,35 @@ +export const cityCoords = { + "Ainaži": { x: 685, y: 146 }, + "Alūksne": { x: 1176, y: 294 }, + "Bauska": { x: 721, y: 608 }, + "Dagda": { x: 1280, y: 680 }, + "Daugavgrīva": { x: 640, y: 410 }, + "Daugavpils": { x: 1140, y: 739 }, + "Dobele": { x: 550, y: 580 }, + "Gulbene": { x: 1100, y: 370 }, + "Jelgava": { x: 620, y: 570 }, + "Kalnciems": { x: 600, y: 500 }, + "Kolka": { x: 380, y: 200 }, + "Kuldīga": { x: 300, y: 470 }, + "Lielpēči": { x: 780, y: 490 }, + "Liepāja": { x: 124, y: 638 }, + "Madona": { x: 1004, y: 432 }, + "Mērsrags": { x: 480, y: 300 }, + "Pāvilosta": { x: 160, y: 450 }, + "Piedruja": { x: 1290, y: 770 }, + "Priekuļi": { x: 900, y: 320 }, + "Rēzekne": { x: 1229, y: 544 }, + "Rīga": { x: 689, y: 430 }, + "Rucava": { x: 140, y: 710 }, + "Rūjiena": { x: 870, y: 140 }, + "Saldus": { x: 383, y: 561 }, + "Sigulda": { x: 810, y: 380 }, + "Sīļi": { x: 1050, y: 640 }, + "Skrīveri": { x: 880, y: 530 }, + "Skulte": { x: 710, y: 320 }, + "Stende": { x: 402, y: 400 }, + "Ventspils": { x: 210, y: 329 }, + "Vičaki": { x: 270, y: 260}, + "Zīlāni": { x: 983, y: 581 }, + "Zosēni": { x: 970, y: 370 }, +}; \ No newline at end of file diff --git a/web/src/aggregator/Result.tsx b/web/src/aggregator/result/QueryResult.tsx similarity index 60% rename from web/src/aggregator/Result.tsx rename to web/src/aggregator/result/QueryResult.tsx index f6f2346..2144a7a 100644 --- a/web/src/aggregator/Result.tsx +++ b/web/src/aggregator/result/QueryResult.tsx @@ -1,13 +1,12 @@ import moment from "moment"; import { Accessor, Component, createResource, createSignal } from "solid-js"; -import "../css/Result.css" -import { apiHost, ResultKeyVal, resultOrder, ResultOrderKeys } from "../consts"; -import { SelectOrder } from "./SelectOrder"; -import { CityResult } from "./chart/CityResult"; -import { isDataQuery } from "./helpers"; +import "../../css/Result.css" +import { apiHost } from "../../consts"; +import { isQueryResult } from "../helpers"; +import { Result } from "./Result"; -export const Result: Component<{ +export const QueryResult: Component<{ getCities: Accessor>, getStart: Accessor, getEnd: Accessor, @@ -29,7 +28,6 @@ export const Result: Component<{ } const [queryResource] = createResource(getTimestamp, fetchQuery); - const [getOrderKey, setOrderKey] = createSignal("A -> Z"); return (
@@ -39,10 +37,6 @@ export const Result: Component<{ value="Query Data" onClick={() => setTimestamp(Date.now())} /> -
-

Result:

- -
{ queryResource.loading && (
@@ -55,19 +49,9 @@ export const Result: Component<{ { queryResource() && queryResource() instanceof Error &&
{ queryResource().message }
} - { queryResource() && queryResource().result && isDataQuery(queryResource().query) && ( -
- { Object.entries(queryResource().result) - .map(keyVal => [...keyVal] as ResultKeyVal) - .sort((a, b) => resultOrder[getOrderKey()](a, b)) - .map(cityData => - ) - }
- )} + { queryResource() && isQueryResult( queryResource() ) && + + }
); } \ No newline at end of file diff --git a/web/src/aggregator/result/Result.tsx b/web/src/aggregator/result/Result.tsx new file mode 100644 index 0000000..4ac6acc --- /dev/null +++ b/web/src/aggregator/result/Result.tsx @@ -0,0 +1,58 @@ +import { Component, createSignal, Resource } from "solid-js"; + +import "../../css/Result.css" +import { ResultKeyVal, resultOrder, ResultOrderKeys } from "../../consts"; +import { SelectOrder } from "../SelectOrder"; +import { CityResult } from "../chart/CityResult"; +import { QueryResult } from "../helpers"; +import { MapView } from "../map/MapView"; + +export const Result: Component<{ + result: Resource +}> = ({ result: resultResource }) => { + const [getOrderKey, setOrderKey] = createSignal("A -> Z"); + type ResultView = "text" | "map"; + const [getResultView, setResultView] = createSignal("text"); + + const cityData = () => + Object.entries(resultResource()!.result) + .map(keyVal => [...keyVal] as ResultKeyVal) + .sort((a, b) => resultOrder[getOrderKey()](a, b)); + + return ( +
+
+

Result:

+ + setResultView("text")} + /> +   |   + setResultView("map")} + /> + + + + +
+
+ { getResultView() === "text" + ? cityData().map(([city, data]) => + ) + : + } +
+
+ ); +} \ No newline at end of file diff --git a/web/src/assets/logo.svg b/web/src/assets/logo.svg deleted file mode 100644 index 025aa30..0000000 --- a/web/src/assets/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/web/src/assets/map_1920x1080.webp b/web/src/assets/map_1920x1080.webp new file mode 100644 index 0000000..bc1640f Binary files /dev/null and b/web/src/assets/map_1920x1080.webp differ diff --git a/web/src/css/FileManager.css b/web/src/css/FileManager.css index 804071d..dff7547 100644 --- a/web/src/css/FileManager.css +++ b/web/src/css/FileManager.css @@ -1,24 +1,24 @@ .container { display: flex; min-height: 100vh; - } +} - .column { +.column { flex: 1; padding: 10px; box-sizing: border-box; text-align: left; - } +} - .column:nth-child(1), - .column:nth-child(2) { +.column:nth-child(1), +.column:nth-child(2) { flex-basis: 15%; background-color: #f2f2f2; min-width: 200px; - } +} - .column:nth-child(3) { +.column:nth-child(3) { flex-basis: 70%; background-color: #e6e6e6; min-width: 680px; - } \ No newline at end of file +} \ No newline at end of file