mirror of
https://github.com/KevinMidboe/brewPi.git
synced 2025-10-29 16:50:12 +00:00
Feat/prerender and state (#8)
* pre-load data behind link elements on hover * Enable SSR and prerendering of pages in 'auto' mode * merge relay & regulator state in /api/state This helps when updating relays and receiving state of relays and regulator state (idle, heating or cooling) after emitting relay change.
This commit is contained in:
@@ -20,7 +20,7 @@ const routes: Array<IRoute> = [{
|
|||||||
|
|
||||||
<ul class="navigation-cards" on:click>
|
<ul class="navigation-cards" on:click>
|
||||||
{#each routes as route}
|
{#each routes as route}
|
||||||
<a href={route.path}>
|
<a href={route.path} data-sveltekit-preload-data="hover">
|
||||||
<li>
|
<li>
|
||||||
<span>{ route.name }</span>
|
<span>{ route.name }</span>
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
export let relays: IRelaysDTO[] = [];
|
export let relays: IRelaysDTO[] = [];
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
function toggleRelay(controls: string) {
|
async function toggleRelay(controls: string) {
|
||||||
const url = `/api/relay/${controls}`;
|
const url = `/api/relay/${controls}`;
|
||||||
const options = {
|
const options = {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
};
|
};
|
||||||
|
|
||||||
fetch(url, options)
|
await fetch(url, options)
|
||||||
.then((resp) => resp.json())
|
.then((resp) => resp.json())
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const changedRelay = relays.findIndex((relay) => relay.pin === response.pin);
|
const changedRelay = relays.findIndex((relay) => relay.pin === response.pin);
|
||||||
|
|||||||
16
src/routes/+layout.ts
Normal file
16
src/routes/+layout.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// if you want to generate a static html file
|
||||||
|
// for your page.
|
||||||
|
// Documentation: https://kit.svelte.dev/docs/page-options#prerender
|
||||||
|
export const prerender = 'auto';
|
||||||
|
|
||||||
|
// if you want to Generate a SPA
|
||||||
|
// you have to set ssr to false.
|
||||||
|
// This is not the case (so set as true or comment the line)
|
||||||
|
// Documentation: https://kit.svelte.dev/docs/page-options#ssr
|
||||||
|
export const ssr = true;
|
||||||
|
|
||||||
|
// How to manage the trailing slashes in the URLs
|
||||||
|
// the URL for about page witll be /about with 'ignore' (default)
|
||||||
|
// the URL for about page witll be /about/ with 'always'
|
||||||
|
// https://kit.svelte.dev/docs/page-options#trailingslash
|
||||||
|
export const trailingSlash = 'ignore';
|
||||||
@@ -1,28 +1,51 @@
|
|||||||
import { BREWLOGGER_HOST } from '$env/static/private';
|
import { BREWLOGGER_HOST } from '$env/static/private';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad, RequestEvent } from './$types';
|
||||||
import type { ISensorDTO } from '../lib/interfaces/ISensorDTO'
|
import type { ISensorDTO } from '../lib/interfaces/ISensorDTO';
|
||||||
import { IRelaysDTO } from '../lib/interfaces/IRelaysDTO';
|
import { IRelaysDTO } from '../lib/interfaces/IRelaysDTO';
|
||||||
import { IStateDTO } from '../lib/interfaces/IStateDTO';
|
import { IStateDTO } from '../lib/interfaces/IStateDTO';
|
||||||
|
|
||||||
const sensorsUrl = `${BREWLOGGER_HOST}/api/sensors`;
|
const sensorsUrl = `${BREWLOGGER_HOST}/api/sensors`;
|
||||||
const relaysUrl = `${BREWLOGGER_HOST}/api/relays`;
|
export const prerender = true; // explicitly pre-render
|
||||||
const stateUrl = `${BREWLOGGER_HOST}/api/regulator`;
|
|
||||||
|
|
||||||
async function getFromEndpoint(endpoint: string) {
|
async function fetchSensors(fetch: Fetch): Promise<ISensorDTO[]> {
|
||||||
return fetch(endpoint)
|
return fetch(sensorsUrl)
|
||||||
.then((resp) => resp.json())
|
.then((resp) => resp.json())
|
||||||
|
.then((data) => data?.sensors || [])
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Failed to fetch endpoint:', endpoint);
|
console.error('failed to fetch sensors.');
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return null
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const load: PageServerLoad = async () => {
|
// calls internal sveltekit api endpoint.
|
||||||
const [sensorsResp, relaysResp, stateResp] = await Promise.all([getFromEndpoint(sensorsUrl), getFromEndpoint(relaysUrl), getFromEndpoint(stateUrl)]);
|
// this allows unified response in svelte app, even
|
||||||
const sensors: ISensorDTO[] = sensorsResp?.sensors || []
|
// though it requires multiple calls to regulator server
|
||||||
const relays: IRelaysDTO[] = relaysResp?.relays || []
|
async function fetchState(fetch: Fetch) {
|
||||||
const state: IStateDTO = stateResp
|
return fetch('/api/state')
|
||||||
|
.then((resp) => resp.json())
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('failed to fetch state');
|
||||||
|
console.error(error);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
type Fetch = typeof fetch;
|
||||||
|
type HandleFetch = {
|
||||||
|
event: RequestEvent;
|
||||||
|
request: Request;
|
||||||
|
fetch: Fetch;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async (input: HandleFetch) => {
|
||||||
|
const [stateResponse, sensorsResponse] = await Promise.all([
|
||||||
|
fetchState(input.fetch),
|
||||||
|
fetchSensors(input.fetch)
|
||||||
|
]);
|
||||||
|
const sensors: ISensorDTO[] = sensorsResponse || [];
|
||||||
|
const relays: IRelaysDTO[] = stateResponse?.relays || [];
|
||||||
|
const regulator: IStateDTO = stateResponse?.regulator;
|
||||||
|
|
||||||
const inside = sensors.find((sensor: ISensorDTO) => sensor.location === 'inside');
|
const inside = sensors.find((sensor: ISensorDTO) => sensor.location === 'inside');
|
||||||
const outside = sensors.find((sensor: ISensorDTO) => sensor.location === 'outside');
|
const outside = sensors.find((sensor: ISensorDTO) => sensor.location === 'outside');
|
||||||
@@ -30,7 +53,6 @@ export const load: PageServerLoad = async () => {
|
|||||||
return {
|
return {
|
||||||
inside: inside || null,
|
inside: inside || null,
|
||||||
outside: outside || null,
|
outside: outside || null,
|
||||||
relays,
|
state: { regulator, relays }
|
||||||
state
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,14 +8,13 @@
|
|||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
const { inside, outside } = data;
|
const { inside, outside } = data;
|
||||||
let { relays, state } = data;
|
let { relays, regulator } = data.state;
|
||||||
|
|
||||||
const updateState = () =>
|
const updateState = () => {
|
||||||
setTimeout(() => {
|
|
||||||
fetch('/api/state')
|
fetch('/api/state')
|
||||||
.then((resp) => resp.json())
|
.then((resp) => resp.json())
|
||||||
.then((response: IStateDTO) => (state = response));
|
.then((response: IStateDTO) => ({ relays, regulator } = response));
|
||||||
}, 100);
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Logo />
|
<Logo />
|
||||||
@@ -23,7 +22,12 @@
|
|||||||
<div class="vertical-grid">
|
<div class="vertical-grid">
|
||||||
<BrewProgress />
|
<BrewProgress />
|
||||||
|
|
||||||
<VerticalSensorDisplay {inside} {outside} {relays} {state} />
|
<VerticalSensorDisplay
|
||||||
|
inside="{inside}"
|
||||||
|
outside="{outside}"
|
||||||
|
relays="{relays}"
|
||||||
|
state="{regulator}"
|
||||||
|
/>
|
||||||
|
|
||||||
<RelayControls bind:relays="{relays}" on:relaySwitched="{updateState}" />
|
<RelayControls bind:relays="{relays}" on:relaySwitched="{updateState}" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import { json, RequestEvent } from '@sveltejs/kit';
|
import { json, RequestEvent } from '@sveltejs/kit';
|
||||||
import { BREWLOGGER_HOST } from '$env/static/private';
|
import { BREWLOGGER_HOST } from '$env/static/private';
|
||||||
import type { RequestHandler } from './$types';
|
import type { RequestHandler } from './$types';
|
||||||
|
import { IRelaysDTO } from '../../../lib/interfaces/IRelaysDTO';
|
||||||
|
|
||||||
export const GET = (async (event: RequestEvent) => {
|
async function fetchRegulator(): Promise<Response | IRelaysDTO[]> {
|
||||||
return fetch(BREWLOGGER_HOST + '/api/regulator')
|
return fetch(BREWLOGGER_HOST + '/api/regulator').then((resp) => resp.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchRelays(): Promise<Response | IRelaysDTO[]> {
|
||||||
|
return fetch(BREWLOGGER_HOST + '/api/relays')
|
||||||
.then((resp) => resp.json())
|
.then((resp) => resp.json())
|
||||||
.then((response) => json(response));
|
.then((data) => data?.relays || []);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GET = (async () => {
|
||||||
|
const [regulatorState, relaysState] = await Promise.all([fetchRegulator(), fetchRelays()]);
|
||||||
|
return json({ regulator: regulatorState, relays: relaysState });
|
||||||
}) satisfies RequestHandler;
|
}) satisfies RequestHandler;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
{#each brews as brew}
|
{#each brews as brew}
|
||||||
<li class="brew">
|
<li class="brew">
|
||||||
<a href="{path(brew.date)}">
|
<a href="{path(brew.date)}" data-sveltekit-preload-data="hover">
|
||||||
<img src="/images/{brew.image}" alt="Beer label of {brew.beer.name}" />
|
<img src="/images/{brew.image}" alt="Beer label of {brew.beer.name}" />
|
||||||
|
|
||||||
<div class="details">
|
<div class="details">
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import { fetchHumidity, fetchTemperature } from '../../../lib/server/graphQueryG
|
|||||||
import type { PageLoad } from './$types';
|
import type { PageLoad } from './$types';
|
||||||
|
|
||||||
async function fetchGraphData(brew) {
|
async function fetchGraphData(brew) {
|
||||||
const start = new Date(brew.date * 1000 - 86400000);
|
const { date } = brew;
|
||||||
const end = new Date(brew.date * 1000 + 4838400000);
|
const start = new Date(date * 1000 - 86400000);
|
||||||
|
const end = new Date(date * 1000 + 4838400000);
|
||||||
const size = 200;
|
const size = 200;
|
||||||
|
|
||||||
const [temperature, humidity] = await Promise.all([
|
const [temperature, humidity] = await Promise.all([
|
||||||
@@ -13,10 +14,7 @@ async function fetchGraphData(brew) {
|
|||||||
fetchHumidity(start, end, size)
|
fetchHumidity(start, end, size)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return { temperature, humidity };
|
||||||
temperature,
|
|
||||||
humidity
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const load = (async ({ params }) => {
|
export const load = (async ({ params }) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user