Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
079e101
first commit
hmbacher May 19, 2025
6f4dbf3
Implement fans configuration feature with UI and backend support
hmbacher May 23, 2025
55ccebd
feat: Add sensor management and control functionality
hmbacher May 27, 2025
ac2c695
feat: Enhance temperature sensor handling with error tracking and eve…
hmbacher May 28, 2025
9e024e2
migrated from ESP32C3 to ESP32S3
hmbacher May 28, 2025
4dc040f
feat: Implement FFC MQTT Configuration and Alarm Logging
hmbacher Jun 2, 2025
6f11828
feat: Integrate alarm state management and update alarm handling in UI
hmbacher Jun 4, 2025
151e871
feat: Add RPM sensor functionality and integrate with fan controller
hmbacher Jun 4, 2025
ac5620a
feat: Refactor RPM sensor to include alarm service and enhance error …
hmbacher Jun 4, 2025
3f179a6
feat: Implement sensor discovery functionality and update controller …
hmbacher Jun 8, 2025
0fe3bd1
feat: Remove unused icons and configuration files; update logo in UI
hmbacher Jun 8, 2025
b6be847
feat: Update navigation to settings page and enhance alarm display wi…
hmbacher Jun 9, 2025
c50ef9a
feat: Enhance alarm notifications and add fan/temperature monitoring …
hmbacher Jun 9, 2025
ce4df56
chore: Update TODO file for project organization and future tasks
hmbacher Jun 9, 2025
5309bb6
feat: Add configuration file and update PWM settings for fan control;…
hmbacher Jun 22, 2025
9cf6e5a
- Removed obsolete (default) docs
hmbacher Aug 9, 2025
0c2f433
chore: Add initial TODO file with features and known bugs
hmbacher Aug 10, 2025
94d4439
Reworked network settings
hmbacher Aug 26, 2025
af42908
Fixed complier/IDE warnings
hmbacher Aug 26, 2025
5d80712
Updated pioarduino platfom and switched to explicit versioning
hmbacher Aug 26, 2025
2d9440a
Merge remote-tracking branch 'esp32sveltekit/main'
hmbacher Aug 26, 2025
db32c2f
Cleanup up async worker
hmbacher Aug 26, 2025
17e0c0a
Update development server configuration and dependencies
hmbacher Aug 27, 2025
9150064
Updated SSL cert creation config, updated pipeline scripts
hmbacher Aug 28, 2025
c6d826b
Fixed vite dev server issue
hmbacher Aug 28, 2025
c6d2462
Fixed bug if now handlers are passed
hmbacher Aug 28, 2025
aa9437c
Added coredump
hmbacher Aug 28, 2025
a5ac26d
Finalized Wifi Sta settings
hmbacher Aug 28, 2025
8d21f11
Merge branch 'main' of github.com:hmbacher/fridge-fan-control
hmbacher Aug 28, 2025
973e280
Optimized dirty flag for SettingsCard and Collapsible
hmbacher Aug 28, 2025
60d4e91
Delete lib/framework/WWWData.h
hmbacher Sep 14, 2025
0750aac
Fixed preprocessor directive
hmbacher Sep 14, 2025
0c155a8
Fixed makro redefinition
hmbacher Sep 14, 2025
59a51b6
Enhanced logo visualization on login page and on main page
hmbacher Sep 15, 2025
478d7fd
Added $src path alias
hmbacher Sep 15, 2025
ad370d4
Added missing page.ts for Core Dump
hmbacher Sep 15, 2025
d418239
Changes to prevent Svelte warning 'binding_property_non_reactive'
hmbacher Sep 15, 2025
ee6204f
Fixed PSRAM chart creation
hmbacher Sep 15, 2025
4de03b7
Fixed PSRAM metric
hmbacher Sep 15, 2025
b10d623
Implemented delayed wifi reconnect, to allow previous POST request to…
hmbacher Sep 16, 2025
deca943
Optimized language
hmbacher Sep 16, 2025
4d06842
Implemented draggable list with svelte-dnd-action
hmbacher Sep 19, 2025
99ce894
Fixed overflow properties
hmbacher Sep 19, 2025
0d3eb9f
Fixed Websockets implementation in frontend
hmbacher Sep 26, 2025
1926029
Changed drag & drop styling
hmbacher Sep 26, 2025
8263db0
Fixed re-ordering of Smoke detectors
hmbacher Sep 26, 2025
8fcd683
Cleanup up obsolete comments
hmbacher Sep 26, 2025
dceea17
Show HTML in Info and Confirm dialog
hmbacher Sep 28, 2025
0a89485
Removed deprecated commands in build script
hmbacher Oct 4, 2025
985b872
Enhanced execution of pre-build scripts
hmbacher Oct 5, 2025
989c378
Add print statements to indicate skipped execution for non-build task…
hmbacher Oct 5, 2025
033ab93
Merge branch 'main' into pr/hmbacher/100
theelims Oct 17, 2025
8531a3c
Latest Arduino
theelims Oct 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions interface/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions interface/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.2.0",
"private": true,
"scripts": {
"dev": "vite dev",
"dev": "vite dev --host",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
Expand Down Expand Up @@ -44,7 +44,7 @@
"jwt-decode": "^4.0.0",
"luxon": "^3.7.1",
"msgpack-lite": "^0.1.26",
"svelte-dnd-list": "^0.1.8",
"svelte-dnd-action": "^0.9.65",
"svelte-modals": "^2.0.1"
}
}
38 changes: 34 additions & 4 deletions interface/src/lib/components/Collapsible.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,54 @@
import { slide } from 'svelte/transition';
import { cubicOut } from 'svelte/easing';
import Down from '~icons/tabler/chevron-down';
import Alert from '~icons/tabler/alert-hexagon';

let { icon, title, children, opened, closed, open = false, class: className = '' } = $props();
interface Props {
open?: boolean;
opened?: any;
closed?: any;
collapsible?: boolean;
icon?: import('svelte').Snippet;
title?: import('svelte').Snippet;
children?: import('svelte').Snippet;
class?: string;
isDirty?: boolean;
}

let {
open = $bindable(false),
opened,
closed,
icon,
title,
children,
class: className = '',
isDirty = false
}: Props = $props();

function openCollapsible() {
open = !open;
if (open) {
opened();
if (opened) opened();
} else {
closed();
if (closed) closed();
}
}
</script>

<div class="{className} relative grid w-full max-w-2xl self-center overflow-hidden">
{#if isDirty}
<div class="absolute left-0 top-0 w-1.5 h-full bg-red-300"></div>
{/if}
<div class="min-h-16 flex w-full items-center justify-between space-x-3 p-4 text-xl font-medium">
<span class="inline-flex items-baseline">
<span class="inline-flex items-center">
{@render icon?.()}
{@render title?.()}
{#if isDirty}
<div data-tip="There are unsaved changes." class="tooltip tooltip-right tooltip-error">
<Alert class="text-error lex-shrink-0 ml-2 h-6 w-6 self-end cursor-help" />
</div>
{/if}
</span>
<button class="btn btn-circle btn-ghost btn-sm" onclick={() => openCollapsible()}>
<Down
Expand Down
8 changes: 4 additions & 4 deletions interface/src/lib/components/ConfirmDialog.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// provided by <Modals />

interface Props {
isOpen: boolean;
isOpen?: boolean;
title: string;
message: string;
onConfirm: any;
Expand Down Expand Up @@ -40,19 +40,19 @@
>
<h2 class="text-base-content text-start text-2xl font-bold">{title}</h2>
<div class="divider my-2"></div>
<p class="text-base-content mb-1 text-start">{message}</p>
<p class="text-base-content mb-1 text-start">{@html message}</p>
<div class="divider my-2"></div>
<div class="flex justify-end gap-2">
<button
class="btn btn-primary inline-flex items-center"
onclick={() => {
modals.close();
}}><labels.cancel.icon class="mr-2 h-5 w-5" /><span>{labels?.cancel.label}</span></button
}}><labels.cancel.icon class="h-5 w-5" /><span>{labels?.cancel.label}</span></button
>
<button
class="btn btn-warning text-warning-content inline-flex items-center"
onclick={onConfirm}
><SvelteComponent class="mr-2 h-5 w-5" /><span>{labels?.confirm.label}</span></button
><SvelteComponent class="h-5 w-5" /><span>{labels?.confirm.label}</span></button
>
</div>
</div>
Expand Down
83 changes: 83 additions & 0 deletions interface/src/lib/components/DraggableList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<script lang="ts">
import { dndzone } from 'svelte-dnd-action';
import type { Snippet } from 'svelte';

interface Props {
items: any[];
onReorder?: (reorderedItems: any[]) => void;
flipDurationMs?: number;
dragDisabled?: boolean;
class?: string;
children: Snippet<[{ item: any; index: number; originalItem: any }]>;
}

let {
items,
onReorder = () => {},
flipDurationMs = 200,
dragDisabled = false,
class: className = '',
children
}: Props = $props();

// Create a state array with IDs for drag-and-drop functionality
let itemsWithIds: any[] = $state([]);

// Update the drag-and-drop array whenever items change
$effect(() => {
itemsWithIds = items.map((item, index) => ({
...item,
id: item.id || `dnd-item-${index}-${Date.now()}` // Generate unique ID with timestamp
}));
});

function handleSort(e: any) {
// Update the visual drag-and-drop array immediately
itemsWithIds = e.detail.items;
}

function handleFinalizeSort(e: any) {
// Remove only temporary IDs, preserve original device IDs
const reorderedItems = e.detail.items.map((item: any) => {
// If this is a temporary ID we added (string starting with 'dnd-item-'), remove it
if (typeof item.id === 'string' && item.id.startsWith('dnd-item-')) {
const { id, ...itemWithoutTempId } = item;
return itemWithoutTempId;
}
// Otherwise, keep the item as-is (preserving original numeric IDs)
return item;
});

// Call the parent's reorder handler
onReorder(reorderedItems);
}

</script>

<section
use:dndzone={{
items: itemsWithIds,
flipDurationMs,
dropTargetStyle: {}, // This is to actively clear default styles
dropTargetClasses: ['dragzone-outline'], // This applies custom styling
dragDisabled
}}
onconsider={handleSort}
onfinalize={handleFinalizeSort}
class={className}
>
{#each itemsWithIds as item, index (item.id)}
{@render children({ item, index, originalItem: items[index] })}
{/each}
</section>

<style>
@reference "$src/app.css";
:global(.dragzone-outline) {
@apply outline-solid outline-2 outline-(--color-primary);
}
:global(#dnd-action-dragged-el) {
@apply outline-solid outline-2 outline-current;

}
</style>
2 changes: 1 addition & 1 deletion interface/src/lib/components/InfoDialog.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
>
<h2 class="text-base-content text-start text-2xl font-bold">{title}</h2>
<div class="divider my-2"></div>
<p class="text-base-content mb-1 text-start">{message}</p>
<p class="text-base-content mb-1 text-start">{@html message}</p>
<div class="divider my-2"></div>
<div class="flex justify-end gap-2">
<button
Expand Down
11 changes: 9 additions & 2 deletions interface/src/lib/components/InputPassword.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@
id?: string;
}

let { value = $bindable(''), id = '' }: Props = $props();
let { value = $bindable('') as string, id = '' as string }: Props = $props();

function handleInput(e: any) {
value = e.target.value;
}
</script>

<div class="relative">
<input {type} class="input w-full" {value} oninput={handleInput} {id} />
<input {type} class="input input-bordered w-full" {value} oninput={handleInput} {id} />
<div class="absolute inset-y-0 right-0 flex items-center pr-1">
<!-- svelte-ignore a11y_click_events_have_key_events -->
<svg
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/50 h-6 {show ? 'block' : 'hidden'}"
onclick={() => (show = false)}
role="button"
aria-label="Hide password"
tabindex="0"
width="40"
height="40"
viewBox="0 0 24 24"
Expand All @@ -43,6 +47,9 @@
xmlns="http://www.w3.org/2000/svg"
class="text-base-content/50 h-6 {show ? 'hidden' : 'block'}"
onclick={() => (show = true)}
role="button"
aria-label="Show password"
tabindex="0"
width="40"
height="40"
viewBox="0 0 24 24"
Expand Down
32 changes: 27 additions & 5 deletions interface/src/lib/components/SettingsCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,47 @@
import { slide } from 'svelte/transition';
import { cubicOut } from 'svelte/easing';
import Down from '~icons/tabler/chevron-down';
import Alert from '~icons/tabler/alert-hexagon';

interface Props {
open?: boolean;
collapsible?: boolean;
icon?: import('svelte').Snippet;
title?: import('svelte').Snippet;
children?: import('svelte').Snippet;
maxwidth?: string;
isDirty?: boolean;
}

let {
open = $bindable(true),
collapsible = true,
icon,
title,
children
children,
maxwidth = 'max-w-2xl',
isDirty = false
}: Props = $props();
</script>

{#if collapsible}
<div
class="bg-base-200 rounded-box shadow-primary/50 relative grid w-full max-w-2xl self-center overflow-hidden shadow-lg"
class="bg-base-200 rounded-box shadow-primary/50 relative grid w-full {maxwidth} self-center overflow-hidden shadow-lg m-10"
>
{#if isDirty}
<div class="absolute left-0 top-0 w-1.5 h-full bg-red-300"></div>
{/if}
<div
class="min-h-16 flex w-full items-center justify-between space-x-3 p-4 text-xl font-medium"
>
<span class="inline-flex items-baseline">
<span class="inline-flex items-center">
{@render icon?.()}
{@render title?.()}
{#if isDirty}
<div data-tip="There are unsaved changes." class="tooltip tooltip-right tooltip-error">
<Alert class="text-error lex-shrink-0 ml-2 h-6 w-6 self-end cursor-help" />
</div>
{/if}
</span>
<button
class="btn btn-circle btn-ghost btn-sm"
Expand All @@ -54,12 +68,20 @@
</div>
{:else}
<div
class="bg-base-200 rounded-box shadow-primary/50 relative grid w-full max-w-2xl self-center overflow-hidden shadow-lg"
class="bg-base-200 rounded-box shadow-primary/50 relative grid w-full {maxwidth} self-center overflow-hidden shadow-lg m-10"
>
{#if isDirty}
<div class="absolute left-0 top-0 w-1.5 h-full bg-red-300"></div>
{/if}
<div class="min-h-16 w-full p-4 text-xl font-medium">
<span class="inline-flex items-baseline">
<span class="inline-flex items-center">
{@render icon?.()}
{@render title?.()}
{#if isDirty}
<div data-tip="There are unsaved changes." class="tooltip tooltip-right tooltip-error">
<Alert class="text-error lex-shrink-0 ml-2 h-6 w-6 self-end cursor-help" />
</div>
{/if}
</span>
</div>
<div class="flex flex-col gap-2 p-4 pt-0">
Expand Down
7 changes: 5 additions & 2 deletions interface/src/lib/components/Spinner.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<script lang="ts">
import Loader from '~icons/tabler/loader-2';

let { text = "Loading..."} = $props();

</script>

<div class="flex h-full w-full flex-col items-center justify-center p-6">
<div class="flex w-full flex-col items-center justify-center p-6">
<Loader class="text-primary h-14 w-auto animate-spin stroke-2" />
<p class="text-xl">Loading...</p>
<p class="text-xl">{text}</p>
</div>
7 changes: 4 additions & 3 deletions interface/src/lib/components/UpdateIndicator.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

let { update = $bindable(false) }: Props = $props();

let firmwareVersion: string;
let firmwareVersion: string = $state('');
let firmwareDownloadLink: string;

async function getGithubAPI() {
Expand All @@ -31,6 +31,7 @@
}
});
if (response.status !== 200) {
notifications.error('Failed to fetch latest release from GitHub.', 5000);
throw new Error(`Failed to fetch latest release from ${githubUrl}`);
}
const results = await response.json();
Expand All @@ -54,7 +55,7 @@
}
}
} catch (error) {
console.error('Error:', error);
console.warn(error);
}
}

Expand Down Expand Up @@ -112,6 +113,6 @@
class="indicator-item indicator-top indicator-center badge badge-info badge-xs top-2 scale-75 lg:top-1"
>{firmwareVersion}</span
>
<Firmware class="inline-block h-7 w-7" />
<Firmware class="h-7 w-7" />
</button>
{/if}
2 changes: 1 addition & 1 deletion interface/src/lib/components/toasts/Toast.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
out:fly={{ x: 100, duration: 400 }}
>
<SvelteComponent class="h-6 w-6 shrink-0" />
<span>{notification.message}</span>
<span>{@html notification.message}</span>
</div>
{/each}
</div>
Loading