mirror of
https://github.com/home-assistant/frontend.git
synced 2025-09-10 13:39:43 +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 */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { LitElement, TemplateResult, html } from "lit";
|
import { html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
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 { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
||||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
||||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
||||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
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 { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
import { HomeAssistant } from "../../../../src/types";
|
import { HomeAssistant } from "../../../../src/types";
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
import "../../components/demo-black-white-row";
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
||||||
@@ -147,7 +147,9 @@ const SCHEMAS: {
|
|||||||
{ name: "target", selector: { target: {} } },
|
{ name: "target", selector: { target: {} } },
|
||||||
{ name: "number", selector: { number: { min: 0, max: 10 } } },
|
{ name: "number", selector: { number: { min: 0, max: 10 } } },
|
||||||
{ name: "boolean", selector: { boolean: {} } },
|
{ 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: "action", selector: { action: {} } },
|
||||||
{ name: "text", selector: { text: { multiline: false } } },
|
{ name: "text", selector: { text: { multiline: false } } },
|
||||||
{ name: "text_multiline", selector: { text: { multiline: true } } },
|
{ name: "text_multiline", selector: { text: { multiline: true } } },
|
||||||
|
@@ -1,20 +1,20 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import "@material/mwc-button";
|
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 { 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-selector/ha-selector";
|
||||||
import "../../../../src/components/ha-settings-row";
|
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 { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
|
import { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import "../../components/demo-black-white-row";
|
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 = [
|
const ENTITIES = [
|
||||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
||||||
@@ -202,6 +202,7 @@ const SCHEMAS: {
|
|||||||
input: {
|
input: {
|
||||||
entity: { name: "Entity", selector: { entity: { multiple: true } } },
|
entity: { name: "Entity", selector: { entity: { multiple: true } } },
|
||||||
device: { name: "Device", selector: { device: { multiple: true } } },
|
device: { name: "Device", selector: { device: { multiple: true } } },
|
||||||
|
area: { name: "Area", selector: { area: { multiple: true } } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = home-assistant-frontend
|
name = home-assistant-frontend
|
||||||
version = 20220322.0
|
version = 20220329.0
|
||||||
author = The Home Assistant Authors
|
author = The Home Assistant Authors
|
||||||
author_email = hello@home-assistant.io
|
author_email = hello@home-assistant.io
|
||||||
license = Apache-2.0
|
license = Apache-2.0
|
||||||
|
@@ -18,7 +18,6 @@ import "./state-badge";
|
|||||||
|
|
||||||
interface HassEntityWithCachedName extends HassEntity {
|
interface HassEntityWithCachedName extends HassEntity {
|
||||||
friendly_name: string;
|
friendly_name: string;
|
||||||
id: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
||||||
@@ -97,9 +96,6 @@ export class HaEntityPicker extends LitElement {
|
|||||||
|
|
||||||
@property() public entityFilter?: HaEntityPickerEntityFilterFunc;
|
@property() public entityFilter?: HaEntityPickerEntityFilterFunc;
|
||||||
|
|
||||||
@property({ attribute: "item-value-path" }) public itemValuePath =
|
|
||||||
"entity_id";
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public hideClearIcon = false;
|
@property({ type: Boolean }) public hideClearIcon = false;
|
||||||
|
|
||||||
@state() private _opened = false;
|
@state() private _opened = false;
|
||||||
@@ -148,7 +144,6 @@ export class HaEntityPicker extends LitElement {
|
|||||||
state: "",
|
state: "",
|
||||||
last_changed: "",
|
last_changed: "",
|
||||||
last_updated: "",
|
last_updated: "",
|
||||||
id: "",
|
|
||||||
context: { id: "", user_id: null, parent_id: null },
|
context: { id: "", user_id: null, parent_id: null },
|
||||||
friendly_name: this.hass!.localize(
|
friendly_name: this.hass!.localize(
|
||||||
"ui.components.entity.entity-picker.no_entities"
|
"ui.components.entity.entity-picker.no_entities"
|
||||||
@@ -169,15 +164,10 @@ export class HaEntityPicker extends LitElement {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return entityIds
|
return entityIds
|
||||||
.map((key) => {
|
.map((key) => ({
|
||||||
const stateObj = hass!.states[key];
|
...hass!.states[key],
|
||||||
|
friendly_name: computeStateName(hass!.states[key]) || key,
|
||||||
return {
|
}))
|
||||||
...stateObj,
|
|
||||||
friendly_name: computeStateName(stateObj) || key,
|
|
||||||
id: stateObj.context.id,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.sort((entityA, entityB) =>
|
.sort((entityA, entityB) =>
|
||||||
caseInsensitiveStringCompare(
|
caseInsensitiveStringCompare(
|
||||||
entityA.friendly_name,
|
entityA.friendly_name,
|
||||||
@@ -205,15 +195,10 @@ export class HaEntityPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
states = entityIds
|
states = entityIds
|
||||||
.map((key) => {
|
.map((key) => ({
|
||||||
const stateObj = hass!.states[key];
|
...hass!.states[key],
|
||||||
|
friendly_name: computeStateName(hass!.states[key]) || key,
|
||||||
return {
|
}))
|
||||||
...stateObj,
|
|
||||||
friendly_name: computeStateName(stateObj) || key,
|
|
||||||
id: stateObj.context?.id,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.sort((entityA, entityB) =>
|
.sort((entityA, entityB) =>
|
||||||
caseInsensitiveStringCompare(
|
caseInsensitiveStringCompare(
|
||||||
entityA.friendly_name,
|
entityA.friendly_name,
|
||||||
@@ -258,7 +243,6 @@ export class HaEntityPicker extends LitElement {
|
|||||||
state: "",
|
state: "",
|
||||||
last_changed: "",
|
last_changed: "",
|
||||||
last_updated: "",
|
last_updated: "",
|
||||||
id: "",
|
|
||||||
context: { id: "", user_id: null, parent_id: null },
|
context: { id: "", user_id: null, parent_id: null },
|
||||||
friendly_name: this.hass!.localize(
|
friendly_name: this.hass!.localize(
|
||||||
"ui.components.entity.entity-picker.no_match"
|
"ui.components.entity.entity-picker.no_match"
|
||||||
@@ -311,8 +295,8 @@ export class HaEntityPicker extends LitElement {
|
|||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<ha-combo-box
|
<ha-combo-box
|
||||||
|
item-value-path="entity_id"
|
||||||
item-label-path="friendly_name"
|
item-label-path="friendly_name"
|
||||||
.itemValuePath=${this.itemValuePath}
|
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._value}
|
.value=${this._value}
|
||||||
.label=${this.label === undefined
|
.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 "@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 { fireEvent } from "../common/dom/fire_event";
|
||||||
import { stopPropagation } from "../common/dom/stop_propagation";
|
import { stopPropagation } from "../common/dom/stop_propagation";
|
||||||
|
import "./ha-select";
|
||||||
|
import "./ha-textfield";
|
||||||
|
|
||||||
export interface TimeChangedEvent {
|
export interface TimeChangedEvent {
|
||||||
|
days?: number;
|
||||||
hours: number;
|
hours: number;
|
||||||
minutes: number;
|
minutes: number;
|
||||||
seconds: number;
|
seconds: number;
|
||||||
@@ -21,6 +22,11 @@ export class HaBaseTimeInput extends LitElement {
|
|||||||
*/
|
*/
|
||||||
@property() label?: string;
|
@property() label?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for the input
|
||||||
|
*/
|
||||||
|
@property() helper?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* auto validate time inputs
|
* auto validate time inputs
|
||||||
*/
|
*/
|
||||||
@@ -41,6 +47,11 @@ export class HaBaseTimeInput extends LitElement {
|
|||||||
*/
|
*/
|
||||||
@property({ type: Boolean }) disabled = false;
|
@property({ type: Boolean }) disabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* day
|
||||||
|
*/
|
||||||
|
@property({ type: Number }) days = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hour
|
* hour
|
||||||
*/
|
*/
|
||||||
@@ -61,6 +72,11 @@ export class HaBaseTimeInput extends LitElement {
|
|||||||
*/
|
*/
|
||||||
@property({ type: Number }) milliseconds = 0;
|
@property({ type: Number }) milliseconds = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label for the day input
|
||||||
|
*/
|
||||||
|
@property() dayLabel = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Label for the hour input
|
* Label for the hour input
|
||||||
*/
|
*/
|
||||||
@@ -91,6 +107,11 @@ export class HaBaseTimeInput extends LitElement {
|
|||||||
*/
|
*/
|
||||||
@property({ type: Boolean }) enableMillisecond = false;
|
@property({ type: Boolean }) enableMillisecond = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* show the day field
|
||||||
|
*/
|
||||||
|
@property({ type: Boolean }) enableDay = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* limit hours input
|
* limit hours input
|
||||||
*/
|
*/
|
||||||
@@ -110,6 +131,29 @@ export class HaBaseTimeInput extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
${this.label ? html`<label>${this.label}</label>` : ""}
|
${this.label ? html`<label>${this.label}</label>` : ""}
|
||||||
<div class="time-input-wrap">
|
<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
|
<ha-textfield
|
||||||
id="hour"
|
id="hour"
|
||||||
type="number"
|
type="number"
|
||||||
@@ -207,6 +251,7 @@ export class HaBaseTimeInput extends LitElement {
|
|||||||
<mwc-list-item value="PM">PM</mwc-list-item>
|
<mwc-list-item value="PM">PM</mwc-list-item>
|
||||||
</ha-select>`}
|
</ha-select>`}
|
||||||
</div>
|
</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));
|
color: var(--mdc-theme-text-primary-on-background, rgba(0, 0, 0, 0.87));
|
||||||
padding-left: 4px;
|
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";
|
import type { TimeChangedEvent } from "./ha-base-time-input";
|
||||||
|
|
||||||
export interface HaDurationData {
|
export interface HaDurationData {
|
||||||
|
days?: number;
|
||||||
hours?: number;
|
hours?: number;
|
||||||
minutes?: number;
|
minutes?: number;
|
||||||
seconds?: number;
|
seconds?: number;
|
||||||
@@ -17,10 +18,14 @@ class HaDurationInput extends LitElement {
|
|||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@property() public helper?: string;
|
||||||
|
|
||||||
@property({ type: Boolean }) public required?: boolean;
|
@property({ type: Boolean }) public required?: boolean;
|
||||||
|
|
||||||
@property({ type: Boolean }) public enableMillisecond?: boolean;
|
@property({ type: Boolean }) public enableMillisecond?: boolean;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public enableDay?: boolean;
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@query("paper-time-input", true) private _input?: HTMLElement;
|
@query("paper-time-input", true) private _input?: HTMLElement;
|
||||||
@@ -35,19 +40,23 @@ class HaDurationInput extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-base-time-input
|
<ha-base-time-input
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
|
.helper=${this.helper}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
.autoValidate=${this.required}
|
.autoValidate=${this.required}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
errorMessage="Required"
|
errorMessage="Required"
|
||||||
enableSecond
|
enableSecond
|
||||||
.enableMillisecond=${this.enableMillisecond}
|
.enableMillisecond=${this.enableMillisecond}
|
||||||
|
.enableDay=${this.enableDay}
|
||||||
format="24"
|
format="24"
|
||||||
|
.days=${this._days}
|
||||||
.hours=${this._hours}
|
.hours=${this._hours}
|
||||||
.minutes=${this._minutes}
|
.minutes=${this._minutes}
|
||||||
.seconds=${this._seconds}
|
.seconds=${this._seconds}
|
||||||
.milliseconds=${this._milliseconds}
|
.milliseconds=${this._milliseconds}
|
||||||
@value-changed=${this._durationChanged}
|
@value-changed=${this._durationChanged}
|
||||||
noHoursLimit
|
noHoursLimit
|
||||||
|
dayLabel="dd"
|
||||||
hourLabel="hh"
|
hourLabel="hh"
|
||||||
minLabel="mm"
|
minLabel="mm"
|
||||||
secLabel="ss"
|
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() {
|
private get _hours() {
|
||||||
return this.data?.hours ? Number(this.data.hours) : 0;
|
return this.data?.hours ? Number(this.data.hours) : 0;
|
||||||
}
|
}
|
||||||
@@ -94,6 +107,11 @@ class HaDurationInput extends LitElement {
|
|||||||
value.minutes %= 60;
|
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", {
|
fireEvent(this, "value-changed", {
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
|
@@ -34,12 +34,25 @@ export const computeInitialHaFormData = (
|
|||||||
};
|
};
|
||||||
} else if ("selector" in field) {
|
} else if ("selector" in field) {
|
||||||
const selector: Selector = field.selector;
|
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;
|
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] = "";
|
data[field.name] = "";
|
||||||
} else if ("number" in selector) {
|
} 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) {
|
} else if ("select" in selector) {
|
||||||
if (selector.select.options.length) {
|
if (selector.select.options.length) {
|
||||||
data[field.name] = selector.select.options[0][0];
|
data[field.name] = selector.select.options[0][0];
|
||||||
@@ -50,6 +63,23 @@ export const computeInitialHaFormData = (
|
|||||||
minutes: 0,
|
minutes: 0,
|
||||||
seconds: 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 label!: string;
|
||||||
|
|
||||||
|
@property() public helper?: string;
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@state() private _unmaskedPassword = false;
|
@state() private _unmaskedPassword = false;
|
||||||
@@ -53,6 +55,8 @@ export class HaFormString extends LitElement implements HaFormElement {
|
|||||||
: "password"}
|
: "password"}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
.value=${this.data || ""}
|
.value=${this.data || ""}
|
||||||
|
.helper=${this.helper}
|
||||||
|
helperPersistent
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.schema.required}
|
.required=${this.schema.required}
|
||||||
.autoValidate=${this.schema.required}
|
.autoValidate=${this.schema.required}
|
||||||
|
@@ -6,6 +6,7 @@ import { EntityRegistryEntry } from "../../data/entity_registry";
|
|||||||
import { AreaSelector } from "../../data/selector";
|
import { AreaSelector } from "../../data/selector";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "../ha-area-picker";
|
import "../ha-area-picker";
|
||||||
|
import "../ha-areas-picker";
|
||||||
|
|
||||||
@customElement("ha-selector-area")
|
@customElement("ha-selector-area")
|
||||||
export class HaAreaSelector extends LitElement {
|
export class HaAreaSelector extends LitElement {
|
||||||
@@ -38,21 +39,43 @@ export class HaAreaSelector extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`<ha-area-picker
|
if (!this.selector.area.multiple) {
|
||||||
.hass=${this.hass}
|
return html`
|
||||||
.value=${this.value}
|
<ha-area-picker
|
||||||
.label=${this.label}
|
.hass=${this.hass}
|
||||||
no-add
|
.value=${this.value}
|
||||||
.deviceFilter=${this._filterDevices}
|
.label=${this.label}
|
||||||
.entityFilter=${this._filterEntities}
|
no-add
|
||||||
.includeDeviceClasses=${this.selector.area.entity?.device_class
|
.deviceFilter=${this._filterDevices}
|
||||||
? [this.selector.area.entity.device_class]
|
.entityFilter=${this._filterEntities}
|
||||||
: undefined}
|
.includeDeviceClasses=${this.selector.area.entity?.device_class
|
||||||
.includeDomains=${this.selector.area.entity?.domain
|
? [this.selector.area.entity.device_class]
|
||||||
? [this.selector.area.entity.domain]
|
: undefined}
|
||||||
: undefined}
|
.includeDomains=${this.selector.area.entity?.domain
|
||||||
.disabled=${this.disabled}
|
? [this.selector.area.entity.domain]
|
||||||
></ha-area-picker>`;
|
: 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 => {
|
private _filterEntities = (entity: EntityRegistryEntry): boolean => {
|
||||||
|
@@ -14,6 +14,8 @@ export class HaTimeDuration extends LitElement {
|
|||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@property() public helper?: string;
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) public required = true;
|
@property({ type: Boolean }) public required = true;
|
||||||
@@ -22,9 +24,11 @@ export class HaTimeDuration extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-duration-input
|
<ha-duration-input
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
|
.helper=${this.helper}
|
||||||
.data=${this.value}
|
.data=${this.value}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
|
.enableDay=${this.selector.duration.enable_day}
|
||||||
></ha-duration-input>
|
></ha-duration-input>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,6 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
|||||||
.excludeEntities=${this.selector.entity.exclude_entities}
|
.excludeEntities=${this.selector.entity.exclude_entities}
|
||||||
.entityFilter=${this._filterEntities}
|
.entityFilter=${this._filterEntities}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.itemValuePath=${!this.selector.entity.use_uuid ? "entity_id" : "id"}
|
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
></ha-entity-picker>`;
|
></ha-entity-picker>`;
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,6 @@ import type {
|
|||||||
LocationSelector,
|
LocationSelector,
|
||||||
LocationSelectorValue,
|
LocationSelectorValue,
|
||||||
} from "../../data/selector";
|
} from "../../data/selector";
|
||||||
import "../../panels/lovelace/components/hui-theme-select-editor";
|
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import type { MarkerLocation } from "../map/ha-locations-editor";
|
import type { MarkerLocation } from "../map/ha-locations-editor";
|
||||||
import "../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,
|
longitude: value?.longitude || this.hass.config.longitude,
|
||||||
radius: selector.location.radius ? value?.radius || 1000 : undefined,
|
radius: selector.location.radius ? value?.radius || 1000 : undefined,
|
||||||
radius_color: zoneRadiusColor,
|
radius_color: zoneRadiusColor,
|
||||||
icon: selector.location.icon,
|
icon:
|
||||||
|
selector.location.icon || selector.location.radius
|
||||||
|
? "mdi:map-marker-radius"
|
||||||
|
: "mdi:map-marker",
|
||||||
location_editable: true,
|
location_editable: true,
|
||||||
radius_editable: true,
|
radius_editable: true,
|
||||||
},
|
},
|
||||||
|
@@ -19,6 +19,8 @@ export class HaNumberSelector extends LitElement {
|
|||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@property() public helper?: string;
|
||||||
|
|
||||||
@property({ type: Boolean }) public required = true;
|
@property({ type: Boolean }) public required = true;
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
@@ -48,6 +50,8 @@ export class HaNumberSelector extends LitElement {
|
|||||||
.max=${this.selector.number.max}
|
.max=${this.selector.number.max}
|
||||||
.value=${this.value ?? ""}
|
.value=${this.value ?? ""}
|
||||||
.step=${this.selector.number.step ?? 1}
|
.step=${this.selector.number.step ?? 1}
|
||||||
|
helperPersistent
|
||||||
|
.helper=${this.helper}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
.suffix=${this.selector.number.unit_of_measurement}
|
.suffix=${this.selector.number.unit_of_measurement}
|
||||||
|
@@ -18,6 +18,8 @@ export class HaTextSelector extends LitElement {
|
|||||||
|
|
||||||
@property() public placeholder?: string;
|
@property() public placeholder?: string;
|
||||||
|
|
||||||
|
@property() public helper?: string;
|
||||||
|
|
||||||
@property() public selector!: StringSelector;
|
@property() public selector!: StringSelector;
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
@@ -32,6 +34,8 @@ export class HaTextSelector extends LitElement {
|
|||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
.placeholder=${this.placeholder}
|
.placeholder=${this.placeholder}
|
||||||
.value=${this.value || ""}
|
.value=${this.value || ""}
|
||||||
|
.helper=${this.helper}
|
||||||
|
helperPersistent
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@input=${this._handleChange}
|
@input=${this._handleChange}
|
||||||
autocapitalize="none"
|
autocapitalize="none"
|
||||||
@@ -44,6 +48,8 @@ export class HaTextSelector extends LitElement {
|
|||||||
return html`<ha-textfield
|
return html`<ha-textfield
|
||||||
.value=${this.value || ""}
|
.value=${this.value || ""}
|
||||||
.placeholder=${this.placeholder || ""}
|
.placeholder=${this.placeholder || ""}
|
||||||
|
.helper=${this.helper}
|
||||||
|
helperPersistent
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.type=${this._unmaskedPassword ? "text" : this.selector.text?.type}
|
.type=${this._unmaskedPassword ? "text" : this.selector.text?.type}
|
||||||
@input=${this._handleChange}
|
@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 { html, LitElement } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
@@ -18,11 +18,11 @@ export class HaThemeSelector extends LitElement {
|
|||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
return html`
|
||||||
<hui-theme-select-editor
|
<ha-theme-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
></hui-theme-select-editor>
|
></ha-theme-picker>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -471,6 +471,7 @@ export class HaServiceControl extends LitElement {
|
|||||||
}
|
}
|
||||||
ha-settings-row {
|
ha-settings-row {
|
||||||
--paper-time-input-justify-content: flex-end;
|
--paper-time-input-justify-content: flex-end;
|
||||||
|
--settings-row-content-width: 100%;
|
||||||
border-top: var(
|
border-top: var(
|
||||||
--service-control-items-border-top,
|
--service-control-items-border-top,
|
||||||
1px solid var(--divider-color)
|
1px solid var(--divider-color)
|
||||||
@@ -489,9 +490,6 @@ export class HaServiceControl extends LitElement {
|
|||||||
margin: var(--service-control-padding, 0 16px);
|
margin: var(--service-control-padding, 0 16px);
|
||||||
padding: 16px 0;
|
padding: 16px 0;
|
||||||
}
|
}
|
||||||
:host(:not([narrow])) ha-settings-row ha-selector {
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
.checkbox-spacer {
|
.checkbox-spacer {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ export class HaSettingsRow extends LitElement {
|
|||||||
<div secondary><slot name="description"></slot></div>
|
<div secondary><slot name="description"></slot></div>
|
||||||
</paper-item-body>
|
</paper-item-body>
|
||||||
</div>
|
</div>
|
||||||
<slot></slot>
|
<div class="content"><slot></slot></div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +43,18 @@ export class HaSettingsRow extends LitElement {
|
|||||||
);
|
);
|
||||||
flex: 1;
|
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]) {
|
:host([narrow]) {
|
||||||
align-items: normal;
|
align-items: normal;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@@ -37,6 +37,7 @@ import { LocalStorage } from "../common/decorators/local-storage";
|
|||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { toggleAttribute } from "../common/dom/toggle_attribute";
|
import { toggleAttribute } from "../common/dom/toggle_attribute";
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
|
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||||
import { stringCompare } from "../common/string/compare";
|
import { stringCompare } from "../common/string/compare";
|
||||||
import { computeRTL } from "../common/util/compute_rtl";
|
import { computeRTL } from "../common/util/compute_rtl";
|
||||||
import { ActionHandlerDetail } from "../data/lovelace";
|
import { ActionHandlerDetail } from "../data/lovelace";
|
||||||
@@ -44,6 +45,7 @@ import {
|
|||||||
PersistentNotification,
|
PersistentNotification,
|
||||||
subscribeNotifications,
|
subscribeNotifications,
|
||||||
} from "../data/persistent_notification";
|
} from "../data/persistent_notification";
|
||||||
|
import { updateCanInstall, UpdateEntity } from "../data/update";
|
||||||
import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive";
|
import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant, PanelInfo, Route } from "../types";
|
import type { HomeAssistant, PanelInfo, Route } from "../types";
|
||||||
@@ -68,7 +70,6 @@ const SORT_VALUE_URL_PATHS = {
|
|||||||
|
|
||||||
const PANEL_ICONS = {
|
const PANEL_ICONS = {
|
||||||
calendar: mdiCalendar,
|
calendar: mdiCalendar,
|
||||||
config: mdiCog,
|
|
||||||
"developer-tools": mdiHammer,
|
"developer-tools": mdiHammer,
|
||||||
energy: mdiLightningBolt,
|
energy: mdiLightningBolt,
|
||||||
history: mdiChartBox,
|
history: mdiChartBox,
|
||||||
@@ -190,6 +191,8 @@ class HaSidebar extends LitElement {
|
|||||||
|
|
||||||
@state() private _notifications?: PersistentNotification[];
|
@state() private _notifications?: PersistentNotification[];
|
||||||
|
|
||||||
|
@state() private _updatesCount = 0;
|
||||||
|
|
||||||
@state() private _renderEmptySortable = false;
|
@state() private _renderEmptySortable = false;
|
||||||
|
|
||||||
private _mouseLeaveTimeout?: number;
|
private _mouseLeaveTimeout?: number;
|
||||||
@@ -235,6 +238,7 @@ class HaSidebar extends LitElement {
|
|||||||
changedProps.has("narrow") ||
|
changedProps.has("narrow") ||
|
||||||
changedProps.has("alwaysExpand") ||
|
changedProps.has("alwaysExpand") ||
|
||||||
changedProps.has("_externalConfig") ||
|
changedProps.has("_externalConfig") ||
|
||||||
|
changedProps.has("_updatesCount") ||
|
||||||
changedProps.has("_notifications") ||
|
changedProps.has("_notifications") ||
|
||||||
changedProps.has("editMode") ||
|
changedProps.has("editMode") ||
|
||||||
changedProps.has("_renderEmptySortable") ||
|
changedProps.has("_renderEmptySortable") ||
|
||||||
@@ -290,6 +294,12 @@ class HaSidebar extends LitElement {
|
|||||||
toggleAttribute(this, "rtl", computeRTL(this.hass));
|
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) {
|
if (!SUPPORT_SCROLL_IF_NEEDED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -387,35 +397,37 @@ class HaSidebar extends LitElement {
|
|||||||
icon?: string | null,
|
icon?: string | null,
|
||||||
iconPath?: string | null
|
iconPath?: string | null
|
||||||
) {
|
) {
|
||||||
return html`
|
return urlPath === "config"
|
||||||
<a
|
? this._renderConfiguration(title)
|
||||||
role="option"
|
: html`
|
||||||
href=${`/${urlPath}`}
|
<a
|
||||||
data-panel=${urlPath}
|
role="option"
|
||||||
tabindex="-1"
|
href=${`/${urlPath}`}
|
||||||
@mouseenter=${this._itemMouseEnter}
|
data-panel=${urlPath}
|
||||||
@mouseleave=${this._itemMouseLeave}
|
tabindex="-1"
|
||||||
>
|
@mouseenter=${this._itemMouseEnter}
|
||||||
<paper-icon-item>
|
@mouseleave=${this._itemMouseLeave}
|
||||||
${iconPath
|
>
|
||||||
? html`<ha-svg-icon
|
<paper-icon-item>
|
||||||
slot="item-icon"
|
${iconPath
|
||||||
.path=${iconPath}
|
? html`<ha-svg-icon
|
||||||
></ha-svg-icon>`
|
slot="item-icon"
|
||||||
: html`<ha-icon slot="item-icon" .icon=${icon}></ha-icon>`}
|
.path=${iconPath}
|
||||||
<span class="item-text">${title}</span>
|
></ha-svg-icon>`
|
||||||
</paper-icon-item>
|
: html`<ha-icon slot="item-icon" .icon=${icon}></ha-icon>`}
|
||||||
${this.editMode
|
<span class="item-text">${title}</span>
|
||||||
? html`<ha-icon-button
|
</paper-icon-item>
|
||||||
.label=${this.hass.localize("ui.sidebar.hide_panel")}
|
${this.editMode
|
||||||
.path=${mdiClose}
|
? html`<ha-icon-button
|
||||||
class="hide-panel"
|
.label=${this.hass.localize("ui.sidebar.hide_panel")}
|
||||||
.panel=${urlPath}
|
.path=${mdiClose}
|
||||||
@click=${this._hidePanel}
|
class="hide-panel"
|
||||||
></ha-icon-button>`
|
.panel=${urlPath}
|
||||||
: ""}
|
@click=${this._hidePanel}
|
||||||
</a>
|
></ha-icon-button>`
|
||||||
`;
|
: ""}
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderPanelsEdit(beforeSpacer: PanelInfo[]) {
|
private _renderPanelsEdit(beforeSpacer: PanelInfo[]) {
|
||||||
@@ -477,6 +489,35 @@ class HaSidebar extends LitElement {
|
|||||||
return html`<div class="spacer" disabled></div>`;
|
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() {
|
private _renderNotifications() {
|
||||||
let notificationCount = this._notifications
|
let notificationCount = this._notifications
|
||||||
? this._notifications.length
|
? this._notifications.length
|
||||||
@@ -953,18 +994,21 @@ class HaSidebar extends LitElement {
|
|||||||
height: 1px;
|
height: 1px;
|
||||||
background-color: var(--divider-color);
|
background-color: var(--divider-color);
|
||||||
}
|
}
|
||||||
.notifications-container {
|
.notifications-container,
|
||||||
|
.configuration-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: env(safe-area-inset-left);
|
margin-left: env(safe-area-inset-left);
|
||||||
}
|
}
|
||||||
:host([rtl]) .notifications-container {
|
:host([rtl]) .notifications-container,
|
||||||
|
:host([rtl]) .configuration-container {
|
||||||
margin-left: initial;
|
margin-left: initial;
|
||||||
margin-right: env(safe-area-inset-right);
|
margin-right: env(safe-area-inset-right);
|
||||||
}
|
}
|
||||||
.notifications {
|
.notifications {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.notifications .item-text {
|
.notifications .item-text,
|
||||||
|
.configuration .item-text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
.profile {
|
.profile {
|
||||||
@@ -988,7 +1032,8 @@ class HaSidebar extends LitElement {
|
|||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification-badge {
|
.notification-badge,
|
||||||
|
.configuration-badge {
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@@ -999,7 +1044,11 @@ class HaSidebar extends LitElement {
|
|||||||
padding: 0px 6px;
|
padding: 0px 6px;
|
||||||
color: var(--text-accent-color, var(--text-primary-color));
|
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;
|
position: absolute;
|
||||||
bottom: 14px;
|
bottom: 14px;
|
||||||
left: 26px;
|
left: 26px;
|
||||||
|
@@ -2,13 +2,13 @@ import "@material/mwc-button";
|
|||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
import { stopPropagation } from "../common/dom/stop_propagation";
|
||||||
import "../../../components/ha-select";
|
import "./ha-select";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
@customElement("hui-theme-select-editor")
|
@customElement("ha-theme-picker")
|
||||||
export class HuiThemeSelectEditor extends LitElement {
|
export class HaThemePicker extends LitElement {
|
||||||
@property() public value?: string;
|
@property() public value?: string;
|
||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
@@ -19,11 +19,7 @@ export class HuiThemeSelectEditor extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-select
|
<ha-select
|
||||||
.label=${this.label ||
|
.label=${this.label ||
|
||||||
`${this.hass!.localize(
|
this.hass!.localize("ui.components.theme_picker.theme")}
|
||||||
"ui.panel.lovelace.editor.card.generic.theme"
|
|
||||||
)} (${this.hass!.localize(
|
|
||||||
"ui.panel.lovelace.editor.card.config.optional"
|
|
||||||
)})`}
|
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
@selected=${this._changed}
|
@selected=${this._changed}
|
||||||
@closed=${stopPropagation}
|
@closed=${stopPropagation}
|
||||||
@@ -32,7 +28,7 @@ export class HuiThemeSelectEditor extends LitElement {
|
|||||||
>
|
>
|
||||||
<mwc-list-item value="remove"
|
<mwc-list-item value="remove"
|
||||||
>${this.hass!.localize(
|
>${this.hass!.localize(
|
||||||
"ui.panel.lovelace.editor.card.generic.no_theme"
|
"ui.components.theme_picker.no_theme"
|
||||||
)}</mwc-list-item
|
)}</mwc-list-item
|
||||||
>
|
>
|
||||||
${Object.keys(this.hass!.themes.themes)
|
${Object.keys(this.hass!.themes.themes)
|
||||||
@@ -64,6 +60,6 @@ export class HuiThemeSelectEditor extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"hui-theme-select-editor": HuiThemeSelectEditor;
|
"ha-theme-picker": HaThemePicker;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -488,6 +488,14 @@ export class HaMap extends ReactiveElement {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
color: var(--primary-text-color);
|
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 {
|
export interface BaseTrigger {
|
||||||
platform: string;
|
platform: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
|
variables?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StateTrigger extends BaseTrigger {
|
export interface StateTrigger extends BaseTrigger {
|
||||||
|
@@ -46,6 +46,7 @@ export interface AreaSelector {
|
|||||||
manufacturer?: DeviceSelector["device"]["manufacturer"];
|
manufacturer?: DeviceSelector["device"]["manufacturer"];
|
||||||
model?: DeviceSelector["device"]["model"];
|
model?: DeviceSelector["device"]["model"];
|
||||||
};
|
};
|
||||||
|
multiple?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +97,9 @@ export interface DeviceSelector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DurationSelector {
|
export interface DurationSelector {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
duration: {
|
||||||
duration: {};
|
enable_day?: boolean;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntitySelector {
|
export interface EntitySelector {
|
||||||
@@ -106,7 +108,6 @@ export interface EntitySelector {
|
|||||||
domain?: string | string[];
|
domain?: string | string[];
|
||||||
device_class?: string;
|
device_class?: string;
|
||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
use_uuid?: boolean;
|
|
||||||
include_entities?: string[];
|
include_entities?: string[];
|
||||||
exclude_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 { computeRTL } from "../../common/util/compute_rtl";
|
||||||
import "../../components/ha-circular-progress";
|
import "../../components/ha-circular-progress";
|
||||||
import "../../components/ha-dialog";
|
import "../../components/ha-dialog";
|
||||||
import "../../components/ha-form/ha-form";
|
|
||||||
import "../../components/ha-icon-button";
|
import "../../components/ha-icon-button";
|
||||||
import "../../components/ha-markdown";
|
|
||||||
import {
|
import {
|
||||||
AreaRegistryEntry,
|
AreaRegistryEntry,
|
||||||
subscribeAreaRegistry,
|
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) {
|
renderShowFormStepFieldError(hass, step, error) {
|
||||||
return hass.localize(
|
return hass.localize(
|
||||||
`component.${step.handler}.config.error.${error}`,
|
`component.${step.handler}.config.error.${error}`,
|
||||||
|
@@ -50,6 +50,12 @@ export interface FlowConfig {
|
|||||||
field: HaFormSchema
|
field: HaFormSchema
|
||||||
): string;
|
): string;
|
||||||
|
|
||||||
|
renderShowFormStepFieldHelper(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
step: DataEntryFlowStepForm,
|
||||||
|
field: HaFormSchema
|
||||||
|
): string;
|
||||||
|
|
||||||
renderShowFormStepFieldError(
|
renderShowFormStepFieldError(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
step: DataEntryFlowStepForm,
|
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) {
|
renderShowFormStepFieldError(hass, step, error) {
|
||||||
return hass.localize(
|
return hass.localize(
|
||||||
`component.${configEntry.domain}.options.error.${error}`,
|
`component.${configEntry.domain}.options.error.${error}`,
|
||||||
|
@@ -54,6 +54,7 @@ class StepFlowForm extends LitElement {
|
|||||||
.schema=${step.data_schema}
|
.schema=${step.data_schema}
|
||||||
.error=${step.errors}
|
.error=${step.errors}
|
||||||
.computeLabel=${this._labelCallback}
|
.computeLabel=${this._labelCallback}
|
||||||
|
.computeHelper=${this._helperCallback}
|
||||||
.computeError=${this._errorCallback}
|
.computeError=${this._errorCallback}
|
||||||
></ha-form>
|
></ha-form>
|
||||||
</div>
|
</div>
|
||||||
@@ -166,6 +167,9 @@ class StepFlowForm extends LitElement {
|
|||||||
private _labelCallback = (field: HaFormSchema): string =>
|
private _labelCallback = (field: HaFormSchema): string =>
|
||||||
this.flowConfig.renderShowFormStepFieldLabel(this.hass, this.step, field);
|
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) =>
|
private _errorCallback = (error: string) =>
|
||||||
this.flowConfig.renderShowFormStepFieldError(this.hass, this.step, error);
|
this.flowConfig.renderShowFormStepFieldError(this.hass, this.step, error);
|
||||||
|
|
||||||
|
@@ -326,12 +326,9 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
ha-settings-row {
|
ha-settings-row {
|
||||||
--paper-time-input-justify-content: flex-end;
|
--paper-time-input-justify-content: flex-end;
|
||||||
|
--settings-row-content-width: 100%;
|
||||||
border-top: 1px solid var(--divider-color);
|
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-button/mwc-button";
|
||||||
|
import "@material/mwc-formfield/mwc-formfield";
|
||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import {
|
import {
|
||||||
@@ -20,9 +19,15 @@ import "../../../components/ha-alert";
|
|||||||
import "../../../components/ha-area-picker";
|
import "../../../components/ha-area-picker";
|
||||||
import "../../../components/ha-expansion-panel";
|
import "../../../components/ha-expansion-panel";
|
||||||
import "../../../components/ha-icon-picker";
|
import "../../../components/ha-icon-picker";
|
||||||
|
import "../../../components/ha-radio";
|
||||||
import "../../../components/ha-select";
|
import "../../../components/ha-select";
|
||||||
import "../../../components/ha-switch";
|
import "../../../components/ha-switch";
|
||||||
import "../../../components/ha-textfield";
|
import "../../../components/ha-textfield";
|
||||||
|
import {
|
||||||
|
ConfigEntry,
|
||||||
|
deleteConfigEntry,
|
||||||
|
getConfigEntries,
|
||||||
|
} from "../../../data/config_entries";
|
||||||
import {
|
import {
|
||||||
DeviceRegistryEntry,
|
DeviceRegistryEntry,
|
||||||
subscribeDeviceRegistry,
|
subscribeDeviceRegistry,
|
||||||
@@ -34,6 +39,7 @@ import {
|
|||||||
removeEntityRegistryEntry,
|
removeEntityRegistryEntry,
|
||||||
updateEntityRegistryEntry,
|
updateEntityRegistryEntry,
|
||||||
} from "../../../data/entity_registry";
|
} from "../../../data/entity_registry";
|
||||||
|
import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
showConfirmationDialog,
|
showConfirmationDialog,
|
||||||
@@ -42,27 +48,39 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
|||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { showDeviceRegistryDetailDialog } from "../devices/device-registry-detail/show-dialog-device-registry-detail";
|
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 = {
|
const OVERRIDE_DEVICE_CLASSES = {
|
||||||
cover: [
|
cover: [
|
||||||
"awning",
|
[
|
||||||
"blind",
|
"awning",
|
||||||
"curtain",
|
"blind",
|
||||||
"damper",
|
"curtain",
|
||||||
"door",
|
"damper",
|
||||||
"garage",
|
"door",
|
||||||
"gate",
|
"garage",
|
||||||
"shade",
|
"gate",
|
||||||
"shutter",
|
"shade",
|
||||||
"window",
|
"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")
|
@customElement("entity-registry-settings")
|
||||||
@@ -85,8 +103,6 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
@state() private _hiddenBy!: string | null;
|
@state() private _hiddenBy!: string | null;
|
||||||
|
|
||||||
private _deviceLookup?: Record<string, DeviceRegistryEntry>;
|
|
||||||
|
|
||||||
@state() private _device?: DeviceRegistryEntry;
|
@state() private _device?: DeviceRegistryEntry;
|
||||||
|
|
||||||
@state() private _helperConfigEntry?: ConfigEntry;
|
@state() private _helperConfigEntry?: ConfigEntry;
|
||||||
@@ -97,6 +113,10 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
private _origEntityId!: string;
|
private _origEntityId!: string;
|
||||||
|
|
||||||
|
private _deviceLookup?: Record<string, DeviceRegistryEntry>;
|
||||||
|
|
||||||
|
private _deviceClassOptions?: string[][];
|
||||||
|
|
||||||
public hassSubscribe(): UnsubscribeFunc[] {
|
public hassSubscribe(): UnsubscribeFunc[] {
|
||||||
return [
|
return [
|
||||||
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
|
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
|
||||||
@@ -125,23 +145,41 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProperties: PropertyValues) {
|
protected willUpdate(changedProperties: PropertyValues) {
|
||||||
super.updated(changedProperties);
|
super.willUpdate(changedProperties);
|
||||||
if (changedProperties.has("entry")) {
|
if (!changedProperties.has("entry")) {
|
||||||
this._error = undefined;
|
return;
|
||||||
this._name = this.entry.name || "";
|
}
|
||||||
this._icon = this.entry.icon || "";
|
|
||||||
this._deviceClass =
|
this._error = undefined;
|
||||||
this.entry.device_class || this.entry.original_device_class;
|
this._name = this.entry.name || "";
|
||||||
this._origEntityId = this.entry.entity_id;
|
this._icon = this.entry.icon || "";
|
||||||
this._areaId = this.entry.area_id;
|
this._deviceClass =
|
||||||
this._entityId = this.entry.entity_id;
|
this.entry.device_class || this.entry.original_device_class;
|
||||||
this._disabledBy = this.entry.disabled_by;
|
this._origEntityId = this.entry.entity_id;
|
||||||
this._hiddenBy = this.entry.hidden_by;
|
this._areaId = this.entry.area_id;
|
||||||
this._device =
|
this._entityId = this.entry.entity_id;
|
||||||
this.entry.device_id && this._deviceLookup
|
this._disabledBy = this.entry.disabled_by;
|
||||||
? this._deviceLookup[this.entry.device_id]
|
this._hiddenBy = this.entry.hidden_by;
|
||||||
: undefined;
|
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}
|
: undefined}
|
||||||
.disabled=${this._submitting}
|
.disabled=${this._submitting}
|
||||||
></ha-icon-picker>
|
></ha-icon-picker>
|
||||||
${OVERRIDE_DEVICE_CLASSES[domain]?.includes(this._deviceClass) ||
|
${this._deviceClassOptions
|
||||||
(domain === "cover" && this.entry.original_device_class === null)
|
? html`
|
||||||
? html`<ha-select
|
<ha-select
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.dialogs.entity_registry.editor.device_class"
|
"ui.dialogs.entity_registry.editor.device_class"
|
||||||
)}
|
)}
|
||||||
.value=${this._deviceClass}
|
.value=${this._deviceClass}
|
||||||
naturalMenuWidth
|
naturalMenuWidth
|
||||||
fixedMenuPosition
|
fixedMenuPosition
|
||||||
@selected=${this._deviceClassChanged}
|
@selected=${this._deviceClassChanged}
|
||||||
@closed=${stopPropagation}
|
@closed=${stopPropagation}
|
||||||
>
|
>
|
||||||
${OVERRIDE_DEVICE_CLASSES[domain].map(
|
${this._deviceClassOptions[0].map(
|
||||||
(deviceClass: string) => html`
|
(deviceClass: string) => html`
|
||||||
<mwc-list-item .value=${deviceClass}>
|
<mwc-list-item .value=${deviceClass} test=${deviceClass}>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${deviceClass}`
|
`ui.dialogs.entity_registry.editor.device_classes.${domain}.${deviceClass}`
|
||||||
)}
|
)}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
</ha-select>`
|
<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
|
<ha-textfield
|
||||||
error-message="Domain needs to stay the same"
|
error-message="Domain needs to stay the same"
|
||||||
@@ -264,7 +313,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
)}:
|
)}:
|
||||||
</div>
|
</div>
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
${this._disabledBy && this._disabledBy !== "user"
|
${this._disabledBy &&
|
||||||
|
this._disabledBy !== "user" &&
|
||||||
|
this._disabledBy !== "integration"
|
||||||
? this.hass.localize(
|
? this.hass.localize(
|
||||||
"ui.dialogs.entity_registry.editor.enabled_cause",
|
"ui.dialogs.entity_registry.editor.enabled_cause",
|
||||||
"cause",
|
"cause",
|
||||||
@@ -286,7 +337,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
.checked=${!this._hiddenBy && !this._disabledBy}
|
.checked=${!this._hiddenBy && !this._disabledBy}
|
||||||
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
||||||
this._device?.disabled_by ||
|
this._device?.disabled_by ||
|
||||||
(this._disabledBy && this._disabledBy !== "user")}
|
(this._disabledBy &&
|
||||||
|
this._disabledBy !== "user" &&
|
||||||
|
this._disabledBy !== "integration")}
|
||||||
@change=${this._viewStatusChanged}
|
@change=${this._viewStatusChanged}
|
||||||
></ha-radio>
|
></ha-radio>
|
||||||
</mwc-formfield>
|
</mwc-formfield>
|
||||||
@@ -301,7 +354,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
.checked=${this._hiddenBy !== null}
|
.checked=${this._hiddenBy !== null}
|
||||||
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
||||||
Boolean(this._device?.disabled_by) ||
|
Boolean(this._device?.disabled_by) ||
|
||||||
(this._disabledBy && this._disabledBy !== "user")}
|
(this._disabledBy &&
|
||||||
|
this._disabledBy !== "user" &&
|
||||||
|
this._disabledBy !== "integration")}
|
||||||
@change=${this._viewStatusChanged}
|
@change=${this._viewStatusChanged}
|
||||||
></ha-radio>
|
></ha-radio>
|
||||||
</mwc-formfield>
|
</mwc-formfield>
|
||||||
@@ -316,7 +371,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
.checked=${this._disabledBy !== null}
|
.checked=${this._disabledBy !== null}
|
||||||
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
.disabled=${(this._hiddenBy && this._hiddenBy !== "user") ||
|
||||||
Boolean(this._device?.disabled_by) ||
|
Boolean(this._device?.disabled_by) ||
|
||||||
(this._disabledBy && this._disabledBy !== "user")}
|
(this._disabledBy &&
|
||||||
|
this._disabledBy !== "user" &&
|
||||||
|
this._disabledBy !== "integration")}
|
||||||
@change=${this._viewStatusChanged}
|
@change=${this._viewStatusChanged}
|
||||||
></ha-radio>
|
></ha-radio>
|
||||||
</mwc-formfield>
|
</mwc-formfield>
|
||||||
@@ -378,7 +435,7 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
class="warning"
|
class="warning"
|
||||||
@click=${this._confirmDeleteEntry}
|
@click=${this._confirmDeleteEntry}
|
||||||
.disabled=${this._submitting ||
|
.disabled=${this._submitting ||
|
||||||
(!this._helperConfigEntry && !stateObj.attributes.restored)}
|
(!this._helperConfigEntry && !stateObj?.attributes.restored)}
|
||||||
>
|
>
|
||||||
${this.hass.localize("ui.dialogs.entity_registry.editor.delete")}
|
${this.hass.localize("ui.dialogs.entity_registry.editor.delete")}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
@@ -577,6 +634,9 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
|||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
width: 340px;
|
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);
|
outline: 2px solid var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
:host:not(.panel) ::slotted(*) {
|
:host(:not(.panel)) ::slotted(*) {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,7 +23,6 @@ export const configElementStyle = css`
|
|||||||
.suffix {
|
.suffix {
|
||||||
margin: 0 8px;
|
margin: 0 8px;
|
||||||
}
|
}
|
||||||
hui-theme-select-editor,
|
|
||||||
hui-action-editor,
|
hui-action-editor,
|
||||||
ha-select,
|
ha-select,
|
||||||
ha-textfield,
|
ha-textfield,
|
||||||
|
@@ -99,6 +99,14 @@ export class HuiAlarmPanelCardEditor
|
|||||||
return this.hass!.localize(`ui.panel.lovelace.editor.card.generic.name`);
|
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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.alarm-panel.${
|
`ui.panel.lovelace.editor.card.alarm-panel.${
|
||||||
schema.name === "states" ? "available_states" : schema.name
|
schema.name === "states" ? "available_states" : schema.name
|
||||||
|
@@ -69,6 +69,12 @@ export class HuiAreaCardEditor
|
|||||||
|
|
||||||
private _computeLabelCallback = (schema: HaFormSchema) => {
|
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||||
switch (schema.name) {
|
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":
|
case "area":
|
||||||
return this.hass!.localize("ui.panel.lovelace.editor.card.area.name");
|
return this.hass!.localize("ui.panel.lovelace.editor.card.area.name");
|
||||||
case "navigation_path":
|
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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`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");
|
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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.calendar.${schema.name}`
|
`ui.panel.lovelace.editor.card.calendar.${schema.name}`
|
||||||
);
|
);
|
||||||
|
@@ -31,7 +31,7 @@ import "../../../../components/ha-icon";
|
|||||||
import "../../../../components/ha-switch";
|
import "../../../../components/ha-switch";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import type { EntitiesCardConfig } from "../../cards/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 { TIMESTAMP_RENDERING_FORMATS } from "../../components/types";
|
||||||
import type { LovelaceRowConfig } from "../../entity-rows/types";
|
import type { LovelaceRowConfig } from "../../entity-rows/types";
|
||||||
import { headerFooterConfigStructs } from "../../header-footer/structs";
|
import { headerFooterConfigStructs } from "../../header-footer/structs";
|
||||||
@@ -265,12 +265,17 @@ export class HuiEntitiesCardEditor
|
|||||||
.configValue=${"title"}
|
.configValue=${"title"}
|
||||||
@input=${this._valueChanged}
|
@input=${this._valueChanged}
|
||||||
></ha-textfield>
|
></ha-textfield>
|
||||||
<hui-theme-select-editor
|
<ha-theme-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._theme}
|
.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"}
|
.configValue=${"theme"}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></hui-theme-select-editor>
|
></ha-theme-picker>
|
||||||
<div class="side-by-side">
|
<div class="side-by-side">
|
||||||
<ha-formfield
|
<ha-formfield
|
||||||
.label=${this.hass.localize(
|
.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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||||
);
|
);
|
||||||
|
@@ -172,6 +172,12 @@ export class HuiGaugeCardEditor
|
|||||||
return this.hass!.localize(
|
return this.hass!.localize(
|
||||||
"ui.panel.lovelace.editor.card.gauge.needle_gauge"
|
"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 (
|
return (
|
||||||
this.hass!.localize(
|
this.hass!.localize(
|
||||||
|
@@ -117,11 +117,23 @@ export class HuiGlanceCardEditor
|
|||||||
fireEvent(this, "config-changed", { config });
|
fireEvent(this, "config-changed", { config });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeLabelCallback = (schema: HaFormSchema) =>
|
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||||
this.hass!.localize(
|
if (schema.name === "theme") {
|
||||||
`ui.panel.lovelace.editor.card.glance.${schema.name}`
|
return `${this.hass!.localize(
|
||||||
) ||
|
"ui.panel.lovelace.editor.card.generic.theme"
|
||||||
this.hass!.localize(`ui.panel.lovelace.editor.card.generic.${schema.name}`);
|
)} (${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 {
|
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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||||
);
|
);
|
||||||
|
@@ -96,11 +96,24 @@ export class HuiLogbookCardEditor
|
|||||||
fireEvent(this, "config-changed", { config: ev.detail.value });
|
fireEvent(this, "config-changed", { config: ev.detail.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeLabelCallback = (schema: HaFormSchema) =>
|
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||||
this.hass!.localize(
|
if (schema.name === "theme") {
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
return `${this.hass!.localize(
|
||||||
) ||
|
"ui.panel.lovelace.editor.card.generic.theme"
|
||||||
this.hass!.localize(`ui.panel.lovelace.editor.card.logbook.${schema.name}`);
|
)} (${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 {
|
declare global {
|
||||||
|
@@ -58,13 +58,23 @@ export class HuiMarkdownCardEditor
|
|||||||
fireEvent(this, "config-changed", { config: ev.detail.value });
|
fireEvent(this, "config-changed", { config: ev.detail.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _computeLabelCallback = (schema: HaFormSchema) =>
|
private _computeLabelCallback = (schema: HaFormSchema) => {
|
||||||
this.hass!.localize(
|
if (schema.name === "theme") {
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
return `${this.hass!.localize(
|
||||||
) ||
|
"ui.panel.lovelace.editor.card.generic.theme"
|
||||||
this.hass!.localize(
|
)} (${this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.markdown.${schema.name}`
|
"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 {
|
declare global {
|
||||||
|
@@ -5,7 +5,7 @@ import { fireEvent } from "../../../../common/dom/fire_event";
|
|||||||
import "../../../../components/entity/ha-entity-picker";
|
import "../../../../components/entity/ha-entity-picker";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { MediaControlCardConfig } from "../../cards/types";
|
import { MediaControlCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-theme-select-editor";
|
import "../../../../components/ha-theme-picker";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
@@ -62,12 +62,17 @@ export class HuiMediaControlCardEditor
|
|||||||
@change=${this._valueChanged}
|
@change=${this._valueChanged}
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
></ha-entity-picker>
|
></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}
|
.hass=${this.hass}
|
||||||
.value=${this._theme}
|
.value=${this._theme}
|
||||||
.configValue=${"theme"}
|
.configValue=${"theme"}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></hui-theme-select-editor>
|
></ha-theme-picker>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@ import { ActionConfig } from "../../../../data/lovelace";
|
|||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { PictureCardConfig } from "../../cards/types";
|
import { PictureCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-action-editor";
|
import "../../components/hui-action-editor";
|
||||||
import "../../components/hui-theme-select-editor";
|
import "../../../../components/ha-theme-picker";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { actionConfigStruct } from "../structs/action-struct";
|
import { actionConfigStruct } from "../structs/action-struct";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
@@ -72,12 +72,17 @@ export class HuiPictureCardEditor
|
|||||||
.configValue=${"image"}
|
.configValue=${"image"}
|
||||||
@input=${this._valueChanged}
|
@input=${this._valueChanged}
|
||||||
></ha-textfield>
|
></ha-textfield>
|
||||||
<hui-theme-select-editor
|
<ha-theme-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._theme}
|
.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"}
|
.configValue=${"theme"}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></hui-theme-select-editor>
|
></ha-theme-picker>
|
||||||
<hui-action-editor
|
<hui-action-editor
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
"ui.panel.lovelace.editor.card.generic.tap_action"
|
"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 (
|
return (
|
||||||
this.hass!.localize(
|
this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`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 (
|
return (
|
||||||
this.hass!.localize(
|
this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||||
|
@@ -64,7 +64,13 @@ export class HuiPlantStatusCardEditor
|
|||||||
"ui.panel.lovelace.editor.card.generic.entity"
|
"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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`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") {
|
if (schema.name === "detail") {
|
||||||
return this.hass!.localize(
|
return this.hass!.localize(
|
||||||
"ui.panel.lovelace.editor.card.sensor.show_more_detail"
|
"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 { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { ShoppingListCardConfig } from "../../cards/types";
|
import { ShoppingListCardConfig } from "../../cards/types";
|
||||||
import "../../components/hui-theme-select-editor";
|
import "../../../../components/ha-theme-picker";
|
||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
@@ -67,12 +67,17 @@ export class HuiShoppingListEditor
|
|||||||
.configValue=${"title"}
|
.configValue=${"title"}
|
||||||
@input=${this._valueChanged}
|
@input=${this._valueChanged}
|
||||||
></ha-textfield>
|
></ha-textfield>
|
||||||
<hui-theme-select-editor
|
<ha-theme-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._theme}
|
.value=${this._theme}
|
||||||
.configValue=${"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}
|
@value-changed=${this._valueChanged}
|
||||||
></hui-theme-select-editor>
|
></ha-theme-picker>
|
||||||
</div>
|
</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(
|
return this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`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 (
|
return (
|
||||||
this.hass!.localize(
|
this.hass!.localize(
|
||||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||||
|
@@ -401,6 +401,10 @@
|
|||||||
"add_device_id": "Choose device",
|
"add_device_id": "Choose device",
|
||||||
"add_entity_id": "Choose entity"
|
"add_entity_id": "Choose entity"
|
||||||
},
|
},
|
||||||
|
"theme-picker": {
|
||||||
|
"theme": "Theme",
|
||||||
|
"no_theme": "No theme"
|
||||||
|
},
|
||||||
"user-picker": {
|
"user-picker": {
|
||||||
"no_user": "No user",
|
"no_user": "No user",
|
||||||
"add_user": "Add user",
|
"add_user": "Add user",
|
||||||
@@ -786,7 +790,31 @@
|
|||||||
"door": "Door",
|
"door": "Door",
|
||||||
"garage_door": "Garage door",
|
"garage_door": "Garage door",
|
||||||
"window": "Window",
|
"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": {
|
"cover": {
|
||||||
"door": "Door",
|
"door": "Door",
|
||||||
@@ -3458,7 +3486,6 @@
|
|||||||
"tap_action": "Tap Action",
|
"tap_action": "Tap Action",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
"theme": "Theme",
|
"theme": "Theme",
|
||||||
"no_theme": "No theme",
|
|
||||||
"unit": "Unit",
|
"unit": "Unit",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"state": "State",
|
"state": "State",
|
||||||
|
Reference in New Issue
Block a user