Improve vacuum controls, slider gestures and per-tile settings discovery
This commit is contained in:
@@ -6,7 +6,8 @@ let inventory = { screens: [], entities: [] },
|
||||
dirty = false,
|
||||
filter = "",
|
||||
dragIndex = -1,
|
||||
busy = false;
|
||||
busy = false,
|
||||
selectedTile = null;
|
||||
const node = (tag, text, cls) => {
|
||||
const n = document.createElement(tag);
|
||||
if (text !== undefined) n.textContent = text;
|
||||
@@ -256,7 +257,22 @@ function renderTiles() {
|
||||
actions.append(b);
|
||||
}
|
||||
const options = node("details", undefined, "tile-options");
|
||||
options.append(node("summary", "Tegelinstellingen"));
|
||||
options.append(node("summary", "Bediening & weergave instellen"));
|
||||
options.open = selectedTile === tile.entity;
|
||||
options.ontoggle = () => {
|
||||
li.classList.toggle("selected-tile", options.open);
|
||||
if (options.open) {
|
||||
selectedTile = tile.entity;
|
||||
document.querySelectorAll(".tile-options").forEach((other) => {
|
||||
if (other !== options) other.open = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
li.onclick = (e) => {
|
||||
if (!e.target.closest("input, select, button, summary, .tile-options"))
|
||||
options.open = !options.open;
|
||||
};
|
||||
const controls = {};
|
||||
const domain = tile.entity.split(".")[0];
|
||||
const fields = [
|
||||
[
|
||||
@@ -295,10 +311,10 @@ function renderTiles() {
|
||||
)
|
||||
fields.push([
|
||||
"inline",
|
||||
"Op de tegel",
|
||||
"Kleine slider op deze tegel?",
|
||||
[
|
||||
["none", "Geen extra bediening"],
|
||||
["slider", "Mini-schuif"],
|
||||
["none", "Nee"],
|
||||
["slider", "Ja, direct bedienen"],
|
||||
],
|
||||
]);
|
||||
if (domain === "sensor")
|
||||
@@ -328,6 +344,7 @@ function renderTiles() {
|
||||
: key === "history_hours"
|
||||
? 24
|
||||
: "none");
|
||||
controls[key] = input;
|
||||
input.onchange = () => {
|
||||
tile.options = {
|
||||
...tile.options,
|
||||
@@ -337,11 +354,18 @@ function renderTiles() {
|
||||
tile.options.inline = "none";
|
||||
if (key === "inline" && input.value === "slider")
|
||||
tile.options.display = "standard";
|
||||
for (const [field, control] of Object.entries(controls)) {
|
||||
if (tile.options[field] !== undefined)
|
||||
control.value = tile.options[field];
|
||||
}
|
||||
markDirty();
|
||||
};
|
||||
label.append(input);
|
||||
options.append(label);
|
||||
}
|
||||
const inspectTile = node("button", "Inspecteer deze tegel", "quiet");
|
||||
inspectTile.onclick = () => inspect(tile.entity);
|
||||
options.append(inspectTile);
|
||||
content.append(options);
|
||||
li.append(node("span", "⠿", "grip"), content, actions);
|
||||
$("#tiles").append(li);
|
||||
@@ -430,7 +454,7 @@ $("#save").onclick = async () => {
|
||||
} catch (e) {
|
||||
toast(e.message);
|
||||
} finally {
|
||||
busy = false;
|
||||
((busy = false), (selectedTile = null));
|
||||
$("#save").disabled = false;
|
||||
}
|
||||
};
|
||||
@@ -625,17 +649,50 @@ $("#create-profile").onclick = async () => {
|
||||
toast(e.message);
|
||||
}
|
||||
};
|
||||
$("#inspect").onclick = async () => {
|
||||
function openSection(id) {
|
||||
const section = $(id);
|
||||
if (section.tagName === "DETAILS") section.open = true;
|
||||
section.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
}
|
||||
$("#nav-tiles").onclick = () => openSection("#tile-section");
|
||||
$("#nav-settings").onclick = () => openSection("#general-settings");
|
||||
$("#nav-inspector").onclick = () => inspect();
|
||||
async function inspect(entity) {
|
||||
if (!selected) return;
|
||||
openSection("#inspector-section");
|
||||
$("#inspection-summary").textContent = "Actuele HA-status ophalen...";
|
||||
try {
|
||||
const data = await (
|
||||
await api(`screens/${encodeURIComponent(selected)}/inspect`)
|
||||
).json();
|
||||
const tiles = entity
|
||||
? data.tiles.filter((t) => t.entity === entity)
|
||||
: data.tiles;
|
||||
$("#inspection-summary").replaceChildren();
|
||||
for (const tile of tiles) {
|
||||
const card = node("article", undefined, "inspection-tile");
|
||||
card.append(
|
||||
node("strong", tile.entity),
|
||||
node("p", `Status: ${tile.state}`),
|
||||
);
|
||||
const options =
|
||||
layout.tiles.find((t) => t.entity === tile.entity)?.options || {};
|
||||
card.append(
|
||||
node(
|
||||
"small",
|
||||
`Kleine slider: ${options.inline === "slider" ? "ja" : "nee"} · Weergave: ${options.display === "watch" ? "grote waarde" : "standaard"}`,
|
||||
),
|
||||
);
|
||||
$("#inspection-summary").append(card);
|
||||
}
|
||||
$("#inspection").textContent = JSON.stringify(
|
||||
await (
|
||||
await api(`screens/${encodeURIComponent(selected)}/inspect`)
|
||||
).json(),
|
||||
entity ? tiles[0] : data,
|
||||
null,
|
||||
2,
|
||||
);
|
||||
} catch (e) {
|
||||
$("#inspection-summary").textContent = e.message;
|
||||
toast(e.message);
|
||||
}
|
||||
};
|
||||
}
|
||||
$("#inspect").onclick = () => inspect();
|
||||
|
||||
@@ -60,15 +60,22 @@
|
||||
maxlength="60"
|
||||
placeholder="Bijvoorbeeld: Woonkamer"
|
||||
/></label>
|
||||
<div class="columns">
|
||||
<nav class="editor-nav" aria-label="Scherm beheren">
|
||||
<button id="nav-tiles" class="quiet">Tegels instellen</button>
|
||||
<button id="nav-settings" class="quiet">
|
||||
Algemene instellingen
|
||||
</button>
|
||||
<button id="nav-inspector" class="quiet">Inspector</button>
|
||||
</nav>
|
||||
<div class="columns" id="tile-section">
|
||||
<div class="tile-editor">
|
||||
<div class="section-title">
|
||||
<h3>Je tegels</h3>
|
||||
<span id="count">0 / 10</span>
|
||||
</div>
|
||||
<p class="hint">
|
||||
Sleep om te ordenen of gebruik de pijltjes. Zes tegels per
|
||||
pagina.
|
||||
Klik op een tegel om bediening en weergave te kiezen. Sleep om
|
||||
te ordenen. Zes tegels per pagina.
|
||||
</p>
|
||||
<ol id="tiles"></ol>
|
||||
<p id="no-tiles" class="hint">
|
||||
@@ -87,7 +94,7 @@
|
||||
<div id="results" aria-live="polite"></div>
|
||||
</div>
|
||||
</div>
|
||||
<details class="screen-settings" open>
|
||||
<details class="screen-settings" id="general-settings" open>
|
||||
<summary>
|
||||
Scherminstellingen
|
||||
<span class="hint">Helderheid, rustmomenten en weergave</span>
|
||||
@@ -100,7 +107,7 @@
|
||||
Gelijke begin- en eindtijd schakelen het nachtvenster uit.
|
||||
</p>
|
||||
</details>
|
||||
<details class="screen-settings">
|
||||
<details class="screen-settings" id="inspector-section">
|
||||
<summary>
|
||||
Inspector
|
||||
<span class="hint"
|
||||
@@ -108,6 +115,7 @@
|
||||
>
|
||||
</summary>
|
||||
<button id="inspect" class="quiet">Lees actuele gegevens</button>
|
||||
<div id="inspection-summary"></div>
|
||||
<pre id="inspection">Selecteer een scherm en lees de gegevens.</pre>
|
||||
</details>
|
||||
<footer class="savebar">
|
||||
|
||||
@@ -655,3 +655,42 @@ pre {
|
||||
.tile .tile-options select {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.editor-nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin: 20px 0;
|
||||
padding: 12px;
|
||||
background: #eaf3fc;
|
||||
border-radius: 14px;
|
||||
}
|
||||
.editor-nav button {
|
||||
background: white;
|
||||
border: 1px solid #c7d9ea;
|
||||
}
|
||||
.tile.selected-tile {
|
||||
border-color: #009fe3;
|
||||
background: #f0f9ff;
|
||||
}
|
||||
.tile-options summary {
|
||||
cursor: pointer;
|
||||
color: #007fb6;
|
||||
font-weight: 650;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.tile-options > button {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.inspection-tile {
|
||||
padding: 14px;
|
||||
margin: 10px 0;
|
||||
border: 1px solid #d8e3ed;
|
||||
border-radius: 12px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
#general-settings,
|
||||
#inspector-section,
|
||||
#tile-section {
|
||||
scroll-margin-top: 16px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user