mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
feat v1.6.2: room field for all device markers (override placement, moves marker to room center); Edit button in info-card opens edit dialog
This commit is contained in:
@@ -10,7 +10,7 @@ PLANS_DIR = "houseplan/plans" # относительно каталога ко
|
|||||||
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.6.1"
|
VERSION = "1.6.2"
|
||||||
|
|
||||||
DEFAULT_CONFIG: dict = {
|
DEFAULT_CONFIG: dict = {
|
||||||
"spaces": [],
|
"spaces": [],
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Vendored
+11
-8
File diff suppressed because one or more lines are too long
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.6.2 — 2026-07-04
|
||||||
|
- Поле «Комната» в диалоге устройства теперь для ВСЕХ значков (не только виртуальных):
|
||||||
|
для привязанных — «переопределить размещение» (по умолчанию по зоне устройства); смена
|
||||||
|
комнаты переставляет значок в её центр. Сохраняется в marker.space/area и выигрывает у зоны HA.
|
||||||
|
- В инфо-карточке добавлена кнопка «Редактировать» — открывает диалог редактирования устройства.
|
||||||
|
|
||||||
## v1.6.0 — 2026-07-04 (Фаза 3: редактор устройств)
|
## v1.6.0 — 2026-07-04 (Фаза 3: редактор устройств)
|
||||||
- Модель «маркеров» (config.markers[]): гибрид — авто-устройства HA появляются сами, маркеры
|
- Модель «маркеров» (config.markers[]): гибрид — авто-устройства HA появляются сами, маркеры
|
||||||
правят/перепривязывают/дополняют их и описывают ручные/виртуальные значки. id маркера
|
правят/перепривязывают/дополняют их и описывают ручные/виртуальные значки. id маркера
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "houseplan-card",
|
"name": "houseplan-card",
|
||||||
"version": "1.6.1",
|
"version": "1.6.2",
|
||||||
"description": "Interactive house plan Lovelace card for Home Assistant (dacha Kirillovskoe)",
|
"description": "Interactive house plan Lovelace card for Home Assistant (dacha Kirillovskoe)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
+26
-21
@@ -12,7 +12,7 @@ import { FLOOR_BG, FLOOR_BG_RECT } from './data/backgrounds';
|
|||||||
import { EXCLUDED_DOMAINS, iconFor, DOMAIN_PRIORITY } from './rules';
|
import { EXCLUDED_DOMAINS, iconFor, DOMAIN_PRIORITY } from './rules';
|
||||||
import './editor';
|
import './editor';
|
||||||
|
|
||||||
const CARD_VERSION = '1.6.1';
|
const CARD_VERSION = '1.6.2';
|
||||||
const LS_KEY = 'houseplan_card_layout_v1';
|
const LS_KEY = 'houseplan_card_layout_v1';
|
||||||
const NORM_W = 1000; // ширина рендер-пространства для нормированных конфигов
|
const NORM_W = 1000; // ширина рендер-пространства для нормированных конфигов
|
||||||
|
|
||||||
@@ -671,7 +671,7 @@ class HouseplanCard extends LitElement {
|
|||||||
const [kind, ref] = m.binding.split(':');
|
const [kind, ref] = m.binding.split(':');
|
||||||
if (kind === 'device') {
|
if (kind === 'device') {
|
||||||
const dev = h.devices[ref];
|
const dev = h.devices[ref];
|
||||||
const area = dev?.area_id || m.area || '';
|
const area = m.area || dev?.area_id || '';
|
||||||
const space = (area && areaMap[area]?.space) || m.space || this._model[0]?.id || '';
|
const space = (area && areaMap[area]?.space) || m.space || this._model[0]?.id || '';
|
||||||
const entIds = dev ? entsBy[dev.id] || [] : [];
|
const entIds = dev ? entsBy[dev.id] || [] : [];
|
||||||
let icon = dev ? iconFor(dev.name_by_user || dev.name || '', dev.model) : 'mdi:help-circle';
|
let icon = dev ? iconFor(dev.name_by_user || dev.name || '', dev.model) : 'mdi:help-circle';
|
||||||
@@ -693,7 +693,7 @@ class HouseplanCard extends LitElement {
|
|||||||
rest.push(item);
|
rest.push(item);
|
||||||
} else if (kind === 'entity') {
|
} else if (kind === 'entity') {
|
||||||
const reg = h.entities[ref];
|
const reg = h.entities[ref];
|
||||||
const area = reg?.area_id || (reg?.device_id && h.devices[reg.device_id]?.area_id) || m.area || '';
|
const area = m.area || reg?.area_id || (reg?.device_id && h.devices[reg.device_id]?.area_id) || '';
|
||||||
const space = (area && areaMap[area]?.space) || m.space || this._model[0]?.id || '';
|
const space = (area && areaMap[area]?.space) || m.space || this._model[0]?.id || '';
|
||||||
const st = h.states[ref];
|
const st = h.states[ref];
|
||||||
const item: DevItem = {
|
const item: DevItem = {
|
||||||
@@ -1281,12 +1281,12 @@ class HouseplanCard extends LitElement {
|
|||||||
cfg.markers = cfg.markers || [];
|
cfg.markers = cfg.markers || [];
|
||||||
// определить id маркера
|
// определить id маркера
|
||||||
let id: string;
|
let id: string;
|
||||||
let space: string | null = null;
|
// комната (выбранная вручную) переопределяет пространство/зону для любого значка
|
||||||
let area: string | null = null;
|
const [roomSp, roomAr] = dlg.room ? dlg.room.split('#') : ['', ''];
|
||||||
|
let space: string | null = roomSp || null;
|
||||||
|
let area: string | null = roomAr || null;
|
||||||
if (dlg.binding === 'virtual') {
|
if (dlg.binding === 'virtual') {
|
||||||
const [sp, ar] = dlg.room ? dlg.room.split('#') : ['', ''];
|
if (!space) space = this._space;
|
||||||
space = sp || this._space;
|
|
||||||
area = ar || null;
|
|
||||||
id = dlg.devId && dlg.devId.startsWith('v_') ? dlg.devId : 'v_' + Date.now().toString(36);
|
id = dlg.devId && dlg.devId.startsWith('v_') ? dlg.devId : 'v_' + Date.now().toString(36);
|
||||||
} else {
|
} else {
|
||||||
const [kind, ref] = dlg.binding.split(':');
|
const [kind, ref] = dlg.binding.split(':');
|
||||||
@@ -1303,15 +1303,19 @@ class HouseplanCard extends LitElement {
|
|||||||
description: dlg.description.trim() || null,
|
description: dlg.description.trim() || null,
|
||||||
pdfs: dlg.pdfs,
|
pdfs: dlg.pdfs,
|
||||||
};
|
};
|
||||||
if (dlg.binding === 'virtual') {
|
// сохраняем выбор комнаты (для виртуальных всегда; для привязанных — если выбрана)
|
||||||
|
if (dlg.binding === 'virtual' || dlg.room) {
|
||||||
marker.space = space;
|
marker.space = space;
|
||||||
marker.area = area;
|
marker.area = area;
|
||||||
}
|
}
|
||||||
|
// сменилась комната → переставить значок в её центр
|
||||||
|
const prevDev = oldId ? this._devices.find((x) => x.id === oldId) : null;
|
||||||
|
const roomChanged = !!dlg.room && prevDev != null && (prevDev.space !== space || prevDev.area !== area);
|
||||||
// удалить прежний маркер (по старому id и по новому id)
|
// удалить прежний маркер (по старому id и по новому id)
|
||||||
cfg.markers = cfg.markers.filter((m) => m.id !== id && m.id !== oldId);
|
cfg.markers = cfg.markers.filter((m) => m.id !== id && m.id !== oldId);
|
||||||
cfg.markers.push(marker);
|
cfg.markers.push(marker);
|
||||||
// позиция: если новый значок или сменилось пространство — поставить в центр комнаты/пространства
|
// позиция: новый значок ИЛИ сменилась комната → поставить в центр комнаты/пространства
|
||||||
if (!this._layout[id]) {
|
if (!this._layout[id] || roomChanged) {
|
||||||
const spm = this._spaceModel(space || undefined);
|
const spm = this._spaceModel(space || undefined);
|
||||||
let cx = spm.vb[0] + spm.vb[2] / 2;
|
let cx = spm.vb[0] + spm.vb[2] / 2;
|
||||||
let cy = spm.vb[1] + spm.vb[3] / 2;
|
let cy = spm.vb[1] + spm.vb[3] / 2;
|
||||||
@@ -1799,6 +1803,9 @@ class HouseplanCard extends LitElement {
|
|||||||
: nothing}
|
: nothing}
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<button class="btn" @click=${() => { const dd = d; this._infoCard = null; this._openMarkerDialog(dd); }}>
|
||||||
|
<ha-icon icon="mdi:pencil"></ha-icon>Редактировать
|
||||||
|
</button>
|
||||||
${d.primary
|
${d.primary
|
||||||
? html`<button class="btn" @click=${() => { const p = d.primary; this._infoCard = null; this._openMoreInfo(p); }}>
|
? html`<button class="btn" @click=${() => { const p = d.primary; this._infoCard = null; this._openMoreInfo(p); }}>
|
||||||
<ha-icon icon="mdi:open-in-new"></ha-icon>Открыть в HA
|
<ha-icon icon="mdi:open-in-new"></ha-icon>Открыть в HA
|
||||||
@@ -1857,16 +1864,14 @@ class HouseplanCard extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${isVirtual
|
<label>Комната${isVirtual ? '' : ' (переопределить размещение)'}</label>
|
||||||
? html`<label>Комната</label>
|
<select class="areasel"
|
||||||
<select class="areasel"
|
@change=${(e: Event) => (this._markerDialog = { ...d, room: (e.target as HTMLSelectElement).value })}>
|
||||||
@change=${(e: Event) => (this._markerDialog = { ...d, room: (e.target as HTMLSelectElement).value })}>
|
<option value="">${isVirtual ? '— выберите комнату —' : '— по зоне устройства (авто) —'}</option>
|
||||||
<option value="">— выберите комнату —</option>
|
${this._allRoomsFlat().map(
|
||||||
${this._allRoomsFlat().map(
|
(r) => html`<option value=${r.value} ?selected=${r.value === d.room}>${r.label}</option>`,
|
||||||
(r) => html`<option value=${r.value} ?selected=${r.value === d.room}>${r.label}</option>`,
|
)}
|
||||||
)}
|
</select>
|
||||||
</select>`
|
|
||||||
: nothing}
|
|
||||||
|
|
||||||
<label>Иконка</label>
|
<label>Иконка</label>
|
||||||
${customElements.get('ha-icon-picker')
|
${customElements.get('ha-icon-picker')
|
||||||
|
|||||||
Reference in New Issue
Block a user