Files
homeassistant_espscreen/web/src/components/AppSettingsView.vue
T
Max Gramser 510ebdf885 Rebuild the editor as a Vue app: sidebar, pages side by side, tile settings in a drawer (0.2.74)
The page is now web/ (Vue 3 + Vite + TypeScript), built into screen_manager/app/static
with hashed file names; server.py serves index.html as built and /assets/. The Python
API, the data and the firmware are unchanged. Your screens sit in a sidebar, the pages
of a screen stand next to each other at the screen's own shape, the library sits on the
right, and a tile's settings slide in as a drawer while the mockup stays in view. New
screen, Firmware & USB, Alerts, Override YAML and Settings are pages of their own.
Fonts moved to web/src/assets; the tests read the source through tests/editor_sources.py.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 08:30:38 +02:00

77 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
// Everything around the screens: firmware updates, alerts, Claude.
import { computed, ref } from "vue";
import { go, installClaudeSkill, runUpdateAll, setAutoUpdate, state } from "../store";
const u = computed(() => state.inventory.updates);
const outdated = computed(() => state.inventory.screens.filter((s) => s.update?.available).length);
const updatesHint = computed(() => !u.value ? "" : u.value.busy
? `Updating to firmware ${u.value.target}…`
: !state.inventory.screens.length
? `No screen paired yet. New screens get firmware ${u.value.target}.`
: outdated.value
? `Firmware ${u.value.target} is available for ${outdated.value} screen${outdated.value === 1 ? "" : "s"}.`
: `All screens have firmware ${u.value.target}.`);
const skill = computed(() => state.inventory.claude_skill);
const installing = ref(false);
async function install() {
installing.value = true;
try { await installClaudeSkill(); } finally { installing.value = false; }
}
</script>
<template>
<div class="panel" id="settings-view">
<div class="panel-head">
<div class="tx">
<span class="eyebrow">Settings</span>
<h1 id="settings-title">Everything around your screens.</h1>
</div>
<button type="button" class="btn quiet" id="close-settings" @click="go('')">← My screens</button>
</div>
<div class="card-grid">
<section class="card">
<h2>Screens</h2>
<p>Add a screen, or build and reinstall the firmware of one you already have.</p>
<div class="tools">
<button type="button" class="tool" @click="go('#new-screen')"><span class="tool-icon">+</span><span class="tx"><b>New screen</b><small>Connect and install</small></span></button>
<button type="button" class="tool" @click="go('#firmware')"><span class="tool-icon">⇪</span><span class="tx"><b>Firmware &amp; USB</b><small>Build and install via USB or Wi-Fi</small></span></button>
</div>
</section>
<section v-if="u" class="card updates" id="updates">
<h2>Firmware updates</h2>
<p id="updates-hint">{{ updatesHint }}</p>
<button v-if="u.pending && !u.busy && u.pending >= 2" id="update-all" type="button" class="btn primary" @click="runUpdateAll">Update all {{ u.pending }} screens</button>
<label class="check">
<input type="checkbox" id="auto-update" :checked="Boolean(u.auto)" @change="setAutoUpdate(($event.target as HTMLInputElement).checked)" />
<span>Update automatically every night<small>Between 03:00 and 06:00, one screen at a time. Stops on an error and reports it in Home Assistant.</small></span>
</label>
</section>
<section class="card">
<h2>Alerts</h2>
<p>A card over the whole screen from an automation, on one screen or on all of them. The cheatsheet has the action names, fields, icons, and colors.</p>
<div class="tools">
<button type="button" class="tool" @click="go('#alerts')"><span class="tool-icon">!</span><span class="tx"><b>Alerts</b><small>Full-screen notifications, from an automation</small></span></button>
</div>
</section>
<section class="card" id="claude">
<h2>Claude</h2>
<p>Teach Claude about ESP Screens, then ask: "Show an alert on all my screens when the mailbox is full." Claude knows the alert events, every field, color, and icon.</p>
<div class="actions">
<button type="button" id="claude-install" class="btn" :class="skill?.installed && skill.current ? 'quiet' : 'primary'" :disabled="!skill || installing" @click="install">
{{ !skill || !skill.installed ? "Install for Claude Code" : skill.current ? "Install again" : "Update the skill" }}
</button>
<span id="claude-status" class="chip" :class="!skill ? '' : !skill.installed ? '' : skill.current ? 'good' : 'update'" role="status">
{{ !skill ? "Loading…" : !skill.installed ? "Not installed" : skill.current ? "● Installed" : "Installed · a newer version is ready" }}
</span>
</div>
<small>For Claude Code in Home Assistant. Writes one file to <code id="claude-path">{{ skill?.path || "/homeassistant/.claude/skills/esp-screens" }}</code>; installing again replaces it.</small>
<div class="actions">
<a class="btn quiet" id="claude-download" href="api/claude-skill.zip" download="esp-screens.zip">Download for claude.ai</a>
<small>Upload the zip in Claude under Customize → Skills.</small>
</div>
</section>
</div>
</div>
</template>