mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-20 06:39:27 +00:00
Compare commits
13 Commits
add-Use-UU
...
20220329.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2a12172eeb | ||
![]() |
85d3011625 | ||
![]() |
ca22ec6340 | ||
![]() |
61f6e8855b | ||
![]() |
a44b8981e1 | ||
![]() |
b080bca9ce | ||
![]() |
d30e8ee9d8 | ||
![]() |
637e4203e5 | ||
![]() |
2648a53bbc | ||
![]() |
b3fa0cccb4 | ||
![]() |
dd963be723 | ||
![]() |
224df896a1 | ||
![]() |
a58b4fb262 |
@@ -1,18 +1,18 @@
|
||||
/* eslint-disable lit/no-template-arrow */
|
||||
import "@material/mwc-button";
|
||||
import { LitElement, TemplateResult, html } from "lit";
|
||||
import { html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
|
||||
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
|
||||
import "../../../../src/components/ha-form/ha-form";
|
||||
import "../../components/demo-black-white-row";
|
||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
||||
import { computeInitialHaFormData } from "../../../../src/components/ha-form/compute-initial-ha-form-data";
|
||||
import "../../../../src/components/ha-form/ha-form";
|
||||
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
|
||||
import { getEntity } from "../../../../src/fake_data/entity";
|
||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||
import { HomeAssistant } from "../../../../src/types";
|
||||
import { getEntity } from "../../../../src/fake_data/entity";
|
||||
import "../../components/demo-black-white-row";
|
||||
|
||||
const ENTITIES = [
|
||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
||||
@@ -147,7 +147,9 @@ const SCHEMAS: {
|
||||
{ name: "target", selector: { target: {} } },
|
||||
{ name: "number", selector: { number: { min: 0, max: 10 } } },
|
||||
{ name: "boolean", selector: { boolean: {} } },
|
||||
{ name: "time", selector: { time: {} } },
|
||||
{ name: "time", required: true, selector: { time: {} } },
|
||||
{ name: "datetime", required: true, selector: { datetime: {} } },
|
||||
{ name: "date", required: true, selector: { date: {} } },
|
||||
{ name: "action", selector: { action: {} } },
|
||||
{ name: "text", selector: { text: { multiline: false } } },
|
||||
{ name: "text_multiline", selector: { text: { multiline: true } } },
|
||||
|
@@ -1,20 +1,20 @@
|
||||
/* eslint-disable lit/no-template-arrow */
|
||||
import "@material/mwc-button";
|
||||
import { LitElement, TemplateResult, css, html } from "lit";
|
||||
import { css, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
||||
import "../../../../src/components/ha-selector/ha-selector";
|
||||
import "../../../../src/components/ha-settings-row";
|
||||
import { BlueprintInput } from "../../../../src/data/blueprint";
|
||||
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
||||
import { getEntity } from "../../../../src/fake_data/entity";
|
||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||
import { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin";
|
||||
import type { HomeAssistant } from "../../../../src/types";
|
||||
import "../../components/demo-black-white-row";
|
||||
import { BlueprintInput } from "../../../../src/data/blueprint";
|
||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
||||
import { getEntity } from "../../../../src/fake_data/entity";
|
||||
import { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin";
|
||||
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
||||
|
||||
const ENTITIES = [
|
||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
||||
@@ -202,6 +202,7 @@ const SCHEMAS: {
|
||||
input: {
|
||||
entity: { name: "Entity", selector: { entity: { multiple: true } } },
|
||||
device: { name: "Device", selector: { device: { multiple: true } } },
|
||||
area: { name: "Area", selector: { area: { multiple: true } } },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = home-assistant-frontend
|
||||
version = 20220322.0
|
||||
version = 20220329.0
|
||||
author = The Home Assistant Authors
|
||||
author_email = hello@home-assistant.io
|
||||
license = Apache-2.0
|
||||
|
@@ -18,7 +18,6 @@ import "./state-badge";
|
||||
|
||||
interface HassEntityWithCachedName extends HassEntity {
|
||||
friendly_name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
||||
@@ -97,9 +96,6 @@ export class HaEntityPicker extends LitElement {
|
||||
|
||||
@property() public entityFilter?: HaEntityPickerEntityFilterFunc;
|
||||
|
||||
@property({ attribute: "item-value-path" }) public itemValuePath =
|
||||
"entity_id";
|
||||
|
||||
@property({ type: Boolean }) public hideClearIcon = false;
|
||||
|
||||
@state() private _opened = false;
|
||||
@@ -148,7 +144,6 @@ export class HaEntityPicker extends LitElement {
|
||||
state: "",
|
||||
last_changed: "",
|
||||
last_updated: "",
|
||||
id: "",
|
||||
context: { id: "", user_id: null, parent_id: null },
|
||||
friendly_name: this.hass!.localize(
|
||||
"ui.components.entity.entity-picker.no_entities"
|
||||
@@ -169,15 +164,10 @@ export class HaEntityPicker extends LitElement {
|
||||
);
|
||||
|
||||
return entityIds
|
||||
.map((key) => {
|
||||
const stateObj = hass!.states[key];
|
||||
|
||||
return {
|
||||
...stateObj,
|
||||
friendly_name: computeStateName(stateObj) || key,
|
||||
id: stateObj.context.id,
|
||||
};
|
||||
})
|
||||
.map((key) => ({
|
||||
...hass!.states[key],
|
||||
friendly_name: computeStateName(hass!.states[key]) || key,
|
||||
}))
|
||||
.sort((entityA, entityB) =>
|
||||
caseInsensitiveStringCompare(
|
||||
entityA.friendly_name,
|
||||
@@ -205,15 +195,10 @@ export class HaEntityPicker extends LitElement {
|
||||
}
|
||||
|
||||
states = entityIds
|
||||
.map((key) => {
|
||||
const stateObj = hass!.states[key];
|
||||
|
||||
return {
|
||||
...stateObj,
|
||||
friendly_name: computeStateName(stateObj) || key,
|
||||
id: stateObj.context?.id,
|
||||
};
|
||||
})
|
||||
.map((key) => ({
|
||||
...hass!.states[key],
|
||||
friendly_name: computeStateName(hass!.states[key]) || key,
|
||||
}))
|
||||
.sort((entityA, entityB) =>
|
||||
caseInsensitiveStringCompare(
|
||||
entityA.friendly_name,
|
||||
@@ -258,7 +243,6 @@ export class HaEntityPicker extends LitElement {
|
||||
state: "",
|
||||
last_changed: "",
|
||||
last_updated: "",
|
||||
id: "",
|
||||
context: { id: "", user_id: null, parent_id: null },
|
||||
friendly_name: this.hass!.localize(
|
||||
"ui.components.entity.entity-picker.no_match"
|
||||
@@ -311,8 +295,8 @@ export class HaEntityPicker extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-combo-box
|
||||
item-value-path="entity_id"
|
||||
item-label-path="friendly_name"
|
||||
.itemValuePath=${this.itemValuePath}
|
||||
.hass=${this.hass}
|
||||
.value=${this._value}
|
||||
.label=${this.label === undefined
|
||||
|
160
src/components/ha-areas-picker.ts
Normal file
160
src/components/ha-areas-picker.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import { css, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { EntityRegistryEntry } from "../data/entity_registry";
|
||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker";
|
||||
import "./ha-area-picker";
|
||||
|
||||
@customElement("ha-areas-picker")
|
||||
export class HaAreasPicker extends SubscribeMixin(LitElement) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@property() public value?: string[];
|
||||
|
||||
@property() public placeholder?: string;
|
||||
|
||||
@property({ type: Boolean, attribute: "no-add" })
|
||||
public noAdd?: boolean;
|
||||
|
||||
/**
|
||||
* Show only areas with entities from specific domains.
|
||||
* @type {Array}
|
||||
* @attr include-domains
|
||||
*/
|
||||
@property({ type: Array, attribute: "include-domains" })
|
||||
public includeDomains?: string[];
|
||||
|
||||
/**
|
||||
* Show no areas with entities of these domains.
|
||||
* @type {Array}
|
||||
* @attr exclude-domains
|
||||
*/
|
||||
@property({ type: Array, attribute: "exclude-domains" })
|
||||
public excludeDomains?: string[];
|
||||
|
||||
/**
|
||||
* Show only areas with entities of these device classes.
|
||||
* @type {Array}
|
||||
* @attr include-device-classes
|
||||
*/
|
||||
@property({ type: Array, attribute: "include-device-classes" })
|
||||
public includeDeviceClasses?: string[];
|
||||
|
||||
@property() public deviceFilter?: HaDevicePickerDeviceFilterFunc;
|
||||
|
||||
@property() public entityFilter?: (entity: EntityRegistryEntry) => boolean;
|
||||
|
||||
@property({ attribute: "picked-area-label" })
|
||||
public pickedAreaLabel?: string;
|
||||
|
||||
@property({ attribute: "pick-area-label" })
|
||||
public pickAreaLabel?: string;
|
||||
|
||||
@property({ type: Boolean }) public disabled?: boolean;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.hass) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
const currentAreas = this._currentAreas;
|
||||
return html`
|
||||
${currentAreas.map(
|
||||
(area) => html`
|
||||
<div>
|
||||
<ha-area-picker
|
||||
.curValue=${area}
|
||||
.noAdd=${this.noAdd}
|
||||
.hass=${this.hass}
|
||||
.value=${area}
|
||||
.label=${this.pickedAreaLabel}
|
||||
.includeDomains=${this.includeDomains}
|
||||
.excludeDomains=${this.excludeDomains}
|
||||
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||
.deviceFilter=${this.deviceFilter}
|
||||
.entityFilter=${this.entityFilter}
|
||||
.disabled=${this.disabled}
|
||||
@value-changed=${this._areaChanged}
|
||||
></ha-area-picker>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
<div>
|
||||
<ha-area-picker
|
||||
.noAdd=${this.noAdd}
|
||||
.hass=${this.hass}
|
||||
.label=${this.pickAreaLabel}
|
||||
.includeDomains=${this.includeDomains}
|
||||
.excludeDomains=${this.excludeDomains}
|
||||
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||
.deviceFilter=${this.deviceFilter}
|
||||
.entityFilter=${this.entityFilter}
|
||||
.disabled=${this.disabled}
|
||||
.placeholder=${this.placeholder}
|
||||
@value-changed=${this._addArea}
|
||||
></ha-area-picker>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private get _currentAreas(): string[] {
|
||||
return this.value || [];
|
||||
}
|
||||
|
||||
private async _updateAreas(areas) {
|
||||
this.value = areas;
|
||||
|
||||
fireEvent(this, "value-changed", {
|
||||
value: areas,
|
||||
});
|
||||
}
|
||||
|
||||
private _areaChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const curValue = (ev.currentTarget as any).curValue;
|
||||
const newValue = ev.detail.value;
|
||||
if (newValue === curValue) {
|
||||
return;
|
||||
}
|
||||
const currentAreas = this._currentAreas;
|
||||
if (!newValue || currentAreas.includes(newValue)) {
|
||||
this._updateAreas(currentAreas.filter((ent) => ent !== curValue));
|
||||
return;
|
||||
}
|
||||
this._updateAreas(
|
||||
currentAreas.map((ent) => (ent === curValue ? newValue : ent))
|
||||
);
|
||||
}
|
||||
|
||||
private _addArea(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
|
||||
const toAdd = ev.detail.value;
|
||||
if (!toAdd) {
|
||||
return;
|
||||
}
|
||||
(ev.currentTarget as any).value = "";
|
||||
const currentAreas = this._currentAreas;
|
||||
if (currentAreas.includes(toAdd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateAreas([...currentAreas, toAdd]);
|
||||
}
|
||||
|
||||
static override styles = css`
|
||||
div {
|
||||
margin-top: 8px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-areas-picker": HaAreasPicker;
|
||||
}
|
||||
}
|
@@ -1,12 +1,13 @@
|
||||
import { LitElement, html, TemplateResult, css } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import "./ha-select";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import "./ha-textfield";
|
||||
import { css, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { stopPropagation } from "../common/dom/stop_propagation";
|
||||
import "./ha-select";
|
||||
import "./ha-textfield";
|
||||
|
||||
export interface TimeChangedEvent {
|
||||
days?: number;
|
||||
hours: number;
|
||||
minutes: number;
|
||||
seconds: number;
|
||||
@@ -21,6 +22,11 @@ export class HaBaseTimeInput extends LitElement {
|
||||
*/
|
||||
@property() label?: string;
|
||||
|
||||
/**
|
||||
* Helper for the input
|
||||
*/
|
||||
@property() helper?: string;
|
||||
|
||||
/**
|
||||
* auto validate time inputs
|
||||
*/
|
||||
@@ -41,6 +47,11 @@ export class HaBaseTimeInput extends LitElement {
|
||||
*/
|
||||
@property({ type: Boolean }) disabled = false;
|
||||
|
||||
/**
|
||||
* day
|
||||
*/
|
||||
@property({ type: Number }) days = 0;
|
||||
|
||||
/**
|
||||
* hour
|
||||
*/
|
||||
@@ -61,6 +72,11 @@ export class HaBaseTimeInput extends LitElement {
|
||||
*/
|
||||
@property({ type: Number }) milliseconds = 0;
|
||||
|
||||
/**
|
||||
* Label for the day input
|
||||
*/
|
||||
@property() dayLabel = "";
|
||||
|
||||
/**
|
||||
* Label for the hour input
|
||||
*/
|
||||
@@ -91,6 +107,11 @@ export class HaBaseTimeInput extends LitElement {
|
||||
*/
|
||||
@property({ type: Boolean }) enableMillisecond = false;
|
||||
|
||||
/**
|
||||
* show the day field
|
||||
*/
|
||||
@property({ type: Boolean }) enableDay = false;
|
||||
|
||||
/**
|
||||
* limit hours input
|
||||
*/
|
||||
@@ -110,6 +131,29 @@ export class HaBaseTimeInput extends LitElement {
|
||||
return html`
|
||||
${this.label ? html`<label>${this.label}</label>` : ""}
|
||||
<div class="time-input-wrap">
|
||||
${this.enableDay
|
||||
? html`
|
||||
<ha-textfield
|
||||
id="day"
|
||||
type="number"
|
||||
inputmode="numeric"
|
||||
.value=${this.days}
|
||||
.label=${this.dayLabel}
|
||||
name="days"
|
||||
@input=${this._valueChanged}
|
||||
@focus=${this._onFocus}
|
||||
no-spinner
|
||||
.required=${this.required}
|
||||
.autoValidate=${this.autoValidate}
|
||||
min="0"
|
||||
.disabled=${this.disabled}
|
||||
suffix=":"
|
||||
class="hasSuffix"
|
||||
>
|
||||
</ha-textfield>
|
||||
`
|
||||
: ""}
|
||||
|
||||
<ha-textfield
|
||||
id="hour"
|
||||
type="number"
|
||||
@@ -207,6 +251,7 @@ export class HaBaseTimeInput extends LitElement {
|
||||
<mwc-list-item value="PM">PM</mwc-list-item>
|
||||
</ha-select>`}
|
||||
</div>
|
||||
${this.helper ? html`<div class="helper">${this.helper}</div>` : ""}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -303,6 +348,13 @@ export class HaBaseTimeInput extends LitElement {
|
||||
color: var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87));
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.helper {
|
||||
color: var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6));
|
||||
font-size: 0.75rem;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -5,6 +5,7 @@ import "./ha-base-time-input";
|
||||
import type { TimeChangedEvent } from "./ha-base-time-input";
|
||||
|
||||
export interface HaDurationData {
|
||||
days?: number;
|
||||
hours?: number;
|
||||
minutes?: number;
|
||||
seconds?: number;
|
||||
@@ -17,10 +18,14 @@ class HaDurationInput extends LitElement {
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@property() public helper?: string;
|
||||
|
||||
@property({ type: Boolean }) public required?: boolean;
|
||||
|
||||
@property({ type: Boolean }) public enableMillisecond?: boolean;
|
||||
|
||||
@property({ type: Boolean }) public enableDay?: boolean;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@query("paper-time-input", true) private _input?: HTMLElement;
|
||||
@@ -35,19 +40,23 @@ class HaDurationInput extends LitElement {
|
||||
return html`
|
||||
<ha-base-time-input
|
||||
.label=${this.label}
|
||||
.helper=${this.helper}
|
||||
.required=${this.required}
|
||||
.autoValidate=${this.required}
|
||||
.disabled=${this.disabled}
|
||||
errorMessage="Required"
|
||||
enableSecond
|
||||
.enableMillisecond=${this.enableMillisecond}
|
||||
.enableDay=${this.enableDay}
|
||||
format="24"
|
||||
.days=${this._days}
|
||||
.hours=${this._hours}
|
||||
.minutes=${this._minutes}
|
||||
.seconds=${this._seconds}
|
||||
.milliseconds=${this._milliseconds}
|
||||
@value-changed=${this._durationChanged}
|
||||
noHoursLimit
|
||||
dayLabel="dd"
|
||||
hourLabel="hh"
|
||||
minLabel="mm"
|
||||
secLabel="ss"
|
||||
@@ -56,6 +65,10 @@ class HaDurationInput extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private get _days() {
|
||||
return this.data?.days ? Number(this.data.days) : 0;
|
||||
}
|
||||
|
||||
private get _hours() {
|
||||
return this.data?.hours ? Number(this.data.hours) : 0;
|
||||
}
|
||||
@@ -94,6 +107,11 @@ class HaDurationInput extends LitElement {
|
||||
value.minutes %= 60;
|
||||
}
|
||||
|
||||
if (this.enableDay && value.hours > 24) {
|
||||
value.days = (value.days ?? 0) + Math.floor(value.hours / 24);
|
||||
value.hours %= 24;
|
||||
}
|
||||
|
||||
fireEvent(this, "value-changed", {
|
||||
value,
|
||||
});
|
||||
|
@@ -34,12 +34,25 @@ export const computeInitialHaFormData = (
|
||||
};
|
||||
} else if ("selector" in field) {
|
||||
const selector: Selector = field.selector;
|
||||
if ("boolean" in selector) {
|
||||
|
||||
if ("device" in selector) {
|
||||
data[field.name] = selector.device.multiple ? [] : "";
|
||||
} else if ("entity" in selector) {
|
||||
data[field.name] = selector.entity.multiple ? [] : "";
|
||||
} else if ("area" in selector) {
|
||||
data[field.name] = selector.area.multiple ? [] : "";
|
||||
} else if ("boolean" in selector) {
|
||||
data[field.name] = false;
|
||||
} else if ("text" in selector) {
|
||||
} else if (
|
||||
"text" in selector ||
|
||||
"addon" in selector ||
|
||||
"attribute" in selector ||
|
||||
"icon" in selector ||
|
||||
"theme" in selector
|
||||
) {
|
||||
data[field.name] = "";
|
||||
} else if ("number" in selector) {
|
||||
data[field.name] = "min" in selector.number ? selector.number.min : 0;
|
||||
data[field.name] = selector.number.min ?? 0;
|
||||
} else if ("select" in selector) {
|
||||
if (selector.select.options.length) {
|
||||
data[field.name] = selector.select.options[0][0];
|
||||
@@ -50,6 +63,23 @@ export const computeInitialHaFormData = (
|
||||
minutes: 0,
|
||||
seconds: 0,
|
||||
};
|
||||
} else if ("time" in selector) {
|
||||
data[field.name] = "00:00:00";
|
||||
} else if ("date" in selector || "datetime" in selector) {
|
||||
const now = new Date().toISOString().slice(0, 10);
|
||||
data[field.name] = `${now} 00:00:00`;
|
||||
} else if ("color_rgb" in selector) {
|
||||
data[field.name] = [0, 0, 0];
|
||||
} else if ("color_temp" in selector) {
|
||||
data[field.name] = selector.color_temp.min_mireds ?? 153;
|
||||
} else if (
|
||||
"action" in selector ||
|
||||
"media" in selector ||
|
||||
"target" in selector
|
||||
) {
|
||||
data[field.name] = {};
|
||||
} else {
|
||||
throw new Error("Selector not supported in initial form data");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -28,6 +28,8 @@ export class HaFormString extends LitElement implements HaFormElement {
|
||||
|
||||
@property() public label!: string;
|
||||
|
||||
@property() public helper?: string;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@state() private _unmaskedPassword = false;
|
||||
@@ -53,6 +55,8 @@ export class HaFormString extends LitElement implements HaFormElement {
|
||||
: "password"}
|
||||
.label=${this.label}
|
||||
.value=${this.data || ""}
|
||||
.helper=${this.helper}
|
||||
helperPersistent
|
||||
.disabled=${this.disabled}
|
||||
.required=${this.schema.required}
|
||||
.autoValidate=${this.schema.required}
|
||||
|
@@ -6,6 +6,7 @@ import { EntityRegistryEntry } from "../../data/entity_registry";
|
||||
import { AreaSelector } from "../../data/selector";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import "../ha-area-picker";
|
||||
import "../ha-areas-picker";
|
||||
|
||||
@customElement("ha-selector-area")
|
||||
export class HaAreaSelector extends LitElement {
|
||||
@@ -38,21 +39,43 @@ export class HaAreaSelector extends LitElement {
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`<ha-area-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
no-add
|
||||
.deviceFilter=${this._filterDevices}
|
||||
.entityFilter=${this._filterEntities}
|
||||
.includeDeviceClasses=${this.selector.area.entity?.device_class
|
||||
? [this.selector.area.entity.device_class]
|
||||
: undefined}
|
||||
.includeDomains=${this.selector.area.entity?.domain
|
||||
? [this.selector.area.entity.domain]
|
||||
: undefined}
|
||||
.disabled=${this.disabled}
|
||||
></ha-area-picker>`;
|
||||
if (!this.selector.area.multiple) {
|
||||
return html`
|
||||
<ha-area-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
no-add
|
||||
.deviceFilter=${this._filterDevices}
|
||||
.entityFilter=${this._filterEntities}
|
||||
.includeDeviceClasses=${this.selector.area.entity?.device_class
|
||||
? [this.selector.area.entity.device_class]
|
||||
: undefined}
|
||||
.includeDomains=${this.selector.area.entity?.domain
|
||||
? [this.selector.area.entity.domain]
|
||||
: undefined}
|
||||
.disabled=${this.disabled}
|
||||
></ha-area-picker>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-areas-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.pickAreaLabel=${this.label}
|
||||
no-add
|
||||
.deviceFilter=${this._filterDevices}
|
||||
.entityFilter=${this._filterEntities}
|
||||
.includeDeviceClasses=${this.selector.area.entity?.device_class
|
||||
? [this.selector.area.entity.device_class]
|
||||
: undefined}
|
||||
.includeDomains=${this.selector.area.entity?.domain
|
||||
? [this.selector.area.entity.domain]
|
||||
: undefined}
|
||||
.disabled=${this.disabled}
|
||||
></ha-areas-picker>
|
||||
`;
|
||||
}
|
||||
|
||||
private _filterEntities = (entity: EntityRegistryEntry): boolean => {
|
||||
|
@@ -14,6 +14,8 @@ export class HaTimeDuration extends LitElement {
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@property() public helper?: string;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@property({ type: Boolean }) public required = true;
|
||||
@@ -22,9 +24,11 @@ export class HaTimeDuration extends LitElement {
|
||||
return html`
|
||||
<ha-duration-input
|
||||
.label=${this.label}
|
||||
.helper=${this.helper}
|
||||
.data=${this.value}
|
||||
.disabled=${this.disabled}
|
||||
.required=${this.required}
|
||||
.enableDay=${this.selector.duration.enable_day}
|
||||
></ha-duration-input>
|
||||
`;
|
||||
}
|
||||
|
@@ -33,7 +33,6 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
||||
.excludeEntities=${this.selector.entity.exclude_entities}
|
||||
.entityFilter=${this._filterEntities}
|
||||
.disabled=${this.disabled}
|
||||
.itemValuePath=${!this.selector.entity.use_uuid ? "entity_id" : "id"}
|
||||
allow-custom-entity
|
||||
></ha-entity-picker>`;
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@ import type {
|
||||
LocationSelector,
|
||||
LocationSelectorValue,
|
||||
} from "../../data/selector";
|
||||
import "../../panels/lovelace/components/hui-theme-select-editor";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import type { MarkerLocation } from "../map/ha-locations-editor";
|
||||
import "../map/ha-locations-editor";
|
||||
@@ -52,7 +51,10 @@ export class HaLocationSelector extends LitElement {
|
||||
longitude: value?.longitude || this.hass.config.longitude,
|
||||
radius: selector.location.radius ? value?.radius || 1000 : undefined,
|
||||
radius_color: zoneRadiusColor,
|
||||
icon: selector.location.icon,
|
||||
icon:
|
||||
selector.location.icon || selector.location.radius
|
||||
? "mdi:map-marker-radius"
|
||||
: "mdi:map-marker",
|
||||
location_editable: true,
|
||||
radius_editable: true,
|
||||
},
|
||||
|
@@ -19,6 +19,8 @@ export class HaNumberSelector extends LitElement {
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@property() public helper?: string;
|
||||
|
||||
@property({ type: Boolean }) public required = true;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
@@ -48,6 +50,8 @@ export class HaNumberSelector extends LitElement {
|
||||
.max=${this.selector.number.max}
|
||||
.value=${this.value ?? ""}
|
||||
.step=${this.selector.number.step ?? 1}
|
||||
helperPersistent
|
||||
.helper=${this.helper}
|
||||
.disabled=${this.disabled}
|
||||
.required=${this.required}
|
||||
.suffix=${this.selector.number.unit_of_measurement}
|
||||
|
@@ -18,6 +18,8 @@ export class HaTextSelector extends LitElement {
|
||||
|
||||
@property() public placeholder?: string;
|
||||
|
||||
@property() public helper?: string;
|
||||
|
||||
@property() public selector!: StringSelector;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
@@ -32,6 +34,8 @@ export class HaTextSelector extends LitElement {
|
||||
.label=${this.label}
|
||||
.placeholder=${this.placeholder}
|
||||
.value=${this.value || ""}
|
||||
.helper=${this.helper}
|
||||
helperPersistent
|
||||
.disabled=${this.disabled}
|
||||
@input=${this._handleChange}
|
||||
autocapitalize="none"
|
||||
@@ -44,6 +48,8 @@ export class HaTextSelector extends LitElement {
|
||||
return html`<ha-textfield
|
||||
.value=${this.value || ""}
|
||||
.placeholder=${this.placeholder || ""}
|
||||
.helper=${this.helper}
|
||||
helperPersistent
|
||||
.disabled=${this.disabled}
|
||||
.type=${this._unmaskedPassword ? "text" : this.selector.text?.type}
|
||||
@input=${this._handleChange}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import "../../panels/lovelace/components/hui-theme-select-editor";
|
||||
import "../ha-theme-picker";
|
||||
import { html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
@@ -18,11 +18,11 @@ export class HaThemeSelector extends LitElement {
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<hui-theme-select-editor
|
||||
<ha-theme-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
></hui-theme-select-editor>
|
||||
></ha-theme-picker>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@@ -471,6 +471,7 @@ export class HaServiceControl extends LitElement {
|
||||
}
|
||||
ha-settings-row {
|
||||
--paper-time-input-justify-content: flex-end;
|
||||
--settings-row-content-width: 100%;
|
||||
border-top: var(
|
||||
--service-control-items-border-top,
|
||||
1px solid var(--divider-color)
|
||||
@@ -489,9 +490,6 @@ export class HaServiceControl extends LitElement {
|
||||
margin: var(--service-control-padding, 0 16px);
|
||||
padding: 16px 0;
|
||||
}
|
||||
:host(:not([narrow])) ha-settings-row ha-selector {
|
||||
width: 60%;
|
||||
}
|
||||
.checkbox-spacer {
|
||||
width: 32px;
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ export class HaSettingsRow extends LitElement {
|
||||
<div secondary><slot name="description"></slot></div>
|
||||
</paper-item-body>
|
||||
</div>
|
||||
<slot></slot>
|
||||
<div class="content"><slot></slot></div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,18 @@ export class HaSettingsRow extends LitElement {
|
||||
);
|
||||
flex: 1;
|
||||
}
|
||||
.content {
|
||||
display: contents;
|
||||
}
|
||||
:host(:not([narrow])) .content {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex: 1;
|
||||
padding: 16px 0;
|
||||
}
|
||||
.content ::slotted(*) {
|
||||
width: var(--settings-row-content-width);
|
||||
}
|
||||
:host([narrow]) {
|
||||
align-items: normal;
|
||||
flex-direction: column;
|
||||
|
@@ -37,6 +37,7 @@ import { LocalStorage } from "../common/decorators/local-storage";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { toggleAttribute } from "../common/dom/toggle_attribute";
|
||||
import { computeDomain } from "../common/entity/compute_domain";
|
||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||
import { stringCompare } from "../common/string/compare";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
import { ActionHandlerDetail } from "../data/lovelace";
|
||||
@@ -44,6 +45,7 @@ import {
|
||||
PersistentNotification,
|
||||
subscribeNotifications,
|
||||
} from "../data/persistent_notification";
|
||||
import { updateCanInstall, UpdateEntity } from "../data/update";
|
||||
import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive";
|
||||
import { haStyleScrollbar } from "../resources/styles";
|
||||
import type { HomeAssistant, PanelInfo, Route } from "../types";
|
||||
@@ -68,7 +70,6 @@ const SORT_VALUE_URL_PATHS = {
|
||||
|
||||
const PANEL_ICONS = {
|
||||
calendar: mdiCalendar,
|
||||
config: mdiCog,
|
||||
"developer-tools": mdiHammer,
|
||||
energy: mdiLightningBolt,
|
||||
history: mdiChartBox,
|
||||
@@ -190,6 +191,8 @@ class HaSidebar extends LitElement {
|
||||
|
||||
@state() private _notifications?: PersistentNotification[];
|
||||
|
||||
@state() private _updatesCount = 0;
|
||||
|
||||
@state() private _renderEmptySortable = false;
|
||||
|
||||
private _mouseLeaveTimeout?: number;
|
||||
@@ -235,6 +238,7 @@ class HaSidebar extends LitElement {
|
||||
changedProps.has("narrow") ||
|
||||
changedProps.has("alwaysExpand") ||
|
||||
changedProps.has("_externalConfig") ||
|
||||
changedProps.has("_updatesCount") ||
|
||||
changedProps.has("_notifications") ||
|
||||
changedProps.has("editMode") ||
|
||||
changedProps.has("_renderEmptySortable") ||
|
||||
@@ -290,6 +294,12 @@ class HaSidebar extends LitElement {
|
||||
toggleAttribute(this, "rtl", computeRTL(this.hass));
|
||||
}
|
||||
|
||||
this._updatesCount = Object.values(this.hass.states).filter(
|
||||
(entity) =>
|
||||
computeStateDomain(entity) === "update" &&
|
||||
updateCanInstall(entity as UpdateEntity)
|
||||
).length;
|
||||
|
||||
if (!SUPPORT_SCROLL_IF_NEEDED) {
|
||||
return;
|
||||
}
|
||||
@@ -387,35 +397,37 @@ class HaSidebar extends LitElement {
|
||||
icon?: string | null,
|
||||
iconPath?: string | null
|
||||
) {
|
||||
return html`
|
||||
<a
|
||||
role="option"
|
||||
href=${`/${urlPath}`}
|
||||
data-panel=${urlPath}
|
||||
tabindex="-1"
|
||||
@mouseenter=${this._itemMouseEnter}
|
||||
@mouseleave=${this._itemMouseLeave}
|
||||
>
|
||||
<paper-icon-item>
|
||||
${iconPath
|
||||
? html`<ha-svg-icon
|
||||
slot="item-icon"
|
||||
.path=${iconPath}
|
||||
></ha-svg-icon>`
|
||||
: html`<ha-icon slot="item-icon" .icon=${icon}></ha-icon>`}
|
||||
<span class="item-text">${title}</span>
|
||||
</paper-icon-item>
|
||||
${this.editMode
|
||||
? html`<ha-icon-button
|
||||
.label=${this.hass.localize("ui.sidebar.hide_panel")}
|
||||
.path=${mdiClose}
|
||||
class="hide-panel"
|
||||
.panel=${urlPath}
|
||||
@click=${this._hidePanel}
|
||||
></ha-icon-button>`
|
||||
: ""}
|
||||
</a>
|
||||
`;
|
||||
return urlPath === "config"
|
||||
? this._renderConfiguration(title)
|
||||
: html`
|
||||
<a
|
||||
role="option"
|
||||
href=${`/${urlPath}`}
|
||||
data-panel=${urlPath}
|
||||
tabindex="-1"
|
||||
@mouseenter=${this._itemMouseEnter}
|
||||
@mouseleave=${this._itemMouseLeave}
|
||||
>
|
||||
<paper-icon-item>
|
||||
${iconPath
|
||||
? html`<ha-svg-icon
|
||||
slot="item-icon"
|
||||
.path=${iconPath}
|
||||
></ha-svg-icon>`
|
||||
: html`<ha-icon slot="item-icon" .icon=${icon}></ha-icon>`}
|
||||
<span class="item-text">${title}</span>
|
||||
</paper-icon-item>
|
||||
${this.editMode
|
||||
? html`<ha-icon-button
|
||||
.label=${this.hass.localize("ui.sidebar.hide_panel")}
|
||||
.path=${mdiClose}
|
||||
class="hide-panel"
|
||||
.panel=${urlPath}
|
||||
@click=${this._hidePanel}
|
||||
></ha-icon-button>`
|
||||
: ""}
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
private _renderPanelsEdit(beforeSpacer: PanelInfo[]) {
|
||||
@@ -477,6 +489,35 @@ class HaSidebar extends LitElement {
|
||||
return html`<div class="spacer" disabled></div>`;
|
||||
}
|
||||
|
||||
private _renderConfiguration(title: string | null) {
|
||||
return html` <a
|
||||
class="configuration-container"
|
||||
role="option"
|
||||
href="/config"
|
||||
data-panel="config"
|
||||
tabindex="-1"
|
||||
@mouseenter=${this._itemMouseEnter}
|
||||
@mouseleave=${this._itemMouseLeave}
|
||||
>
|
||||
<paper-icon-item class="configuration" role="option">
|
||||
<ha-svg-icon slot="item-icon" .path=${mdiCog}></ha-svg-icon>
|
||||
${!this.alwaysExpand && this._updatesCount > 0
|
||||
? html`
|
||||
<span class="configuration-badge" slot="item-icon">
|
||||
${this._updatesCount}
|
||||
</span>
|
||||
`
|
||||
: ""}
|
||||
<span class="item-text">${title}</span>
|
||||
${this.alwaysExpand && this._updatesCount > 0
|
||||
? html`
|
||||
<span class="configuration-badge">${this._updatesCount}</span>
|
||||
`
|
||||
: ""}
|
||||
</paper-icon-item>
|
||||
</a>`;
|
||||
}
|
||||
|
||||
private _renderNotifications() {
|
||||
let notificationCount = this._notifications
|
||||
? this._notifications.length
|
||||
@@ -953,18 +994,21 @@ class HaSidebar extends LitElement {
|
||||
height: 1px;
|
||||
background-color: var(--divider-color);
|
||||
}
|
||||
.notifications-container {
|
||||
.notifications-container,
|
||||
.configuration-container {
|
||||
display: flex;
|
||||
margin-left: env(safe-area-inset-left);
|
||||
}
|
||||
:host([rtl]) .notifications-container {
|
||||
:host([rtl]) .notifications-container,
|
||||
:host([rtl]) .configuration-container {
|
||||
margin-left: initial;
|
||||
margin-right: env(safe-area-inset-right);
|
||||
}
|
||||
.notifications {
|
||||
cursor: pointer;
|
||||
}
|
||||
.notifications .item-text {
|
||||
.notifications .item-text,
|
||||
.configuration .item-text {
|
||||
flex: 1;
|
||||
}
|
||||
.profile {
|
||||
@@ -988,7 +1032,8 @@ class HaSidebar extends LitElement {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.notification-badge {
|
||||
.notification-badge,
|
||||
.configuration-badge {
|
||||
min-width: 20px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
@@ -999,7 +1044,11 @@ class HaSidebar extends LitElement {
|
||||
padding: 0px 6px;
|
||||
color: var(--text-accent-color, var(--text-primary-color));
|
||||
}
|
||||
ha-svg-icon + .notification-badge {
|
||||
.configuration-badge {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
ha-svg-icon + .notification-badge,
|
||||
ha-svg-icon + .configuration-badge {
|
||||
position: absolute;
|
||||
bottom: 14px;
|
||||
left: 26px;
|
||||
|
@@ -2,13 +2,13 @@ import "@material/mwc-button";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
import "../../../components/ha-select";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { stopPropagation } from "../common/dom/stop_propagation";
|
||||
import "./ha-select";
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
@customElement("hui-theme-select-editor")
|
||||
export class HuiThemeSelectEditor extends LitElement {
|
||||
@customElement("ha-theme-picker")
|
||||
export class HaThemePicker extends LitElement {
|
||||
@property() public value?: string;
|
||||
|
||||
@property() public label?: string;
|
||||
@@ -19,11 +19,7 @@ export class HuiThemeSelectEditor extends LitElement {
|
||||
return html`
|
||||
<ha-select
|
||||
.label=${this.label ||
|
||||
`${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`}
|
||||
this.hass!.localize("ui.components.theme_picker.theme")}
|
||||
.value=${this.value}
|
||||
@selected=${this._changed}
|
||||
@closed=${stopPropagation}
|
||||
@@ -32,7 +28,7 @@ export class HuiThemeSelectEditor extends LitElement {
|
||||
>
|
||||
<mwc-list-item value="remove"
|
||||
>${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.no_theme"
|
||||
"ui.components.theme_picker.no_theme"
|
||||
)}</mwc-list-item
|
||||
>
|
||||
${Object.keys(this.hass!.themes.themes)
|
||||
@@ -64,6 +60,6 @@ export class HuiThemeSelectEditor extends LitElement {
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-theme-select-editor": HuiThemeSelectEditor;
|
||||
"ha-theme-picker": HaThemePicker;
|
||||
}
|
||||
}
|
@@ -488,6 +488,14 @@ export class HaMap extends ReactiveElement {
|
||||
text-align: center;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.leaflet-pane {
|
||||
z-index: 0 !important;
|
||||
}
|
||||
.leaflet-control,
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
z-index: 1 !important;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@@ -62,6 +62,7 @@ export interface ContextConstraint {
|
||||
export interface BaseTrigger {
|
||||
platform: string;
|
||||
id?: string;
|
||||
variables?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface StateTrigger extends BaseTrigger {
|
||||
|
@@ -46,6 +46,7 @@ export interface AreaSelector {
|
||||
manufacturer?: DeviceSelector["device"]["manufacturer"];
|
||||
model?: DeviceSelector["device"]["model"];
|
||||
};
|
||||
multiple?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,8 +97,9 @@ export interface DeviceSelector {
|
||||
}
|
||||
|
||||
export interface DurationSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
duration: {};
|
||||
duration: {
|
||||
enable_day?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EntitySelector {
|
||||
@@ -106,7 +108,6 @@ export interface EntitySelector {
|
||||
domain?: string | string[];
|
||||
device_class?: string;
|
||||
multiple?: boolean;
|
||||
use_uuid?: boolean;
|
||||
include_entities?: string[];
|
||||
exclude_entities?: string[];
|
||||
};
|
||||
|
@@ -14,9 +14,7 @@ import { fireEvent, HASSDomEvent } from "../../common/dom/fire_event";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import "../../components/ha-circular-progress";
|
||||
import "../../components/ha-dialog";
|
||||
import "../../components/ha-form/ha-form";
|
||||
import "../../components/ha-icon-button";
|
||||
import "../../components/ha-markdown";
|
||||
import {
|
||||
AreaRegistryEntry,
|
||||
subscribeAreaRegistry,
|
||||
|
@@ -91,6 +91,12 @@ export const showConfigFlowDialog = (
|
||||
);
|
||||
},
|
||||
|
||||
renderShowFormStepFieldHelper(hass, step, field) {
|
||||
return hass.localize(
|
||||
`component.${step.handler}.config.step.${step.step_id}.data_description.${field.name}`
|
||||
);
|
||||
},
|
||||
|
||||
renderShowFormStepFieldError(hass, step, error) {
|
||||
return hass.localize(
|
||||
`component.${step.handler}.config.error.${error}`,
|
||||
|
@@ -50,6 +50,12 @@ export interface FlowConfig {
|
||||
field: HaFormSchema
|
||||
): string;
|
||||
|
||||
renderShowFormStepFieldHelper(
|
||||
hass: HomeAssistant,
|
||||
step: DataEntryFlowStepForm,
|
||||
field: HaFormSchema
|
||||
): string;
|
||||
|
||||
renderShowFormStepFieldError(
|
||||
hass: HomeAssistant,
|
||||
step: DataEntryFlowStepForm,
|
||||
|
@@ -89,6 +89,12 @@ export const showOptionsFlowDialog = (
|
||||
);
|
||||
},
|
||||
|
||||
renderShowFormStepFieldHelper(hass, step, field) {
|
||||
return hass.localize(
|
||||
`component.${configEntry.domain}.options.step.${step.step_id}.data_description.${field.name}`
|
||||
);
|
||||
},
|
||||
|
||||
renderShowFormStepFieldError(hass, step, error) {
|
||||
return hass.localize(
|
||||
`component.${configEntry.domain}.options.error.${error}`,
|
||||
|
@@ -54,6 +54,7 @@ class StepFlowForm extends LitElement {
|
||||
.schema=${step.data_schema}
|
||||
.error=${step.errors}
|
||||
.computeLabel=${this._labelCallback}
|
||||
.computeHelper=${this._helperCallback}
|
||||
.computeError=${this._errorCallback}
|
||||
></ha-form>
|
||||
</div>
|
||||
@@ -166,6 +167,9 @@ class StepFlowForm extends LitElement {
|
||||
private _labelCallback = (field: HaFormSchema): string =>
|
||||
this.flowConfig.renderShowFormStepFieldLabel(this.hass, this.step, field);
|
||||
|
||||
private _helperCallback = (field: HaFormSchema): string =>
|
||||
this.flowConfig.renderShowFormStepFieldHelper(this.hass, this.step, field);
|
||||
|
||||
private _errorCallback = (error: string) =>
|
||||
this.flowConfig.renderShowFormStepFieldError(this.hass, this.step, error);
|
||||
|
||||
|
@@ -326,12 +326,9 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
}
|
||||
ha-settings-row {
|
||||
--paper-time-input-justify-content: flex-end;
|
||||
--settings-row-content-width: 100%;
|
||||
border-top: 1px solid var(--divider-color);
|
||||
}
|
||||
:host(:not([narrow])) ha-settings-row ha-textfield,
|
||||
:host(:not([narrow])) ha-settings-row ha-selector {
|
||||
width: 60%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import "@material/mwc-formfield/mwc-formfield";
|
||||
import "../../../components/ha-radio";
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@material/mwc-formfield/mwc-formfield";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import {
|
||||
@@ -20,9 +19,15 @@ import "../../../components/ha-alert";
|
||||
import "../../../components/ha-area-picker";
|
||||
import "../../../components/ha-expansion-panel";
|
||||
import "../../../components/ha-icon-picker";
|
||||
import "../../../components/ha-radio";
|
||||
import "../../../components/ha-select";
|
||||
import "../../../components/ha-switch";
|
||||
import "../../../components/ha-textfield";
|
||||
import {
|
||||
ConfigEntry,
|
||||
deleteConfigEntry,
|
||||
getConfigEntries,
|
||||
} from "../../../data/config_entries";
|
||||
import {
|
||||
DeviceRegistryEntry,
|
||||
subscribeDeviceRegistry,
|
||||
@@ -34,6 +39,7 @@ import {
|
||||
removeEntityRegistryEntry,
|
||||
updateEntityRegistryEntry,
|
||||
} from "../../../data/entity_registry";
|
||||
import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
|
||||
import {
|
||||
showAlertDialog,
|
||||
showConfirmationDialog,
|
||||
@@ -42,27 +48,39 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { showDeviceRegistryDetailDialog } from "../devices/device-registry-detail/show-dialog-device-registry-detail";
|
||||
import {
|
||||
ConfigEntry,
|
||||
deleteConfigEntry,
|
||||
getConfigEntries,
|
||||
} from "../../../data/config_entries";
|
||||
import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
|
||||
|
||||
const OVERRIDE_DEVICE_CLASSES = {
|
||||
cover: [
|
||||
"awning",
|
||||
"blind",
|
||||
"curtain",
|
||||
"damper",
|
||||
"door",
|
||||
"garage",
|
||||
"gate",
|
||||
"shade",
|
||||
"shutter",
|
||||
"window",
|
||||
[
|
||||
"awning",
|
||||
"blind",
|
||||
"curtain",
|
||||
"damper",
|
||||
"door",
|
||||
"garage",
|
||||
"gate",
|
||||
"shade",
|
||||
"shutter",
|
||||
"window",
|
||||
],
|
||||
],
|
||||
binary_sensor: [
|
||||
["lock"], // Lock
|
||||
["window", "door", "garage_door", "opening"], // Door
|
||||
["battery", "battery_charging"], // Battery
|
||||
["cold", "gas", "heat"], // Climate
|
||||
["running", "motion", "moving", "occupancy", "presence", "vibration"], // Presence
|
||||
["power", "plug", "light"], // Power
|
||||
[
|
||||
"smoke",
|
||||
"safety",
|
||||
"sound",
|
||||
"problem",
|
||||
"tamper",
|
||||
"carbon_monoxide",
|
||||
"moisture",
|
||||
], // Alarm
|
||||
],
|
||||
binary_sensor: ["window", "door", "garage_door", "opening"],
|
||||
};
|
||||
|
||||
@customElement("entity-registry-settings")
|
||||
@@ -85,8 +103,6 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _hiddenBy!: string | null;
|
||||
|
||||
private _deviceLookup?: Record<string, DeviceRegistryEntry>;
|
||||
|
||||
@state() private _device?: DeviceRegistryEntry;
|
||||
|
||||
@state() private _helperConfigEntry?: ConfigEntry;
|
||||
@@ -97,6 +113,10 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _origEntityId!: string;
|
||||
|
||||
private _deviceLookup?: Record<string, DeviceRegistryEntry>;
|
||||
|
||||
private _deviceClassOptions?: string[][];
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
|
||||
@@ -125,23 +145,41 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
super.updated(changedProperties);
|
||||
if (changedProperties.has("entry")) {
|
||||
this._error = undefined;
|
||||
this._name = this.entry.name || "";
|
||||
this._icon = this.entry.icon || "";
|
||||
this._deviceClass =
|
||||
this.entry.device_class || this.entry.original_device_class;
|
||||
this._origEntityId = this.entry.entity_id;
|
||||
this._areaId = this.entry.area_id;
|
||||
this._entityId = this.entry.entity_id;
|
||||
this._disabledBy = this.entry.disabled_by;
|
||||
this._hiddenBy = this.entry.hidden_by;
|
||||
this._device =
|
||||
this.entry.device_id && this._deviceLookup
|
||||
? this._deviceLookup[this.entry.device_id]
|
||||
: undefined;
|
||||
protected willUpdate(changedProperties: PropertyValues) {
|
||||
super.willUpdate(changedProperties);
|
||||
if (!changedProperties.has("entry")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._error = undefined;
|
||||
this._name = this.entry.name || "";
|
||||
this._icon = this.entry.icon || "";
|
||||
this._deviceClass =
|
||||
this.entry.device_class || this.entry.original_device_class;
|
||||
this._origEntityId = this.entry.entity_id;
|
||||
this._areaId = this.entry.area_id;
|
||||
this._entityId = this.entry.entity_id;
|
||||
this._disabledBy = this.entry.disabled_by;
|
||||
this._hiddenBy = this.entry.hidden_by;
|
||||
this._device =
|
||||
this.entry.device_id && this._deviceLookup
|
||||
? this._deviceLookup[this.entry.device_id]
|
||||
: undefined;
|
||||
|
||||
const domain = computeDomain(this.entry.entity_id);
|
||||
const deviceClasses: string[][] = OVERRIDE_DEVICE_CLASSES[domain];
|
||||
|
||||
if (!deviceClasses) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._deviceClassOptions = [[], []];
|
||||
for (const deviceClass of deviceClasses) {
|
||||
if (deviceClass.includes(this.entry.original_device_class!)) {
|
||||
this._deviceClassOptions[0] = deviceClass;
|
||||
} else {
|
||||
this._deviceClassOptions[1].push(...deviceClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,28 +235,39 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
: undefined}
|
||||
.disabled=${this._submitting}
|
||||
></ha-icon-picker>
|
||||
${OVERRIDE_DEVICE_CLASSES[domain]?.includes(this._deviceClass) ||
|
||||
(domain === "cover" && this.entry.original_device_class === null)
|
||||
? html`<ha-select
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.entity_registry.editor.device_class"
|
||||
)}
|
||||
.value=${this._deviceClass}
|
||||
naturalMenuWidth
|
||||
fixedMenuPosition
|
||||
@selected=${this._deviceClassChanged}
|
||||
@closed=${stopPropagation}
|
||||
>
|
||||
${OVERRIDE_DEVICE_CLASSES[domain].map(
|
||||
(deviceClass: string) => html`
|
||||
<mwc-list-item .value=${deviceClass}>
|
||||
${this.hass.localize(
|
||||
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${deviceClass}`
|
||||
)}
|
||||
</mwc-list-item>
|
||||
`
|
||||
)}
|
||||
</ha-select>`
|
||||
${this._deviceClassOptions
|
||||
? html`
|
||||
<ha-select
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.entity_registry.editor.device_class"
|
||||
)}
|
||||
.value=${this._deviceClass}
|
||||
naturalMenuWidth
|
||||
fixedMenuPosition
|
||||
@selected=${this._deviceClassChanged}
|
||||
@closed=${stopPropagation}
|
||||
>
|
||||
${this._deviceClassOptions[0].map(
|
||||
(deviceClass: string) => html`
|
||||
<mwc-list-item .value=${deviceClass} test=${deviceClass}>
|
||||
${this.hass.localize(
|
||||
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${deviceClass}`
|
||||
)}
|
||||
</mwc-list-item>
|
||||
`
|
||||
)}
|
||||
<li divider role="separator"></li>
|
||||
${this._deviceClassOptions[1].map(
|
||||
(deviceClass: string) => html`
|
||||
<mwc-list-item .value=${deviceClass} test=${deviceClass}>
|
||||
${this.hass.localize(
|
||||
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${deviceClass}`
|
||||
)}
|
||||
</mwc-list-item>
|
||||
`
|
||||
)}
|
||||
</ha-select>
|
||||
`
|
||||
: ""}
|
||||
<ha-textfield
|
||||
error-message="Domain needs to stay the same"
|
||||
@@ -264,7 +313,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
)}:
|
||||
</div>
|
||||
<div class="secondary">
|
||||
${this._disabledBy && this._disabledBy !== "user"
|
||||
${this._disabledBy &&
|
||||
this._disabledBy !== "user" &&
|
||||
this._disabledBy !== "integration"
|
||||
? this.hass.localize(
|
||||
"ui.dialogs.entity_registry.editor.enabled_cause",
|
||||
"cause",
|
||||
@@ -286,7 +337,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
.checked=${!this._hiddenBy && !this._disabledBy}
|
||||
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
||||
this._device?.disabled_by ||
|
||||
(this._disabledBy && this._disabledBy !== "user")}
|
||||
(this._disabledBy &&
|
||||
this._disabledBy !== "user" &&
|
||||
this._disabledBy !== "integration")}
|
||||
@change=${this._viewStatusChanged}
|
||||
></ha-radio>
|
||||
</mwc-formfield>
|
||||
@@ -301,7 +354,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
.checked=${this._hiddenBy !== null}
|
||||
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
||||
Boolean(this._device?.disabled_by) ||
|
||||
(this._disabledBy && this._disabledBy !== "user")}
|
||||
(this._disabledBy &&
|
||||
this._disabledBy !== "user" &&
|
||||
this._disabledBy !== "integration")}
|
||||
@change=${this._viewStatusChanged}
|
||||
></ha-radio>
|
||||
</mwc-formfield>
|
||||
@@ -316,7 +371,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
.checked=${this._disabledBy !== null}
|
||||
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
||||
Boolean(this._device?.disabled_by) ||
|
||||
(this._disabledBy && this._disabledBy !== "user")}
|
||||
(this._disabledBy &&
|
||||
this._disabledBy !== "user" &&
|
||||
this._disabledBy !== "integration")}
|
||||
@change=${this._viewStatusChanged}
|
||||
></ha-radio>
|
||||
</mwc-formfield>
|
||||
@@ -378,7 +435,7 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
class="warning"
|
||||
@click=${this._confirmDeleteEntry}
|
||||
.disabled=${this._submitting ||
|
||||
(!this._helperConfigEntry && !stateObj.attributes.restored)}
|
||||
(!this._helperConfigEntry && !stateObj?.attributes.restored)}
|
||||
>
|
||||
${this.hass.localize("ui.dialogs.entity_registry.editor.delete")}
|
||||
</mwc-button>
|
||||
@@ -577,6 +634,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
margin: 8px 0;
|
||||
width: 340px;
|
||||
}
|
||||
li[divider] {
|
||||
border-bottom-color: var(--divider-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@@ -116,7 +116,7 @@ export class HuiCardOptions extends LitElement {
|
||||
outline: 2px solid var(--primary-color);
|
||||
}
|
||||
|
||||
:host:not(.panel) ::slotted(*) {
|
||||
:host(:not(.panel)) ::slotted(*) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,6 @@ export const configElementStyle = css`
|
||||
.suffix {
|
||||
margin: 0 8px;
|
||||
}
|
||||
hui-theme-select-editor,
|
||||
hui-action-editor,
|
||||
ha-select,
|
||||
ha-textfield,
|
||||
|
@@ -99,6 +99,14 @@ export class HuiAlarmPanelCardEditor
|
||||
return this.hass!.localize(`ui.panel.lovelace.editor.card.generic.name`);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.alarm-panel.${
|
||||
schema.name === "states" ? "available_states" : schema.name
|
||||
|
@@ -69,6 +69,12 @@ export class HuiAreaCardEditor
|
||||
|
||||
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||
switch (schema.name) {
|
||||
case "theme":
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
case "area":
|
||||
return this.hass!.localize("ui.panel.lovelace.editor.card.area.name");
|
||||
case "navigation_path":
|
||||
|
@@ -200,6 +200,14 @@ export class HuiButtonCardEditor
|
||||
)}`;
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
);
|
||||
|
@@ -121,6 +121,14 @@ export class HuiCalendarCardEditor
|
||||
return this.hass!.localize("ui.panel.lovelace.editor.card.generic.title");
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.calendar.${schema.name}`
|
||||
);
|
||||
|
@@ -31,7 +31,7 @@ import "../../../../components/ha-icon";
|
||||
import "../../../../components/ha-switch";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { EntitiesCardConfig } from "../../cards/types";
|
||||
import "../../components/hui-theme-select-editor";
|
||||
import "../../../../components/ha-theme-picker";
|
||||
import { TIMESTAMP_RENDERING_FORMATS } from "../../components/types";
|
||||
import type { LovelaceRowConfig } from "../../entity-rows/types";
|
||||
import { headerFooterConfigStructs } from "../../header-footer/structs";
|
||||
@@ -265,12 +265,17 @@ export class HuiEntitiesCardEditor
|
||||
.configValue=${"title"}
|
||||
@input=${this._valueChanged}
|
||||
></ha-textfield>
|
||||
<hui-theme-select-editor
|
||||
<ha-theme-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this._theme}
|
||||
.label=${`${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`}
|
||||
.configValue=${"theme"}
|
||||
@value-changed=${this._valueChanged}
|
||||
></hui-theme-select-editor>
|
||||
></ha-theme-picker>
|
||||
<div class="side-by-side">
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize(
|
||||
|
@@ -112,6 +112,14 @@ export class HuiEntityCardEditor
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
);
|
||||
|
@@ -172,6 +172,12 @@ export class HuiGaugeCardEditor
|
||||
return this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.gauge.needle_gauge"
|
||||
);
|
||||
case "theme":
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
return (
|
||||
this.hass!.localize(
|
||||
|
@@ -117,11 +117,23 @@ export class HuiGlanceCardEditor
|
||||
fireEvent(this, "config-changed", { config });
|
||||
}
|
||||
|
||||
private _computeLabelCallback = (schema: HaFormSchema) =>
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.glance.${schema.name}`
|
||||
) ||
|
||||
this.hass!.localize(`ui.panel.lovelace.editor.card.generic.${schema.name}`);
|
||||
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
return (
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.glance.${schema.name}`
|
||||
) ||
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -75,6 +75,14 @@ export class HuiHumidifierCardEditor
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
);
|
||||
|
@@ -179,6 +179,14 @@ export class HuiLightCardEditor
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
);
|
||||
|
@@ -96,11 +96,24 @@ export class HuiLogbookCardEditor
|
||||
fireEvent(this, "config-changed", { config: ev.detail.value });
|
||||
}
|
||||
|
||||
private _computeLabelCallback = (schema: HaFormSchema) =>
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
) ||
|
||||
this.hass!.localize(`ui.panel.lovelace.editor.card.logbook.${schema.name}`);
|
||||
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return (
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
) ||
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.logbook.${schema.name}`
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -58,13 +58,23 @@ export class HuiMarkdownCardEditor
|
||||
fireEvent(this, "config-changed", { config: ev.detail.value });
|
||||
}
|
||||
|
||||
private _computeLabelCallback = (schema: HaFormSchema) =>
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
) ||
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.markdown.${schema.name}`
|
||||
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
return (
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
) ||
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.markdown.${schema.name}`
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -5,7 +5,7 @@ import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../components/entity/ha-entity-picker";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { MediaControlCardConfig } from "../../cards/types";
|
||||
import "../../components/hui-theme-select-editor";
|
||||
import "../../../../components/ha-theme-picker";
|
||||
import { LovelaceCardEditor } from "../../types";
|
||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||
@@ -62,12 +62,17 @@ export class HuiMediaControlCardEditor
|
||||
@change=${this._valueChanged}
|
||||
allow-custom-entity
|
||||
></ha-entity-picker>
|
||||
<hui-theme-select-editor
|
||||
<ha-theme-picker
|
||||
.label=${`${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`}
|
||||
.hass=${this.hass}
|
||||
.value=${this._theme}
|
||||
.configValue=${"theme"}
|
||||
@value-changed=${this._valueChanged}
|
||||
></hui-theme-select-editor>
|
||||
></ha-theme-picker>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import { ActionConfig } from "../../../../data/lovelace";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { PictureCardConfig } from "../../cards/types";
|
||||
import "../../components/hui-action-editor";
|
||||
import "../../components/hui-theme-select-editor";
|
||||
import "../../../../components/ha-theme-picker";
|
||||
import { LovelaceCardEditor } from "../../types";
|
||||
import { actionConfigStruct } from "../structs/action-struct";
|
||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||
@@ -72,12 +72,17 @@ export class HuiPictureCardEditor
|
||||
.configValue=${"image"}
|
||||
@input=${this._valueChanged}
|
||||
></ha-textfield>
|
||||
<hui-theme-select-editor
|
||||
<ha-theme-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this._theme}
|
||||
.label=${`${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`}
|
||||
.configValue=${"theme"}
|
||||
@value-changed=${this._valueChanged}
|
||||
></hui-theme-select-editor>
|
||||
></ha-theme-picker>
|
||||
<hui-action-editor
|
||||
.label="${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.tap_action"
|
||||
|
@@ -170,6 +170,14 @@ export class HuiPictureEntityCardEditor
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return (
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
|
@@ -165,6 +165,14 @@ export class HuiPictureGlanceCardEditor
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return (
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
|
@@ -64,7 +64,13 @@ export class HuiPlantStatusCardEditor
|
||||
"ui.panel.lovelace.editor.card.generic.entity"
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
);
|
||||
|
@@ -153,6 +153,14 @@ export class HuiSensorCardEditor
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
if (schema.name === "detail") {
|
||||
return this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.sensor.show_more_detail"
|
||||
|
@@ -6,7 +6,7 @@ import { isComponentLoaded } from "../../../../common/config/is_component_loaded
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import { ShoppingListCardConfig } from "../../cards/types";
|
||||
import "../../components/hui-theme-select-editor";
|
||||
import "../../../../components/ha-theme-picker";
|
||||
import { LovelaceCardEditor } from "../../types";
|
||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||
@@ -67,12 +67,17 @@ export class HuiShoppingListEditor
|
||||
.configValue=${"title"}
|
||||
@input=${this._valueChanged}
|
||||
></ha-textfield>
|
||||
<hui-theme-select-editor
|
||||
<ha-theme-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this._theme}
|
||||
.configValue=${"theme"}
|
||||
.label=${`${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`}
|
||||
@value-changed=${this._valueChanged}
|
||||
></hui-theme-select-editor>
|
||||
></ha-theme-picker>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
@@ -71,6 +71,14 @@ export class HuiThermostatCardEditor
|
||||
);
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
);
|
||||
|
@@ -184,6 +184,14 @@ export class HuiWeatherForecastCardEditor
|
||||
)})`;
|
||||
}
|
||||
|
||||
if (schema.name === "theme") {
|
||||
return `${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.theme"
|
||||
)} (${this.hass!.localize(
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})`;
|
||||
}
|
||||
|
||||
return (
|
||||
this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
|
@@ -401,6 +401,10 @@
|
||||
"add_device_id": "Choose device",
|
||||
"add_entity_id": "Choose entity"
|
||||
},
|
||||
"theme-picker": {
|
||||
"theme": "Theme",
|
||||
"no_theme": "No theme"
|
||||
},
|
||||
"user-picker": {
|
||||
"no_user": "No user",
|
||||
"add_user": "Add user",
|
||||
@@ -786,7 +790,31 @@
|
||||
"door": "Door",
|
||||
"garage_door": "Garage door",
|
||||
"window": "Window",
|
||||
"opening": "Other"
|
||||
"opening": "Opening",
|
||||
"battery": "Battery",
|
||||
"battery_charging": "Battery charging",
|
||||
"carbon_monoxide": "Carbon monoxide",
|
||||
"cold": "Cold",
|
||||
"connectivity": "Connectivity",
|
||||
"gas": "Gas",
|
||||
"heat": "Heat",
|
||||
"light": "Light",
|
||||
"lock": "Lock",
|
||||
"moisture": "Moisture",
|
||||
"motion": "Motion",
|
||||
"moving": "Moving",
|
||||
"occupancy": "Occupancy",
|
||||
"plug": "Plug",
|
||||
"power": "Power",
|
||||
"presence": "Presence",
|
||||
"problem": "Problem",
|
||||
"running": "Running",
|
||||
"safety": "Safety",
|
||||
"smoke": "Smoke",
|
||||
"sound": "Sound",
|
||||
"tamper": "Tamper",
|
||||
"update": "Update",
|
||||
"vibration": "Vibration"
|
||||
},
|
||||
"cover": {
|
||||
"door": "Door",
|
||||
@@ -3458,7 +3486,6 @@
|
||||
"tap_action": "Tap Action",
|
||||
"title": "Title",
|
||||
"theme": "Theme",
|
||||
"no_theme": "No theme",
|
||||
"unit": "Unit",
|
||||
"url": "URL",
|
||||
"state": "State",
|
||||
|
Reference in New Issue
Block a user