Setting up harmonie page in frontend

This commit is contained in:
Guntis Smaukstelis
2025-02-02 23:33:15 +02:00
parent ae4080103f
commit 8d77a6a582
8 changed files with 123 additions and 28 deletions
+2 -1
View File
@@ -55,7 +55,8 @@ class FetchService(log: Logger[IO]) {
for { for {
base <- baseUrl base <- baseUrl
queryParams = Query.fromPairs( queryParams = Query.fromPairs(
"parameter-name" -> "temperature-2m", // https://opendatadocs.dmi.govcloud.dk/Data/Forecast_Data_Weather_Model_HARMONIE_DINI_EDR
"parameter-name" -> "temperature-2m,total-precipitation,precipitation-type,wind-speed,gust-wind-speed-10m,wind-10m-u,wind-10m-v",
"datetime" -> time.toString, "datetime" -> time.toString,
"api-key" -> harmonieServerConfig.api_key, "api-key" -> harmonieServerConfig.api_key,
) )
+5 -1
View File
@@ -1,3 +1,7 @@
{ {
"typescript.tsdk": "node_modules/typescript/lib" "typescript.tsdk": "node_modules/typescript/lib",
"javascript.preferences.quoteStyle": "single",
"typescript.preferences.quoteStyle": "single",
"javascript.format.semicolons": "remove",
"typescript.format.semicolons": "remove"
} }
+16
View File
@@ -8,6 +8,7 @@
"name": "weather-tool-web", "name": "weather-tool-web",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@solidjs/router": "^0.15.2",
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"moment": "^2.30.1", "moment": "^2.30.1",
"solid-js": "^1.9.4" "solid-js": "^1.9.4"
@@ -1096,6 +1097,15 @@
"win32" "win32"
] ]
}, },
"node_modules/@solidjs/router": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/@solidjs/router/-/router-0.15.3.tgz",
"integrity": "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw==",
"license": "MIT",
"peerDependencies": {
"solid-js": "^1.8.6"
}
},
"node_modules/@types/babel__core": { "node_modules/@types/babel__core": {
"version": "7.20.5", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -3271,6 +3281,12 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@solidjs/router": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/@solidjs/router/-/router-0.15.3.tgz",
"integrity": "sha512-iEbW8UKok2Oio7o6Y4VTzLj+KFCmQPGEpm1fS3xixwFBdclFVBvaQVeibl1jys4cujfAK5Kn6+uG2uBm3lxOMw==",
"requires": {}
},
"@types/babel__core": { "@types/babel__core": {
"version": "7.20.5", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+2 -1
View File
@@ -19,6 +19,7 @@
"dependencies": { "dependencies": {
"chart.js": "^4.4.1", "chart.js": "^4.4.1",
"moment": "^2.30.1", "moment": "^2.30.1",
"solid-js": "^1.9.4" "solid-js": "^1.9.4",
"@solidjs/router": "^0.15.2"
} }
} }
+15 -25
View File
@@ -1,4 +1,5 @@
import { Component, JSXElement, createSignal } from 'solid-js'; import { Component, JSXElement, createSignal } from 'solid-js'
import { Route, Router } from '@solidjs/router'
import styles from './css/menu.module.css'; import styles from './css/menu.module.css';
import { Country } from './country/Country'; import { Country } from './country/Country';
@@ -7,46 +8,35 @@ import { Database } from './database/Database';
import { Station } from './station/Station'; import { Station } from './station/Station';
import { apiHost } from './consts'; import { apiHost } from './consts';
import { WeatherIconStub } from './components/weatherIcons/WeatherIconStub'; import { WeatherIconStub } from './components/weatherIcons/WeatherIconStub';
import { Harmonie } from './harmonie/Harmonie'
console.log("env:", import.meta.env.MODE); console.log("env:", import.meta.env.MODE);
console.log("api host:", apiHost); console.log("api host:", apiHost);
const App: Component = () => { const App: Component = () => {
const pages: [string, () => JSXElement][] = [ const pages = ['station', 'cities', 'latvia', 'database', 'harmonie']
["station", () => <Station />],
["cities", () => <Cities />],
["latvia", () => <Country />],
["database", () => <Database />],
];
const [getPageTitle, setPageTitle] = createSignal("station");
const getPageContent = () => {
const page = pages.find(p => p[0] === getPageTitle());
return page ? page[1]() : <div>Page not found!</div>;
}
const getActiveCSS = (pageTitle: string) => {
return getPageTitle() === pageTitle ? styles.active : "";
}
return ( return (
<div> <div>
<div class="grid-1-1"> <div class="grid-1-1">
<div><WeatherIconStub /></div> <div><WeatherIconStub /></div>
<div> <div>
<ul class={styles.menu}> <ul class={styles.menu}>
{ pages.map(([pageTitle]) => { pages.map(page =>
<li <li>
class={getActiveCSS(pageTitle)} <a href={page}>{page}</a>
onClick={() => setPageTitle(pageTitle)}
>
{pageTitle}
</li> </li>
)} )}
</ul> </ul>
</div> </div>
</div> </div>
{ getPageContent() } <Router>
<Route path="/" component={Harmonie} />
<Route path="/harmonie" component={Harmonie} />
<Route path="/station" component={Station} />
<Route path="/cities" component={Cities} />
<Route path="/latvia" component={Country} />
<Route path="/database" component={Database} />
</Router>
</div> </div>
); );
}; };
+35
View File
@@ -0,0 +1,35 @@
import { Accessor, Component, createSignal } from 'solid-js'
import styles from './harmonie.module.css'
import { apiHost } from '../consts'
export const GribFile: Component<{
name: string,
isActive: Accessor<boolean>,
onClick: (name: string) => void,
}> = ({ name, isActive, onClick }) => {
const [getStructure, setStructure] = createSignal<any[]>([])
function onFileClick() {
onClick(name)
if (getStructure().length === 0) {
fetch(`${apiHost}/api/show/grib/${name}`)
.then(re => re.json())
.then(setStructure)
}
}
return <li
class={isActive() ? styles.active : ''}
onClick={onFileClick}
>
<div class={styles.name}>{ name }</div>
<ul class={styles.meteoParams}>
{ getStructure().map(grib =>
<li>{ grib.title }</li>
)}
</ul>
</li>
}
+30
View File
@@ -0,0 +1,30 @@
import { Component, createSignal } from 'solid-js'
import { apiHost } from '../consts'
import styles from './harmonie.module.css'
import { GribFile } from './GribFile'
export const Harmonie: Component<{}> = () => {
const [getFileList, setFileList] = createSignal<string[]>([])
const [getActiveGrib, setActiveGrib] = createSignal('')
fetch(`${apiHost}/api/show/grib-list`)
.then(re => re.json())
.then(fileList => {
fileList.sort((a: string, b: string) => a < b ? 1 : -1)
setFileList(fileList)
})
return <div>
Harmonie
<ul class={styles.fileList}>
{getFileList().map(fileName =>
<GribFile
name={fileName}
isActive={() => getActiveGrib() === fileName}
onClick={() => setActiveGrib(fileName)}
/>
)}
</ul>
</div>
}
+18
View File
@@ -0,0 +1,18 @@
.fileList li {
padding: 5px 0;
}
.fileList > li:nth-child(odd) {
background-color: #ddd;
}
.fileList .active .name {
font-weight: bold;
}
.fileList .meteoParams {
display: none;
}
.fileList li.active .meteoParams {
display: block;
}