Merge main into refactor-weather-weekly - resolve type safety conflicts
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
import { storedLocation } from '$lib/stores/settings';
|
||||
import { urlHashStore } from '$lib/stores/url-hash-store';
|
||||
|
||||
import { Checkbox } from '$lib/components/ui/checkbox';
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
@@ -17,16 +16,15 @@
|
||||
import { defaultParameters } from './options';
|
||||
|
||||
let node: HTMLElement;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let charts: any[] = [];
|
||||
let Highcharts = $state<any>();
|
||||
let chart: any;
|
||||
let Highcharts = $state<typeof import('highcharts') | null>(null);
|
||||
|
||||
let showLegend = $state(false);
|
||||
let averageOnly = $state(false);
|
||||
|
||||
const location = get(storedLocation);
|
||||
|
||||
const params = urlHashStore({
|
||||
let params = $state({
|
||||
latitude: [52.52],
|
||||
longitude: [13.41],
|
||||
...defaultParameters,
|
||||
@@ -48,38 +46,34 @@
|
||||
if (dev) {
|
||||
// const HighchartsDebugger = await import('highcharts/modules/debugger');
|
||||
// HighchartsDebugger.default(Highcharts);
|
||||
// @ts-ignore
|
||||
const Debugger = (
|
||||
(await import('highcharts/es-modules/Extensions/Debugger/Debugger.js')) as any
|
||||
await import('highcharts/es-modules/Extensions/Debugger/Debugger.js' as any)
|
||||
).default;
|
||||
// @ts-ignore
|
||||
const ErrorMessages = (
|
||||
(await import('highcharts/es-modules/Extensions/Debugger/ErrorMessages.js')) as any
|
||||
await import('highcharts/es-modules/Extensions/Debugger/ErrorMessages.js' as any)
|
||||
).default;
|
||||
Highcharts.errorMessages = ErrorMessages;
|
||||
Debugger.compose(Highcharts.Chart);
|
||||
if (Highcharts) {
|
||||
(Highcharts as any).errorMessages = ErrorMessages;
|
||||
Debugger.compose(Highcharts.Chart);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
count = 0;
|
||||
if (Highcharts) {
|
||||
charts.forEach((c) => c.destroy());
|
||||
charts = [];
|
||||
// eslint-disable-next-line svelte/no-dom-manipulating
|
||||
(node as any).replaceChildren();
|
||||
const loadData = async () => {
|
||||
count = 0;
|
||||
if (Highcharts) {
|
||||
node.replaceChildren();
|
||||
|
||||
(async () => {
|
||||
const dataReq = await fetch(
|
||||
`https://api.open-meteo.com/v1/forecast?latitude=${location.latitude}&longitude=${location.longitude}&hourly=${$params.hourly?.join(',')}&models=${$params.models?.join(',')}&timeformat=unixtime&daily=sunset,sunrise`
|
||||
`https://api.open-meteo.com/v1/forecast?latitude=${location.latitude}&longitude=${location.longitude}&hourly=${params.hourly?.join(',') || ''}&models=${params.models?.join(',') || ''}&timeformat=unixtime&daily=sunset,sunrise`
|
||||
);
|
||||
const data = await dataReq.json();
|
||||
|
||||
let dailyFirstModelKeyParts = Object.keys(data.daily)[1].split('_');
|
||||
dailyFirstModelKeyParts.shift();
|
||||
const dailyFirstModelKey = dailyFirstModelKeyParts.join('_');
|
||||
let dailyFirstModelKey: string[] | string = Object.keys(data.daily)[1].split('_');
|
||||
dailyFirstModelKey.shift();
|
||||
dailyFirstModelKey = dailyFirstModelKey.join('_');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
let plotBands: any = [];
|
||||
if (
|
||||
'daily' in data &&
|
||||
@@ -97,7 +91,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
for (let variable of $params.hourly || []) {
|
||||
for (let variable of params.hourly || []) {
|
||||
const chartDiv = document.createElement('div');
|
||||
|
||||
let unit;
|
||||
@@ -169,19 +163,20 @@
|
||||
className: 'highcharts-average-series'
|
||||
});
|
||||
|
||||
const chart = new Highcharts.Chart(chartDiv, {
|
||||
credits: {
|
||||
text: count === ($params.hourly?.length || 0) - 1 ? 'Open-Meteo.com' : '',
|
||||
href: 'http://open-meteo.com'
|
||||
},
|
||||
|
||||
new Highcharts!.Chart({
|
||||
chart: {
|
||||
renderTo: chartDiv,
|
||||
height: showLegend ? '400px' : '300px',
|
||||
styledMode: true,
|
||||
marginLeft: '50',
|
||||
marginLeft: 50,
|
||||
marginRight: 0
|
||||
},
|
||||
|
||||
credits: {
|
||||
text: count === (params.hourly?.length || 0) - 1 ? 'Open-Meteo.com' : '',
|
||||
href: 'http://open-meteo.com'
|
||||
},
|
||||
|
||||
lang: {
|
||||
locale: 'en-GB'
|
||||
},
|
||||
@@ -194,8 +189,8 @@
|
||||
subtitle: {
|
||||
text:
|
||||
count === 0
|
||||
? `Compare <span class="font-bold">${$params.hourly?.join(', ')}</span> in models: <span class="font-bold">` +
|
||||
$params.models?.join(', ') +
|
||||
? `Compare <span class="font-bold">${params.hourly?.join(', ') || ''}</span> in models: <span class="font-bold">` +
|
||||
(params.models?.join(', ') || '') +
|
||||
'</span>'
|
||||
: '',
|
||||
align: 'left'
|
||||
@@ -243,7 +238,7 @@
|
||||
verticalAlign: 'bottom'
|
||||
},
|
||||
|
||||
series: series,
|
||||
series: series as any,
|
||||
|
||||
responsive: {
|
||||
rules: [
|
||||
@@ -262,22 +257,23 @@
|
||||
});
|
||||
|
||||
count++;
|
||||
charts.push(chart);
|
||||
// eslint-disable-next-line svelte/no-dom-manipulating
|
||||
node.appendChild(chartDiv);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
};
|
||||
loadData();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
charts.forEach((c) => c.destroy());
|
||||
if (chart) {
|
||||
chart.destroy();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- min-h-[302px] min-h-[602px] min-h-[902px] min-h-[1202px] -->
|
||||
<div
|
||||
class="container-wrapper relative -mx-6 md:mx-0 min-h-[{300 * ($params.hourly?.length || 0) +
|
||||
class="container-wrapper relative -mx-6 md:mx-0 min-h-[{300 * (params.hourly?.length || 0) +
|
||||
2}px]"
|
||||
>
|
||||
<div in:fade={{ duration: 300 }} out:fade={{ duration: 300 }} bind:this={node}></div>
|
||||
@@ -312,7 +308,7 @@
|
||||
name="Show legend"
|
||||
bind:checked={showLegend}
|
||||
onCheckedChange={() => {
|
||||
$params.hourly = $params.hourly;
|
||||
params.hourly = params.hourly;
|
||||
}}
|
||||
/>
|
||||
<Label for="show_legend" class="mb-[2px] cursor-pointer text-lg">Show legend</Label>
|
||||
@@ -323,7 +319,7 @@
|
||||
name="Average only"
|
||||
bind:checked={averageOnly}
|
||||
onCheckedChange={() => {
|
||||
$params.hourly = $params.hourly;
|
||||
params.hourly = params.hourly;
|
||||
}}
|
||||
/>
|
||||
<Label for="average_only" class="mb-[2px] cursor-pointer text-lg">Average only</Label>
|
||||
@@ -334,48 +330,46 @@
|
||||
<div class="mt-4 md:mt-8">
|
||||
<div class="flex">
|
||||
<a href="#models"><h2 id="models" class="text-2xl md:text-3xl">Models</h2></a>
|
||||
{#if $params.models && $params.models.length > 0}
|
||||
{#if params.models && params.models.length > 0}
|
||||
<div transition:fade={{ duration: 200 }} class="relative mt-[5px]">
|
||||
<div
|
||||
class="absolute -top-1 ml-2 rounded-full border-2 border-foreground/25 bg-secondary px-3 py-1 text-sm no-underline"
|
||||
>
|
||||
{$params.models?.length} / {models.flat().length}
|
||||
{params.models?.length || 0} / {models.length}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="mt-2 grid sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4">
|
||||
{#each models as group, i (i)}
|
||||
<div class="mb-3">
|
||||
{#each group as { value, label } (value)}
|
||||
<div class="group flex items-center" title={label}>
|
||||
<Checkbox
|
||||
id="{value}_model"
|
||||
class="border-border-dark cursor-pointer bg-muted/50 duration-100 group-hover:border-[currentColor]"
|
||||
{value}
|
||||
checked={$params.models?.includes(value)}
|
||||
aria-labelledby="{value}_label"
|
||||
onCheckedChange={() => {
|
||||
if ($params.models?.includes(value)) {
|
||||
$params.models = $params.models.filter((item: string) => {
|
||||
return item !== value;
|
||||
});
|
||||
} else if ($params.models) {
|
||||
$params.models.push(value);
|
||||
$params.models = $params.models;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Label
|
||||
id="{value}_model_label"
|
||||
for="{value}_model"
|
||||
class="cursor-pointer truncate py-[0.1rem] pl-[0.42rem]">{label}</Label
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
<div class="mb-3">
|
||||
{#each models as { value, label } (value)}
|
||||
<div class="group flex items-center" title={label}>
|
||||
<Checkbox
|
||||
id="{value}_model"
|
||||
class="border-border-dark cursor-pointer bg-muted/50 duration-100 group-hover:border-[currentColor]"
|
||||
{value}
|
||||
checked={params.models?.includes(value)}
|
||||
aria-labelledby="{value}_label"
|
||||
onCheckedChange={() => {
|
||||
if (params.models?.includes(value)) {
|
||||
params.models = params.models.filter((item) => {
|
||||
return item !== value;
|
||||
});
|
||||
} else if (params.models) {
|
||||
params.models.push(value);
|
||||
params.models = params.models;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Label
|
||||
id="{value}_model_label"
|
||||
for="{value}_model"
|
||||
class="cursor-pointer truncate py-[0.1rem] pl-[0.42rem]">{label}</Label
|
||||
>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HOURLY -->
|
||||
@@ -386,12 +380,12 @@
|
||||
Hourly Weather Variables
|
||||
</h2></a
|
||||
>
|
||||
{#if $params.hourly && $params.hourly.length > 0}
|
||||
{#if params.hourly && params.hourly.length > 0}
|
||||
<div transition:fade={{ duration: 200 }} class="relative mt-[5px]">
|
||||
<div
|
||||
class="absolute -top-1 ml-2 rounded-full border-2 border-foreground/25 bg-secondary px-3 py-1 text-sm no-underline"
|
||||
>
|
||||
{$params.hourly?.length} / {hourly.flat().length}
|
||||
{params.hourly?.length || 0} / {hourly.flat().length}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -408,16 +402,16 @@
|
||||
id="{value}_hourly"
|
||||
class="border-border-dark cursor-pointer bg-muted/50 duration-100 group-hover:border-[currentColor]"
|
||||
{value}
|
||||
checked={$params.hourly?.includes(value)}
|
||||
checked={params.hourly?.includes(value)}
|
||||
aria-labelledby="{value}_label"
|
||||
onCheckedChange={() => {
|
||||
if ($params.hourly?.includes(value)) {
|
||||
$params.hourly = $params.hourly.filter((item: string) => {
|
||||
if (params.hourly?.includes(value)) {
|
||||
params.hourly = params.hourly.filter((item) => {
|
||||
return item !== value;
|
||||
});
|
||||
} else if ($params.hourly) {
|
||||
$params.hourly.push(value);
|
||||
$params.hourly = $params.hourly;
|
||||
} else if (params.hourly) {
|
||||
params.hourly.push(value);
|
||||
params.hourly = params.hourly;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user