mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 08:28:31 +00:00
feat v1.8.4: онбординг — обязательная подложка и привязка к зоне (с кнопкой «без зоны»), авто-диалог пространства и авто-вход в разметку после первого пространства
This commit is contained in:
@@ -10,7 +10,7 @@ PLANS_DIR = "houseplan/plans" # относительно каталога ко
|
||||
FILES_URL = "/houseplan_files/files"
|
||||
FILES_DIR = "houseplan/files"
|
||||
CONF_ADMIN_ONLY = "admin_only"
|
||||
VERSION = "1.8.3"
|
||||
VERSION = "1.8.4"
|
||||
|
||||
DEFAULT_CONFIG: dict = {
|
||||
"spaces": [],
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -15,5 +15,5 @@
|
||||
"iot_class": "local_push",
|
||||
"issue_tracker": "https://github.com/justbusiness/houseplan-card/issues",
|
||||
"requirements": [],
|
||||
"version": "1.8.3"
|
||||
"version": "1.8.4"
|
||||
}
|
||||
Vendored
+15
-7
File diff suppressed because one or more lines are too long
@@ -1,5 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## v1.8.4 — 2026-07-04 (онбординг: обязательные поля + ведение пользователя)
|
||||
- Первичная инициализация приведена к целевому сценарию: установка → диалог пространства →
|
||||
комнаты → авто-значки устройств.
|
||||
- **Подложка обязательна** при создании пространства: «Сохранить» неактивна без загруженного
|
||||
плана (раньше требовалось только название — можно было создать пустое пространство).
|
||||
- **Зона комнаты обязательна** с явным выходом: основная «Сохранить» требует привязку к зоне HA;
|
||||
для декоративных комнат без устройств (холл, сауна) есть отдельная кнопка «Без зоны»
|
||||
(нужно только имя). Раньше сохранить можно было по «имя ИЛИ зона».
|
||||
- **Ведение пользователя:** на пустом серверном конфиге диалог пространства открывается
|
||||
автоматически; после добавления первого пространства карточка сама входит в режим разметки
|
||||
комнат с подсказкой «обведите комнаты».
|
||||
- При сохранении комнаты с зоной значки устройств этой зоны авто-расставляются внутри контура
|
||||
(курируемый набор: без мостов/служебных/дублей/одиночных ламп из групп), тост показывает,
|
||||
сколько устройств добавлено.
|
||||
|
||||
## v1.8.3 — 2026-07-04 (мгновенный старт: кэш конфига, данные в фоне)
|
||||
- Иконки и план появлялись с задержкой — карточка ждала ответа сервера (WS `config/get`
|
||||
+ ретраи прогрева соединения), до этого модель пространств была пуста.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "houseplan-card",
|
||||
"version": "1.8.3",
|
||||
"version": "1.8.4",
|
||||
"description": "Interactive house plan Lovelace card for Home Assistant (dacha Kirillovskoe)",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
+61
-6
@@ -13,7 +13,7 @@ import {
|
||||
} from './logic';
|
||||
import './editor';
|
||||
|
||||
const CARD_VERSION = '1.8.3';
|
||||
const CARD_VERSION = '1.8.4';
|
||||
const LS_KEY = 'houseplan_card_layout_v1';
|
||||
const LS_CFG = 'houseplan_card_cfg_v1'; // кэш серверного конфига+раскладки для мгновенного рендера
|
||||
const LS_ZOOM = 'houseplan_card_zoom_v1';
|
||||
@@ -155,6 +155,7 @@ class HouseplanCard extends LitElement {
|
||||
private _pinchStart: { dist: number; zoom: number } | null = null;
|
||||
private _suppressClick = false;
|
||||
private _roViewport?: ResizeObserver;
|
||||
private _onboardingShown = false; // авто-диалог пространства показан один раз за сессию
|
||||
|
||||
private _infoCard: DevItem | null = null;
|
||||
private _markerDialog: {
|
||||
@@ -383,6 +384,17 @@ class HouseplanCard extends LitElement {
|
||||
this._roViewport.observe(stage);
|
||||
}
|
||||
if (stage && !this._view) this._refitView();
|
||||
// онбординг: на пустом серверном конфиге сразу открываем диалог пространства
|
||||
if (
|
||||
this._serverStorage &&
|
||||
this._loadOk &&
|
||||
this._model.length === 0 &&
|
||||
!this._spaceDialog &&
|
||||
!this._onboardingShown
|
||||
) {
|
||||
this._onboardingShown = true;
|
||||
this._openSpaceDialog('create');
|
||||
}
|
||||
}
|
||||
|
||||
// ================= сервер: конфиг + раскладка =================
|
||||
@@ -1316,8 +1328,21 @@ class HouseplanCard extends LitElement {
|
||||
this._cursorPt = this._snap(this._svgPoint(ev));
|
||||
}
|
||||
|
||||
/** Сохранить комнату с обязательной привязкой к зоне HA. */
|
||||
private _saveRoom(): void {
|
||||
if (!this._contourClosed || !this._areaSel && !this._nameSel) return;
|
||||
if (!this._areaSel) return;
|
||||
this._commitRoom();
|
||||
}
|
||||
|
||||
/** Сохранить декоративную комнату без зоны (нужно только имя). */
|
||||
private _saveRoomNoArea(): void {
|
||||
if (!this._nameSel.trim()) return;
|
||||
this._areaSel = '';
|
||||
this._commitRoom();
|
||||
}
|
||||
|
||||
private _commitRoom(): void {
|
||||
if (!this._contourClosed) return;
|
||||
const sp = this._curSpaceCfg;
|
||||
if (!sp) return;
|
||||
const H = this._spaceH;
|
||||
@@ -1332,12 +1357,19 @@ class HouseplanCard extends LitElement {
|
||||
this._saveConfig();
|
||||
this._path = [];
|
||||
this._pathSegs = [];
|
||||
const boundArea = this._areaSel;
|
||||
this._areaSel = '';
|
||||
this._nameSel = '';
|
||||
this._roomDialog = false;
|
||||
this._regSignature = '';
|
||||
this._maybeRebuildDevices();
|
||||
this._showToast('Комната сохранена');
|
||||
// авто-добавление значков устройств зоны — через _defaultPositions (сетка внутри контура)
|
||||
const added = boundArea ? this._devices.filter((d) => d.area === boundArea).length : 0;
|
||||
this._showToast(
|
||||
boundArea
|
||||
? `Комната сохранена — добавлено устройств: ${added}`
|
||||
: 'Комната сохранена (без зоны)',
|
||||
);
|
||||
}
|
||||
|
||||
private _cancelPath(): void {
|
||||
@@ -1671,6 +1703,11 @@ class HouseplanCard extends LitElement {
|
||||
private async _saveSpaceDialog(): Promise<void> {
|
||||
const d = this._spaceDialog;
|
||||
if (!d || d.busy || !d.title.trim()) return;
|
||||
if (!d.planFile && !d.planUrl) {
|
||||
this._showToast('Загрузите подложку — план этажа обязателен');
|
||||
return;
|
||||
}
|
||||
const wasFirst = d.mode === 'create' && (this._serverCfg?.spaces.length || 0) === 0;
|
||||
this._spaceDialog = { ...d, busy: true };
|
||||
try {
|
||||
const cfg = this._serverCfg!;
|
||||
@@ -1702,7 +1739,17 @@ class HouseplanCard extends LitElement {
|
||||
if (d.mode === 'create') this._space = sp.id;
|
||||
this._regSignature = '';
|
||||
this._maybeRebuildDevices();
|
||||
this._showToast(d.mode === 'create' ? 'Пространство добавлено' : 'Пространство сохранено');
|
||||
if (wasFirst) {
|
||||
// ведём пользователя дальше: сразу в режим разметки комнат
|
||||
this._edit = false;
|
||||
this._markup = true;
|
||||
this._tool = 'draw';
|
||||
this._path = [];
|
||||
this._cursorPt = null;
|
||||
this._showToast('Пространство добавлено. Обведите комнаты: кликайте по точкам сетки и замкните контур.');
|
||||
} else {
|
||||
this._showToast(d.mode === 'create' ? 'Пространство добавлено' : 'Пространство сохранено');
|
||||
}
|
||||
} catch (e: any) {
|
||||
this._spaceDialog = { ...this._spaceDialog!, busy: false };
|
||||
this._showToast('Ошибка: ' + (e?.message || e));
|
||||
@@ -2164,7 +2211,9 @@ class HouseplanCard extends LitElement {
|
||||
: nothing}
|
||||
<span class="spacer"></span>
|
||||
<button class="btn ghost" @click=${() => (this._spaceDialog = null)}>Отмена</button>
|
||||
<button class="btn on" @click=${this._saveSpaceDialog} ?disabled=${!d.title.trim() || d.busy}>
|
||||
<button class="btn on" @click=${this._saveSpaceDialog}
|
||||
?disabled=${!d.title.trim() || !(d.planFile || d.planUrl) || d.busy}
|
||||
title=${!(d.planFile || d.planUrl) ? 'Загрузите подложку (план этажа)' : ''}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>${d.busy ? '…' : 'Сохранить'}
|
||||
</button>
|
||||
</div>
|
||||
@@ -2198,7 +2247,13 @@ class HouseplanCard extends LitElement {
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn ghost" @click=${this._roomDialogCancel}>Отмена</button>
|
||||
<button class="btn on" @click=${this._saveRoom} ?disabled=${!this._areaSel && !this._nameSel}>
|
||||
<span class="spacer"></span>
|
||||
<button class="btn ghost" @click=${this._saveRoomNoArea} ?disabled=${!this._nameSel.trim()}
|
||||
title="Декоративная комната без привязки к зоне (например, холл)">
|
||||
Без зоны
|
||||
</button>
|
||||
<button class="btn on" @click=${this._saveRoom} ?disabled=${!this._areaSel}
|
||||
title=${!this._areaSel ? 'Выберите зону Home Assistant' : ''}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>Сохранить
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user