mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
fix v1.33.3: icon picker shows the auto icon when none set
- marker dialog stores autoIcon (DevItem.icon); ha-icon-picker gets it as placeholder, fallback input too; 'Auto: mdi:...' hint with preview under the picker, hidden once an explicit icon is chosen - smoke_icon_placeholder.mjs; TESTING/CHANGELOG same-commit
This commit is contained in:
@@ -11,7 +11,7 @@ PLANS_DIR = "houseplan/plans" # relative to the HA configuration directory
|
|||||||
FILES_URL = "/houseplan_files/files"
|
FILES_URL = "/houseplan_files/files"
|
||||||
FILES_DIR = "houseplan/files"
|
FILES_DIR = "houseplan/files"
|
||||||
CONF_ADMIN_ONLY = "admin_only"
|
CONF_ADMIN_ONLY = "admin_only"
|
||||||
VERSION = "1.33.2"
|
VERSION = "1.33.3"
|
||||||
|
|
||||||
DEFAULT_CONFIG: dict = {
|
DEFAULT_CONFIG: dict = {
|
||||||
"spaces": [],
|
"spaces": [],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -16,5 +16,5 @@
|
|||||||
"issue_tracker": "https://github.com/Matysh/houseplan-card/issues",
|
"issue_tracker": "https://github.com/Matysh/houseplan-card/issues",
|
||||||
"requirements": [],
|
"requirements": [],
|
||||||
"single_config_entry": true,
|
"single_config_entry": true,
|
||||||
"version": "1.33.2"
|
"version": "1.33.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { launch } from './serve.mjs';
|
||||||
|
const { page, browser } = await launch();
|
||||||
|
const res = await page.evaluate(async () => {
|
||||||
|
const out = {};
|
||||||
|
const c = window.__card;
|
||||||
|
const sr = () => c.shadowRoot || c.renderRoot;
|
||||||
|
c._setMode('devices'); await c.updateComplete;
|
||||||
|
// устройство без явной иконки (marker.icon пуст)
|
||||||
|
const dev = c._devices.find((d) => !d.marker?.icon && d.icon);
|
||||||
|
out.hasAutoDev = !!dev;
|
||||||
|
c._openMarkerDialog(dev); await c.updateComplete;
|
||||||
|
out.autoIconStored = c._markerDialog.autoIcon === dev.icon;
|
||||||
|
out.iconEmpty = c._markerDialog.icon === '';
|
||||||
|
// подсказка с авто-иконкой видна
|
||||||
|
const hint = sr().querySelector('.iconauto');
|
||||||
|
out.hintShown = !!hint && hint.textContent.includes(dev.icon);
|
||||||
|
out.hintIcon = hint?.querySelector('ha-icon')?.getAttribute('icon') === dev.icon;
|
||||||
|
// пикер (или фолбэк-инпут) получил placeholder
|
||||||
|
const picker = sr().querySelector('ha-icon-picker');
|
||||||
|
const inputs = [...sr().querySelectorAll('.dialog input')];
|
||||||
|
out.placeholderSet = picker
|
||||||
|
? picker.placeholder === dev.icon
|
||||||
|
: inputs.some((i) => i.placeholder === dev.icon);
|
||||||
|
// при явной иконке подсказки нет
|
||||||
|
c._markerDialog = { ...c._markerDialog, icon: 'mdi:star' }; await c.updateComplete;
|
||||||
|
out.noHintWhenExplicit = !sr().querySelector('.iconauto');
|
||||||
|
c._markerDialog = null; await c.updateComplete;
|
||||||
|
return out;
|
||||||
|
});
|
||||||
|
console.log(JSON.stringify(res, null, 1));
|
||||||
|
await browser.close();
|
||||||
File diff suppressed because one or more lines are too long
Vendored
+17
-4
File diff suppressed because one or more lines are too long
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.33.3 — 2026-07-22
|
||||||
|
- Device dialog: when no icon is set explicitly, the icon picker no longer
|
||||||
|
looks empty — it shows the **auto-derived icon** (from the icon rules /
|
||||||
|
device class) as a placeholder, with an "Auto: mdi:…" hint line underneath.
|
||||||
|
Picking an explicit icon replaces it as before; clearing returns to auto.
|
||||||
|
|
||||||
## v1.33.2 — 2026-07-22
|
## v1.33.2 — 2026-07-22
|
||||||
- Removed the **Reset** button from the Device editor. It wiped the entire
|
- Removed the **Reset** button from the Device editor. It wiped the entire
|
||||||
layout — positions of all devices, room cards and their scales across every
|
layout — positions of all devices, room cards and their scales across every
|
||||||
|
|||||||
@@ -140,6 +140,10 @@ Run the *core flows* (marked ★ below) in each environment at least once per mi
|
|||||||
(explicit ripple color still wins); off/white lights unchanged [auto]
|
(explicit ripple color still wins); off/white lights unchanged [auto]
|
||||||
- [ ] Alarm pulse (v1.27.0): leak/smoke/gas/CO/siren in 'on' pulse a red ring over any
|
- [ ] Alarm pulse (v1.27.0): leak/smoke/gas/CO/siren in 'on' pulse a red ring over any
|
||||||
display mode; clears on 'off'; unavailable never alarms [auto]; reduced-motion static
|
display mode; clears on 'off'; unavailable never alarms [auto]; reduced-motion static
|
||||||
|
- [ ] Icon picker placeholder (v1.33.3): with no explicit icon the device
|
||||||
|
dialog's icon picker shows the auto-derived icon as its placeholder, plus
|
||||||
|
an "Auto: mdi:..." hint line with the icon preview; the hint disappears
|
||||||
|
once an explicit icon is picked [auto]
|
||||||
- [ ] No Reset button (v1.33.2): the Device editor toolbar has three tools —
|
- [ ] No Reset button (v1.33.2): the Device editor toolbar has three tools —
|
||||||
add, show all, icon rules; the layout-wiping Reset is gone [auto]
|
add, show all, icon rules; the layout-wiping Reset is gone [auto]
|
||||||
- [ ] Grid in all editors + decor fade (v1.33.1): the dot grid shows in the
|
- [ ] Grid in all editors + decor fade (v1.33.1): the dot grid shows in the
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "houseplan-card",
|
"name": "houseplan-card",
|
||||||
"version": "1.33.2",
|
"version": "1.33.3",
|
||||||
"description": "Interactive house plan Lovelace card for Home Assistant",
|
"description": "Interactive house plan Lovelace card for Home Assistant",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
+12
-3
@@ -32,7 +32,7 @@ import './space-card';
|
|||||||
import { cardStyles } from './styles';
|
import { cardStyles } from './styles';
|
||||||
import { langOf, t, type I18nKey } from './i18n';
|
import { langOf, t, type I18nKey } from './i18n';
|
||||||
|
|
||||||
const CARD_VERSION = '1.33.2';
|
const CARD_VERSION = '1.33.3';
|
||||||
const LS_KEY = 'houseplan_card_layout_v1';
|
const LS_KEY = 'houseplan_card_layout_v1';
|
||||||
const LS_CFG = 'houseplan_card_cfg_v1'; // cache of the server config+layout for instant rendering
|
const LS_CFG = 'houseplan_card_cfg_v1'; // cache of the server config+layout for instant rendering
|
||||||
const LS_ZOOM = 'houseplan_card_zoom_v1';
|
const LS_ZOOM = 'houseplan_card_zoom_v1';
|
||||||
@@ -159,6 +159,7 @@ class HouseplanCard extends LitElement {
|
|||||||
binding: string; // 'device:<id>' | 'entity:<eid>' | 'virtual'
|
binding: string; // 'device:<id>' | 'entity:<eid>' | 'virtual'
|
||||||
bindingFilter: string;
|
bindingFilter: string;
|
||||||
icon: string; // '' = auto
|
icon: string; // '' = auto
|
||||||
|
autoIcon: string; // the icon the rules would give — picker placeholder
|
||||||
display: 'badge' | 'ripple' | 'icon_ripple' | 'value';
|
display: 'badge' | 'ripple' | 'icon_ripple' | 'value';
|
||||||
rippleColor: string; // '' = accent
|
rippleColor: string; // '' = accent
|
||||||
rippleSize: number; // in icon diameters
|
rippleSize: number; // in icon diameters
|
||||||
@@ -1984,6 +1985,7 @@ class HouseplanCard extends LitElement {
|
|||||||
binding: d.bindingKind === 'virtual' ? 'virtual' : d.bindingKind + ':' + d.bindingRef,
|
binding: d.bindingKind === 'virtual' ? 'virtual' : d.bindingKind + ':' + d.bindingRef,
|
||||||
bindingFilter: '',
|
bindingFilter: '',
|
||||||
icon: d.marker?.icon || '',
|
icon: d.marker?.icon || '',
|
||||||
|
autoIcon: d.icon || '',
|
||||||
display: d.marker?.display || 'badge',
|
display: d.marker?.display || 'badge',
|
||||||
rippleColor: d.marker?.ripple_color || '',
|
rippleColor: d.marker?.ripple_color || '',
|
||||||
rippleSize: Number(d.marker?.ripple_size) > 0 ? Number(d.marker!.ripple_size) : 3,
|
rippleSize: Number(d.marker?.ripple_size) > 0 ? Number(d.marker!.ripple_size) : 3,
|
||||||
@@ -2001,7 +2003,7 @@ class HouseplanCard extends LitElement {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
this._markerDialog = {
|
this._markerDialog = {
|
||||||
name: '', binding: 'virtual', bindingFilter: '', icon: '',
|
name: '', binding: 'virtual', bindingFilter: '', icon: '', autoIcon: '',
|
||||||
display: 'badge', rippleColor: '', rippleSize: 3, size: 1, angle: 0,
|
display: 'badge', rippleColor: '', rippleSize: 3, size: 1, angle: 0,
|
||||||
tapAction: '', model: '',
|
tapAction: '', model: '',
|
||||||
link: '', description: '', pdfs: [], room: '', busy: false,
|
link: '', description: '', pdfs: [], room: '', busy: false,
|
||||||
@@ -3640,10 +3642,17 @@ class HouseplanCard extends LitElement {
|
|||||||
<label>${this._t('marker.icon_label')}</label>
|
<label>${this._t('marker.icon_label')}</label>
|
||||||
${customElements.get('ha-icon-picker')
|
${customElements.get('ha-icon-picker')
|
||||||
? html`<ha-icon-picker .hass=${this.hass} .value=${d.icon}
|
? html`<ha-icon-picker .hass=${this.hass} .value=${d.icon}
|
||||||
|
.placeholder=${d.autoIcon || undefined}
|
||||||
|
.fallbackPath=${undefined}
|
||||||
@value-changed=${(e: any) => (this._markerDialog = { ...d, icon: e.detail.value || '' })}></ha-icon-picker>`
|
@value-changed=${(e: any) => (this._markerDialog = { ...d, icon: e.detail.value || '' })}></ha-icon-picker>`
|
||||||
: html`<input class="namein" type="text" placeholder=${this._t('marker.icon_ph')}
|
: html`<input class="namein" type="text"
|
||||||
|
placeholder=${d.autoIcon || this._t('marker.icon_ph')}
|
||||||
.value=${d.icon}
|
.value=${d.icon}
|
||||||
@input=${(e: Event) => (this._markerDialog = { ...d, icon: (e.target as HTMLInputElement).value })} />`}
|
@input=${(e: Event) => (this._markerDialog = { ...d, icon: (e.target as HTMLInputElement).value })} />`}
|
||||||
|
${!d.icon && d.autoIcon
|
||||||
|
? html`<p class="muted iconauto"><ha-icon icon=${d.autoIcon}></ha-icon>
|
||||||
|
${this._t('marker.icon_auto', { icon: d.autoIcon })}</p>`
|
||||||
|
: nothing}
|
||||||
|
|
||||||
<label>${this._t('marker.display_label')}</label>
|
<label>${this._t('marker.display_label')}</label>
|
||||||
<select class="areasel"
|
<select class="areasel"
|
||||||
|
|||||||
+2
-1
@@ -277,5 +277,6 @@
|
|||||||
"decor.text_size": "Size",
|
"decor.text_size": "Size",
|
||||||
"decor.size_s": "Small",
|
"decor.size_s": "Small",
|
||||||
"decor.size_m": "Medium",
|
"decor.size_m": "Medium",
|
||||||
"decor.size_l": "Large"
|
"decor.size_l": "Large",
|
||||||
|
"marker.icon_auto": "Auto: {icon} (by icon rules; pick one to override)"
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -277,5 +277,6 @@
|
|||||||
"decor.text_size": "Размер",
|
"decor.text_size": "Размер",
|
||||||
"decor.size_s": "Мелкий",
|
"decor.size_s": "Мелкий",
|
||||||
"decor.size_m": "Средний",
|
"decor.size_m": "Средний",
|
||||||
"decor.size_l": "Крупный"
|
"decor.size_l": "Крупный",
|
||||||
|
"marker.icon_auto": "Авто: {icon} (по правилам иконок; выберите свою, чтобы заменить)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -396,6 +396,14 @@ export const cardStyles = css`
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
.roomlabel .rlm.lit { opacity: 1; }
|
.roomlabel .rlm.lit { opacity: 1; }
|
||||||
|
.iconauto {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 4px 0 0;
|
||||||
|
}
|
||||||
|
.iconauto ha-icon { --mdc-icon-size: 18px; }
|
||||||
.rlhandle {
|
.rlhandle {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
Reference in New Issue
Block a user