mirror of
https://github.com/Matysh/houseplan-card
synced 2026-07-31 16:38:31 +00:00
refactor+fix v1.10.0: аудит — гонки записи (asyncio.Lock, атомарный rev), точечный layout/update вместо layout/set (анти last-writer-wins), layout/delete, safeUrl против XSS в link/pdfs, fetchWithAuth, KEY_HASS, стриминговый лимит upload, модульность (styles/types/devices), динамические пространства в GUI-редакторе, чистка мёртвого кода (file/set, GROUP_TITLES)
This commit is contained in:
+40
-23
@@ -1,30 +1,9 @@
|
||||
/** Редактор конфигурации карточки (GUI в Lovelace). */
|
||||
import { LitElement, html, nothing } from 'lit';
|
||||
|
||||
const SCHEMA = [
|
||||
{ name: 'title', selector: { text: {} } },
|
||||
{
|
||||
name: 'default_floor',
|
||||
selector: {
|
||||
select: {
|
||||
mode: 'dropdown',
|
||||
options: [
|
||||
{ value: 'f1', label: '1 этаж' },
|
||||
{ value: 'f2', label: '2 этаж' },
|
||||
{ value: 'yard', label: 'Двор' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{ name: 'icon_size', selector: { number: { min: 1, max: 6, step: 0.1, mode: 'box' } } },
|
||||
{ name: 'show_temperature', selector: { boolean: {} } },
|
||||
{ name: 'live_states', selector: { boolean: {} } },
|
||||
{ name: 'show_signal', selector: { boolean: {} } },
|
||||
];
|
||||
|
||||
const LABELS: Record<string, string> = {
|
||||
title: 'Заголовок',
|
||||
default_floor: 'Этаж по умолчанию',
|
||||
default_floor: 'Пространство по умолчанию',
|
||||
icon_size: 'Размер иконок, % ширины плана',
|
||||
show_temperature: 'Показывать температуру',
|
||||
live_states: 'Живые состояния (вкл/выкл, открыто…)',
|
||||
@@ -34,22 +13,60 @@ const LABELS: Record<string, string> = {
|
||||
class HouseplanCardEditor extends LitElement {
|
||||
public hass?: any;
|
||||
private _config?: any;
|
||||
private _spaces: { value: string; label: string }[] | null = null;
|
||||
private _spacesLoading = false;
|
||||
|
||||
static properties = {
|
||||
hass: { attribute: false },
|
||||
_config: { state: true },
|
||||
_spaces: { state: true },
|
||||
};
|
||||
|
||||
public setConfig(config: any): void {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
/** Пространства из серверного конфига интеграции — не хардкод. */
|
||||
private async _loadSpaces(): Promise<void> {
|
||||
if (this._spaces || this._spacesLoading || !this.hass) return;
|
||||
this._spacesLoading = true;
|
||||
try {
|
||||
const resp = await this.hass.callWS({ type: 'houseplan/config/get' });
|
||||
this._spaces = (resp?.config?.spaces || []).map((s: any) => ({
|
||||
value: s.id,
|
||||
label: s.title || s.id,
|
||||
}));
|
||||
} catch {
|
||||
this._spaces = [];
|
||||
} finally {
|
||||
this._spacesLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private get _schema(): any[] {
|
||||
const spaces = this._spaces || [];
|
||||
return [
|
||||
{ name: 'title', selector: { text: {} } },
|
||||
spaces.length
|
||||
? {
|
||||
name: 'default_floor',
|
||||
selector: { select: { mode: 'dropdown', options: spaces } },
|
||||
}
|
||||
: { name: 'default_floor', selector: { text: {} } },
|
||||
{ name: 'icon_size', selector: { number: { min: 1, max: 6, step: 0.1, mode: 'box' } } },
|
||||
{ name: 'show_temperature', selector: { boolean: {} } },
|
||||
{ name: 'live_states', selector: { boolean: {} } },
|
||||
{ name: 'show_signal', selector: { boolean: {} } },
|
||||
];
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this.hass || !this._config) return nothing;
|
||||
this._loadSpaces();
|
||||
return html`<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this._config}
|
||||
.schema=${SCHEMA}
|
||||
.schema=${this._schema}
|
||||
.computeLabel=${(s: any) => LABELS[s.name] || s.name}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>`;
|
||||
|
||||
Reference in New Issue
Block a user