mirror of
https://github.com/home-assistant/frontend.git
synced 2025-12-12 02:57:25 +00:00
Compare commits
11 Commits
copilot/mi
...
targets-on
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26a5b85eb0 | ||
|
|
bba400443e | ||
|
|
a7a937e197 | ||
|
|
2a97913520 | ||
|
|
9f16ce7341 | ||
|
|
3e20e9b388 | ||
|
|
6891eb9ff8 | ||
|
|
f649b3783d | ||
|
|
c46f67d572 | ||
|
|
86acfa67dd | ||
|
|
3c5c19270f |
@@ -1,4 +1,4 @@
|
|||||||
import type { DeviceRegistryEntry } from "../../../src/data/device_registry";
|
import type { DeviceRegistryEntry } from "../../../src/data/device/device_registry";
|
||||||
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
|
|
||||||
export const mockDeviceRegistry = (
|
export const mockDeviceRegistry = (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { EntityRegistryEntry } from "../../../src/data/entity_registry";
|
import type { EntityRegistryEntry } from "../../../src/data/entity/entity_registry";
|
||||||
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
|
|
||||||
export const mockEntityRegistry = (
|
export const mockEntityRegistry = (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { LabelRegistryEntry } from "../../../src/data/label_registry";
|
import type { LabelRegistryEntry } from "../../../src/data/label/label_registry";
|
||||||
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
import type { MockHomeAssistant } from "../../../src/fake_data/provide_hass";
|
||||||
|
|
||||||
export const mockLabelRegistry = (
|
export const mockLabelRegistry = (
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ export class DemoAutomationDescribeAction extends LitElement {
|
|||||||
<div class="action">
|
<div class="action">
|
||||||
<span>
|
<span>
|
||||||
${this._action
|
${this._action
|
||||||
? describeAction(this.hass, [], [], {}, this._action)
|
? describeAction(this.hass, [], this._action)
|
||||||
: "<invalid YAML>"}
|
: "<invalid YAML>"}
|
||||||
</span>
|
</span>
|
||||||
<ha-yaml-editor
|
<ha-yaml-editor
|
||||||
@@ -155,7 +155,7 @@ export class DemoAutomationDescribeAction extends LitElement {
|
|||||||
${ACTIONS.map(
|
${ACTIONS.map(
|
||||||
(conf) => html`
|
(conf) => html`
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<span>${describeAction(this.hass, [], [], {}, conf as any)}</span>
|
<span>${describeAction(this.hass, [], conf as any)}</span>
|
||||||
<pre>${dump(conf)}</pre>
|
<pre>${dump(conf)}</pre>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import { computeInitialHaFormData } from "../../../../src/components/ha-form/com
|
|||||||
import "../../../../src/components/ha-form/ha-form";
|
import "../../../../src/components/ha-form/ha-form";
|
||||||
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
|
import type { HaFormSchema } from "../../../../src/components/ha-form/types";
|
||||||
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
|
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
|
||||||
|
import type { DeviceRegistryEntry } from "../../../../src/data/device/device_registry";
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
import { getEntity } from "../../../../src/fake_data/entity";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
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 type { DeviceRegistryEntry } from "../../../../src/data/device_registry";
|
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import "../../../../src/components/ha-selector/ha-selector";
|
|||||||
import "../../../../src/components/ha-settings-row";
|
import "../../../../src/components/ha-settings-row";
|
||||||
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
|
import type { AreaRegistryEntry } from "../../../../src/data/area_registry";
|
||||||
import type { BlueprintInput } from "../../../../src/data/blueprint";
|
import type { BlueprintInput } from "../../../../src/data/blueprint";
|
||||||
import type { DeviceRegistryEntry } from "../../../../src/data/device_registry";
|
import type { DeviceRegistryEntry } from "../../../../src/data/device/device_registry";
|
||||||
import type { FloorRegistryEntry } from "../../../../src/data/floor_registry";
|
import type { FloorRegistryEntry } from "../../../../src/data/floor_registry";
|
||||||
import type { LabelRegistryEntry } from "../../../../src/data/label_registry";
|
import type { LabelRegistryEntry } from "../../../../src/data/label/label_registry";
|
||||||
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
import { getEntity } from "../../../../src/fake_data/entity";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import type { IntegrationManifest } from "../../../../src/data/integration";
|
import type { IntegrationManifest } from "../../../../src/data/integration";
|
||||||
|
|
||||||
import type { DeviceRegistryEntry } from "../../../../src/data/device_registry";
|
import type { DeviceRegistryEntry } from "../../../../src/data/device/device_registry";
|
||||||
import type { EntityRegistryEntry } from "../../../../src/data/entity_registry";
|
import type { EntityRegistryEntry } from "../../../../src/data/entity/entity_registry";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
import "../../../../src/panels/config/integrations/ha-config-flow-card";
|
import "../../../../src/panels/config/integrations/ha-config-flow-card";
|
||||||
import type {
|
import type {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
"@fullcalendar/list": "6.1.19",
|
"@fullcalendar/list": "6.1.19",
|
||||||
"@fullcalendar/luxon3": "6.1.19",
|
"@fullcalendar/luxon3": "6.1.19",
|
||||||
"@fullcalendar/timegrid": "6.1.19",
|
"@fullcalendar/timegrid": "6.1.19",
|
||||||
"@home-assistant/webawesome": "3.0.0-ha.1",
|
"@home-assistant/webawesome": "3.0.0-ha.2",
|
||||||
"@lezer/highlight": "1.2.3",
|
"@lezer/highlight": "1.2.3",
|
||||||
"@lit-labs/motion": "1.0.9",
|
"@lit-labs/motion": "1.0.9",
|
||||||
"@lit-labs/observers": "2.0.6",
|
"@lit-labs/observers": "2.0.6",
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import {
|
|||||||
DOMAIN_ATTRIBUTES_FORMATERS,
|
DOMAIN_ATTRIBUTES_FORMATERS,
|
||||||
DOMAIN_ATTRIBUTES_UNITS,
|
DOMAIN_ATTRIBUTES_UNITS,
|
||||||
TEMPERATURE_ATTRIBUTES,
|
TEMPERATURE_ATTRIBUTES,
|
||||||
} from "../../data/entity_attributes";
|
} from "../../data/entity/entity_attributes";
|
||||||
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
|
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
|
||||||
import type { FrontendLocaleData } from "../../data/translation";
|
import type { FrontendLocaleData } from "../../data/translation";
|
||||||
import type { WeatherEntity } from "../../data/weather";
|
import type { WeatherEntity } from "../../data/weather";
|
||||||
import { getWeatherUnit } from "../../data/weather";
|
import { getWeatherUnit } from "../../data/weather";
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
|
||||||
import type {
|
import type {
|
||||||
EntityRegistryDisplayEntry,
|
EntityRegistryDisplayEntry,
|
||||||
EntityRegistryEntry,
|
EntityRegistryEntry,
|
||||||
} from "../../data/entity_registry";
|
} from "../../data/entity/entity_registry";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { computeStateName } from "./compute_state_name";
|
|
||||||
import { getDuplicates } from "../string/get_duplicates";
|
import { getDuplicates } from "../string/get_duplicates";
|
||||||
|
import { computeStateName } from "./compute_state_name";
|
||||||
|
|
||||||
export const computeDeviceName = (
|
export const computeDeviceName = (
|
||||||
device: DeviceRegistryEntry
|
device: DeviceRegistryEntry
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { HassEntity } from "home-assistant-js-websocket";
|
|||||||
import type {
|
import type {
|
||||||
EntityRegistryDisplayEntry,
|
EntityRegistryDisplayEntry,
|
||||||
EntityRegistryEntry,
|
EntityRegistryEntry,
|
||||||
} from "../../data/entity_registry";
|
} from "../../data/entity/entity_registry";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { computeDeviceName } from "./compute_device_name";
|
import { computeDeviceName } from "./compute_device_name";
|
||||||
import { computeStateName } from "./compute_state_name";
|
import { computeStateName } from "./compute_state_name";
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type { HassConfig, HassEntity } from "home-assistant-js-websocket";
|
import type { HassConfig, HassEntity } from "home-assistant-js-websocket";
|
||||||
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
|
import { UNAVAILABLE, UNKNOWN } from "../../data/entity/entity";
|
||||||
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
|
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
|
||||||
import type { FrontendLocaleData } from "../../data/translation";
|
import type { FrontendLocaleData } from "../../data/translation";
|
||||||
import { TimeZone } from "../../data/translation";
|
import { TimeZone } from "../../data/translation";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { DURATION_UNITS, formatDuration } from "../datetime/format_duration";
|
|
||||||
import { formatDate } from "../datetime/format_date";
|
import { formatDate } from "../datetime/format_date";
|
||||||
import { formatDateTime } from "../datetime/format_date_time";
|
import { formatDateTime } from "../datetime/format_date_time";
|
||||||
|
import { DURATION_UNITS, formatDuration } from "../datetime/format_duration";
|
||||||
import { formatTime } from "../datetime/format_time";
|
import { formatTime } from "../datetime/format_time";
|
||||||
import {
|
import {
|
||||||
formatNumber,
|
formatNumber,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { AreaRegistryEntry } from "../../../data/area_registry";
|
import type { AreaRegistryEntry } from "../../../data/area_registry";
|
||||||
import type { DeviceRegistryEntry } from "../../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../../data/device/device_registry";
|
||||||
import type { FloorRegistryEntry } from "../../../data/floor_registry";
|
import type { FloorRegistryEntry } from "../../../data/floor_registry";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import type { AreaRegistryEntry } from "../../../data/area_registry";
|
import type { AreaRegistryEntry } from "../../../data/area_registry";
|
||||||
import type { DeviceRegistryEntry } from "../../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../../data/device/device_registry";
|
||||||
import type {
|
import type {
|
||||||
EntityRegistryDisplayEntry,
|
EntityRegistryDisplayEntry,
|
||||||
EntityRegistryEntry,
|
EntityRegistryEntry,
|
||||||
ExtEntityRegistryEntry,
|
ExtEntityRegistryEntry,
|
||||||
} from "../../../data/entity_registry";
|
} from "../../../data/entity/entity_registry";
|
||||||
import type { FloorRegistryEntry } from "../../../data/floor_registry";
|
import type { FloorRegistryEntry } from "../../../data/floor_registry";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import type { HomeAssistant } from "../../types";
|
|
||||||
import type { IntegrationManifest } from "../../data/integration";
|
|
||||||
import { computeDomain } from "./compute_domain";
|
|
||||||
import { HELPERS_CRUD } from "../../data/helpers_crud";
|
|
||||||
import type { Helper } from "../../panels/config/helpers/const";
|
|
||||||
import { isHelperDomain } from "../../panels/config/helpers/const";
|
|
||||||
import { isComponentLoaded } from "../config/is_component_loaded";
|
|
||||||
import type { EntityRegistryEntry } from "../../data/entity_registry";
|
|
||||||
import { removeEntityRegistryEntry } from "../../data/entity_registry";
|
|
||||||
import type { ConfigEntry } from "../../data/config_entries";
|
import type { ConfigEntry } from "../../data/config_entries";
|
||||||
import { deleteConfigEntry } from "../../data/config_entries";
|
import { deleteConfigEntry } from "../../data/config_entries";
|
||||||
|
import type { EntityRegistryEntry } from "../../data/entity/entity_registry";
|
||||||
|
import { removeEntityRegistryEntry } from "../../data/entity/entity_registry";
|
||||||
|
import { HELPERS_CRUD } from "../../data/helpers_crud";
|
||||||
|
import type { IntegrationManifest } from "../../data/integration";
|
||||||
|
import type { Helper } from "../../panels/config/helpers/const";
|
||||||
|
import { isHelperDomain } from "../../panels/config/helpers/const";
|
||||||
|
import type { HomeAssistant } from "../../types";
|
||||||
|
import { isComponentLoaded } from "../config/is_component_loaded";
|
||||||
|
import { computeDomain } from "./compute_domain";
|
||||||
|
|
||||||
export const isDeletableEntity = (
|
export const isDeletableEntity = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { computeStateDomain } from "./compute_state_domain";
|
import { UNAVAILABLE_STATES } from "../../data/entity/entity";
|
||||||
import { UNAVAILABLE_STATES } from "../../data/entity";
|
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { computeDomain } from "./compute_domain";
|
|
||||||
import { stringCompare } from "../string/compare";
|
import { stringCompare } from "../string/compare";
|
||||||
|
import { computeDomain } from "./compute_domain";
|
||||||
|
import { computeStateDomain } from "./compute_state_domain";
|
||||||
|
|
||||||
export const FIXED_DOMAIN_STATES = {
|
export const FIXED_DOMAIN_STATES = {
|
||||||
alarm_control_panel: [
|
alarm_control_panel: [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { computeStateDomain } from "./compute_state_domain";
|
import { isUnavailableState, UNAVAILABLE } from "../../data/entity/entity";
|
||||||
import { isUnavailableState, UNAVAILABLE } from "../../data/entity";
|
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
|
import { computeStateDomain } from "./compute_state_domain";
|
||||||
|
|
||||||
export const computeGroupEntitiesState = (states: HassEntity[]): string => {
|
export const computeGroupEntitiesState = (states: HassEntity[]): string => {
|
||||||
if (!states.length) {
|
if (!states.length) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { isUnavailableState, OFF, UNAVAILABLE } from "../../data/entity";
|
import { isUnavailableState, OFF, UNAVAILABLE } from "../../data/entity/entity";
|
||||||
import { computeDomain } from "./compute_domain";
|
import { computeDomain } from "./compute_domain";
|
||||||
|
|
||||||
export function stateActive(stateObj: HassEntity, state?: string): boolean {
|
export function stateActive(stateObj: HassEntity, state?: string): boolean {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { UNAVAILABLE } from "../../data/entity";
|
import { UNAVAILABLE } from "../../data/entity/entity";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { DOMAINS_WITH_CARD } from "../const";
|
import { DOMAINS_WITH_CARD } from "../const";
|
||||||
import { canToggleState } from "./can_toggle_state";
|
import { canToggleState } from "./can_toggle_state";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/** Return a color representing a state. */
|
/** Return a color representing a state. */
|
||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { UNAVAILABLE } from "../../data/entity";
|
import { UNAVAILABLE } from "../../data/entity/entity";
|
||||||
import type { GroupEntity } from "../../data/group";
|
import type { GroupEntity } from "../../data/group";
|
||||||
import { computeGroupDomain } from "../../data/group";
|
import { computeGroupDomain } from "../../data/group";
|
||||||
import { computeCssVariable } from "../../resources/css-variables";
|
import { computeCssVariable } from "../../resources/css-variables";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type {
|
|||||||
HassEntity,
|
HassEntity,
|
||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
|
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
|
||||||
import type { FrontendLocaleData } from "../../data/translation";
|
import type { FrontendLocaleData } from "../../data/translation";
|
||||||
import { NumberFormat } from "../../data/translation";
|
import { NumberFormat } from "../../data/translation";
|
||||||
import { round } from "./round";
|
import { round } from "./round";
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { getGraphColorByIndex } from "../../common/color/colors";
|
|||||||
import { hex2rgb, lab2hex, rgb2lab } from "../../common/color/convert-color";
|
import { hex2rgb, lab2hex, rgb2lab } from "../../common/color/convert-color";
|
||||||
import { labBrighten } from "../../common/color/lab";
|
import { labBrighten } from "../../common/color/lab";
|
||||||
import { computeDomain } from "../../common/entity/compute_domain";
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
import { stateColorProperties } from "../../common/entity/state_color";
|
|
||||||
import { UNAVAILABLE, UNKNOWN } from "../../data/entity";
|
|
||||||
import { computeCssValue } from "../../resources/css-variables";
|
|
||||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||||
import { FIXED_DOMAIN_STATES } from "../../common/entity/get_states";
|
import { FIXED_DOMAIN_STATES } from "../../common/entity/get_states";
|
||||||
|
import { stateColorProperties } from "../../common/entity/state_color";
|
||||||
|
import { UNAVAILABLE, UNKNOWN } from "../../data/entity/entity";
|
||||||
|
import { computeCssValue } from "../../resources/css-variables";
|
||||||
|
|
||||||
const DOMAIN_STATE_SHADES: Record<string, Record<string, number>> = {
|
const DOMAIN_STATE_SHADES: Record<string, Record<string, number>> = {
|
||||||
media_player: {
|
media_player: {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { computeCssColor } from "../../common/color/compute-color";
|
|||||||
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 { stringCompare } from "../../common/string/compare";
|
import { stringCompare } from "../../common/string/compare";
|
||||||
import type { LabelRegistryEntry } from "../../data/label_registry";
|
import type { LabelRegistryEntry } from "../../data/label/label_registry";
|
||||||
import "../chips/ha-chip-set";
|
import "../chips/ha-chip-set";
|
||||||
import "../ha-dropdown";
|
import "../ha-dropdown";
|
||||||
import "../ha-dropdown-item";
|
import "../ha-dropdown-item";
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import type { DeviceAction } from "../../data/device_automation";
|
import type { DeviceAction } from "../../data/device/device_automation";
|
||||||
import {
|
import {
|
||||||
fetchDeviceActions,
|
fetchDeviceActions,
|
||||||
localizeDeviceAutomationAction,
|
localizeDeviceAutomationAction,
|
||||||
} from "../../data/device_automation";
|
} from "../../data/device/device_automation";
|
||||||
import { HaDeviceAutomationPicker } from "./ha-device-automation-picker";
|
import { HaDeviceAutomationPicker } from "./ha-device-automation-picker";
|
||||||
|
|
||||||
@customElement("ha-device-action-picker")
|
@customElement("ha-device-action-picker")
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ import { consume } from "@lit/context";
|
|||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { property, state } from "lit/decorators";
|
import { property, state } 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 { fullEntitiesContext } from "../../data/context";
|
import { fullEntitiesContext } from "../../data/context";
|
||||||
import type { DeviceAutomation } from "../../data/device_automation";
|
import type { DeviceAutomation } from "../../data/device/device_automation";
|
||||||
import {
|
import {
|
||||||
deviceAutomationsEqual,
|
deviceAutomationsEqual,
|
||||||
sortDeviceAutomations,
|
sortDeviceAutomations,
|
||||||
} from "../../data/device_automation";
|
} from "../../data/device/device_automation";
|
||||||
import type { EntityRegistryEntry } from "../../data/entity_registry";
|
import type { EntityRegistryEntry } from "../../data/entity/entity_registry";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "../ha-md-select-option";
|
|
||||||
import "../ha-md-select";
|
import "../ha-md-select";
|
||||||
import { stopPropagation } from "../../common/dom/stop_propagation";
|
import "../ha-md-select-option";
|
||||||
|
|
||||||
const NO_AUTOMATION_KEY = "NO_AUTOMATION";
|
const NO_AUTOMATION_KEY = "NO_AUTOMATION";
|
||||||
const UNKNOWN_AUTOMATION_KEY = "UNKNOWN_AUTOMATION";
|
const UNKNOWN_AUTOMATION_KEY = "UNKNOWN_AUTOMATION";
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import type { DeviceCondition } from "../../data/device_automation";
|
import type { DeviceCondition } from "../../data/device/device_automation";
|
||||||
import {
|
import {
|
||||||
fetchDeviceConditions,
|
fetchDeviceConditions,
|
||||||
localizeDeviceAutomationCondition,
|
localizeDeviceAutomationCondition,
|
||||||
} from "../../data/device_automation";
|
} from "../../data/device/device_automation";
|
||||||
import { HaDeviceAutomationPicker } from "./ha-device-automation-picker";
|
import { HaDeviceAutomationPicker } from "./ha-device-automation-picker";
|
||||||
|
|
||||||
@customElement("ha-device-condition-picker")
|
@customElement("ha-device-condition-picker")
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import {
|
|||||||
deviceComboBoxKeys,
|
deviceComboBoxKeys,
|
||||||
getDevices,
|
getDevices,
|
||||||
type DevicePickerItem,
|
type DevicePickerItem,
|
||||||
type DeviceRegistryEntry,
|
} from "../../data/device/device_picker";
|
||||||
} from "../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { brandsUrl } from "../../util/brands-url";
|
import { brandsUrl } from "../../util/brands-url";
|
||||||
import "../ha-generic-picker";
|
import "../ha-generic-picker";
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import type { DeviceTrigger } from "../../data/device_automation";
|
import type { DeviceTrigger } from "../../data/device/device_automation";
|
||||||
import {
|
import {
|
||||||
fetchDeviceTriggers,
|
fetchDeviceTriggers,
|
||||||
localizeDeviceAutomationTrigger,
|
localizeDeviceAutomationTrigger,
|
||||||
} from "../../data/device_automation";
|
} from "../../data/device/device_automation";
|
||||||
import { HaDeviceAutomationPicker } from "./ha-device-automation-picker";
|
import { HaDeviceAutomationPicker } from "./ha-device-automation-picker";
|
||||||
|
|
||||||
@customElement("ha-device-trigger-picker")
|
@customElement("ha-device-trigger-picker")
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { customElement, property } from "lit/decorators";
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { isValidEntityId } from "../../common/entity/valid_entity_id";
|
import { isValidEntityId } from "../../common/entity/valid_entity_id";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity";
|
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity/entity";
|
||||||
import type { HomeAssistant, ValueChangedEvent } from "../../types";
|
import type { HomeAssistant, ValueChangedEvent } from "../../types";
|
||||||
import "../ha-sortable";
|
import "../ha-sortable";
|
||||||
import "./ha-entity-picker";
|
import "./ha-entity-picker";
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ import { fireEvent } from "../../common/dom/fire_event";
|
|||||||
import { computeEntityNameList } from "../../common/entity/compute_entity_name_display";
|
import { computeEntityNameList } from "../../common/entity/compute_entity_name_display";
|
||||||
import { isValidEntityId } from "../../common/entity/valid_entity_id";
|
import { isValidEntityId } from "../../common/entity/valid_entity_id";
|
||||||
import { computeRTL } from "../../common/util/compute_rtl";
|
import { computeRTL } from "../../common/util/compute_rtl";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity";
|
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity/entity";
|
||||||
import {
|
import {
|
||||||
entityComboBoxKeys,
|
entityComboBoxKeys,
|
||||||
getEntities,
|
getEntities,
|
||||||
type EntityComboBoxItem,
|
type EntityComboBoxItem,
|
||||||
} from "../../data/entity_registry";
|
} from "../../data/entity/entity_picker";
|
||||||
import { domainToName } from "../../data/integration";
|
import { domainToName } from "../../data/integration";
|
||||||
import {
|
import {
|
||||||
isHelperDomain,
|
isHelperDomain,
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { STATES_OFF } from "../../common/const";
|
import { STATES_OFF } from "../../common/const";
|
||||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import { UNAVAILABLE, UNKNOWN, isUnavailableState } from "../../data/entity";
|
import {
|
||||||
|
UNAVAILABLE,
|
||||||
|
UNKNOWN,
|
||||||
|
isUnavailableState,
|
||||||
|
} from "../../data/entity/entity";
|
||||||
import { forwardHaptic } from "../../data/haptics";
|
import { forwardHaptic } from "../../data/haptics";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "../ha-formfield";
|
import "../ha-formfield";
|
||||||
|
|||||||
@@ -14,8 +14,12 @@ import {
|
|||||||
getNumberFormatOptions,
|
getNumberFormatOptions,
|
||||||
isNumericState,
|
isNumericState,
|
||||||
} from "../../common/number/format_number";
|
} from "../../common/number/format_number";
|
||||||
import { isUnavailableState, UNAVAILABLE, UNKNOWN } from "../../data/entity";
|
import {
|
||||||
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
|
isUnavailableState,
|
||||||
|
UNAVAILABLE,
|
||||||
|
UNKNOWN,
|
||||||
|
} from "../../data/entity/entity";
|
||||||
|
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
|
||||||
import { timerTimeRemaining } from "../../data/timer";
|
import { timerTimeRemaining } from "../../data/timer";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "../ha-label-badge";
|
import "../ha-label-badge";
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import { createAreaRegistryEntry } from "../data/area_registry";
|
|||||||
import type {
|
import type {
|
||||||
DeviceEntityDisplayLookup,
|
DeviceEntityDisplayLookup,
|
||||||
DeviceRegistryEntry,
|
DeviceRegistryEntry,
|
||||||
} from "../data/device_registry";
|
} from "../data/device/device_registry";
|
||||||
import { getDeviceEntityDisplayLookup } from "../data/device_registry";
|
import { getDeviceEntityDisplayLookup } from "../data/device/device_registry";
|
||||||
import type { EntityRegistryDisplayEntry } from "../data/entity_registry";
|
import type { EntityRegistryDisplayEntry } from "../data/entity/entity_registry";
|
||||||
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
||||||
import { showAreaRegistryDetailDialog } from "../panels/config/areas/show-dialog-area-registry-detail";
|
import { showAreaRegistryDetailDialog } from "../panels/config/areas/show-dialog-area-registry-detail";
|
||||||
import type { HomeAssistant, ValueChangedEvent } from "../types";
|
import type { HomeAssistant, ValueChangedEvent } from "../types";
|
||||||
@@ -296,7 +296,6 @@ export class HaAreaPicker extends LitElement {
|
|||||||
secondary: floorName,
|
secondary: floorName,
|
||||||
icon: area.icon || undefined,
|
icon: area.icon || undefined,
|
||||||
icon_path: area.icon ? undefined : mdiTextureBox,
|
icon_path: area.icon ? undefined : mdiTextureBox,
|
||||||
sorting_label: areaName,
|
|
||||||
search_labels: {
|
search_labels: {
|
||||||
areaName: areaName || null,
|
areaName: areaName || null,
|
||||||
floorName: floorName || null,
|
floorName: floorName || null,
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ import type { CSSResultGroup, PropertyValues } from "lit";
|
|||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { computeAttributeNameDisplay } from "../common/entity/compute_attribute_display";
|
import { computeAttributeNameDisplay } from "../common/entity/compute_attribute_display";
|
||||||
|
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||||
import {
|
import {
|
||||||
STATE_ATTRIBUTES,
|
STATE_ATTRIBUTES,
|
||||||
STATE_ATTRIBUTES_DOMAIN_CLASS,
|
STATE_ATTRIBUTES_DOMAIN_CLASS,
|
||||||
} from "../data/entity_attributes";
|
} from "../data/entity/entity_attributes";
|
||||||
import { haStyle } from "../resources/styles";
|
import { haStyle } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import "./ha-attribute-value";
|
import "./ha-attribute-value";
|
||||||
import "./ha-expansion-panel";
|
import "./ha-expansion-panel";
|
||||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
|
||||||
|
|
||||||
@customElement("ha-attributes")
|
@customElement("ha-attributes")
|
||||||
class HaAttributes extends LitElement {
|
class HaAttributes extends LitElement {
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ export class HaAutomationRow extends LitElement {
|
|||||||
<slot name="leading-icon"></slot>
|
<slot name="leading-icon"></slot>
|
||||||
</div>
|
</div>
|
||||||
<slot class="header" name="header"></slot>
|
<slot class="header" name="header"></slot>
|
||||||
<slot name="icons"></slot>
|
<div class="icons">
|
||||||
|
<slot name="icons"></slot>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -118,9 +120,9 @@ export class HaAutomationRow extends LitElement {
|
|||||||
}
|
}
|
||||||
.row {
|
.row {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: var(--ha-space-0) var(--ha-space-2);
|
padding: 0 var(--ha-space-3);
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-weight: var(--ha-font-weight-medium);
|
font-weight: var(--ha-font-weight-medium);
|
||||||
@@ -145,6 +147,9 @@ export class HaAutomationRow extends LitElement {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
}
|
}
|
||||||
|
.leading-icon-wrapper {
|
||||||
|
padding-top: var(--ha-space-3);
|
||||||
|
}
|
||||||
::slotted([slot="leading-icon"]) {
|
::slotted([slot="leading-icon"]) {
|
||||||
color: var(--ha-color-on-neutral-quiet);
|
color: var(--ha-color-on-neutral-quiet);
|
||||||
}
|
}
|
||||||
@@ -172,6 +177,10 @@ export class HaAutomationRow extends LitElement {
|
|||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
margin: var(--ha-space-0) var(--ha-space-3);
|
margin: var(--ha-space-0) var(--ha-space-3);
|
||||||
}
|
}
|
||||||
|
.icons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
:host([sort-selected]) .row {
|
:host([sort-selected]) .row {
|
||||||
outline: solid;
|
outline: solid;
|
||||||
outline-color: rgba(var(--rgb-accent-color), 0.6);
|
outline-color: rgba(var(--rgb-accent-color), 0.6);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { css, html, LitElement, nothing } from "lit";
|
|||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import type { ClimateEntity } from "../data/climate";
|
import type { ClimateEntity } from "../data/climate";
|
||||||
import { CLIMATE_PRESET_NONE } from "../data/climate";
|
import { CLIMATE_PRESET_NONE } from "../data/climate";
|
||||||
import { isUnavailableState, OFF } from "../data/entity";
|
import { isUnavailableState, OFF } from "../data/entity/entity";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
|
||||||
@customElement("ha-climate-state")
|
@customElement("ha-climate-state")
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ import type { ConfigEntry, SubEntry } from "../data/config_entries";
|
|||||||
import { getConfigEntry, getSubEntries } from "../data/config_entries";
|
import { getConfigEntry, getSubEntries } from "../data/config_entries";
|
||||||
import type { Agent } from "../data/conversation";
|
import type { Agent } from "../data/conversation";
|
||||||
import { listAgents } from "../data/conversation";
|
import { listAgents } from "../data/conversation";
|
||||||
|
import { getExtendedEntityRegistryEntry } from "../data/entity/entity_registry";
|
||||||
import { fetchIntegrationManifest } from "../data/integration";
|
import { fetchIntegrationManifest } from "../data/integration";
|
||||||
import { showOptionsFlowDialog } from "../dialogs/config-flow/show-dialog-options-flow";
|
import { showOptionsFlowDialog } from "../dialogs/config-flow/show-dialog-options-flow";
|
||||||
|
import { showSubConfigFlowDialog } from "../dialogs/config-flow/show-dialog-sub-config-flow";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import "./ha-list-item";
|
import "./ha-list-item";
|
||||||
import "./ha-select";
|
import "./ha-select";
|
||||||
import type { HaSelect } from "./ha-select";
|
import type { HaSelect } from "./ha-select";
|
||||||
import { getExtendedEntityRegistryEntry } from "../data/entity_registry";
|
|
||||||
import { showSubConfigFlowDialog } from "../dialogs/config-flow/show-dialog-sub-config-flow";
|
|
||||||
|
|
||||||
const NONE = "__NONE_OPTION__";
|
const NONE = "__NONE_OPTION__";
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export class HaDomainIcon extends LitElement {
|
|||||||
if (icn) {
|
if (icn) {
|
||||||
return html`<ha-icon .icon=${icn}></ha-icon>`;
|
return html`<ha-icon .icon=${icn}></ha-icon>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._renderFallback();
|
return this._renderFallback();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import DropdownItem from "@home-assistant/webawesome/dist/components/dropdown-item/dropdown-item";
|
import DropdownItem from "@home-assistant/webawesome/dist/components/dropdown-item/dropdown-item";
|
||||||
import { css, type CSSResultGroup } from "lit";
|
import "@home-assistant/webawesome/dist/components/icon/icon";
|
||||||
|
import { css, type CSSResultGroup, html } from "lit";
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
|
import "./ha-svg-icon";
|
||||||
|
import { mdiCheckboxBlankOutline, mdiCheckboxMarked } from "@mdi/js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Home Assistant dropdown item component
|
* Home Assistant dropdown item component
|
||||||
@@ -14,6 +17,16 @@ import { customElement } from "lit/decorators";
|
|||||||
*/
|
*/
|
||||||
@customElement("ha-dropdown-item")
|
@customElement("ha-dropdown-item")
|
||||||
export class HaDropdownItem extends DropdownItem {
|
export class HaDropdownItem extends DropdownItem {
|
||||||
|
protected renderCheckboxIcon() {
|
||||||
|
return html`
|
||||||
|
<ha-svg-icon
|
||||||
|
id="check"
|
||||||
|
part="checkmark"
|
||||||
|
.path=${this.checked ? mdiCheckboxMarked : mdiCheckboxBlankOutline}
|
||||||
|
></ha-svg-icon>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
DropdownItem.styles,
|
DropdownItem.styles,
|
||||||
@@ -22,6 +35,10 @@ export class HaDropdownItem extends DropdownItem {
|
|||||||
min-height: var(--ha-space-10);
|
min-height: var(--ha-space-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#check {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
#icon ::slotted(*) {
|
#icon ::slotted(*) {
|
||||||
color: var(--ha-color-on-neutral-normal);
|
color: var(--ha-color-on-neutral-normal);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { computeCssColor } from "../common/color/compute-color";
|
|||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { navigate } from "../common/navigate";
|
import { navigate } from "../common/navigate";
|
||||||
import { stringCompare } from "../common/string/compare";
|
import { stringCompare } from "../common/string/compare";
|
||||||
import type { LabelRegistryEntry } from "../data/label_registry";
|
import type { LabelRegistryEntry } from "../data/label/label_registry";
|
||||||
import { subscribeLabelRegistry } from "../data/label_registry";
|
import { subscribeLabelRegistry } from "../data/label/label_registry";
|
||||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||||
import { haStyleScrollbar } from "../resources/styles";
|
import { haStyleScrollbar } from "../resources/styles";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import { updateAreaRegistryEntry } from "../data/area_registry";
|
|||||||
import type {
|
import type {
|
||||||
DeviceEntityDisplayLookup,
|
DeviceEntityDisplayLookup,
|
||||||
DeviceRegistryEntry,
|
DeviceRegistryEntry,
|
||||||
} from "../data/device_registry";
|
} from "../data/device/device_registry";
|
||||||
import { getDeviceEntityDisplayLookup } from "../data/device_registry";
|
import { getDeviceEntityDisplayLookup } from "../data/device/device_registry";
|
||||||
import type { EntityRegistryDisplayEntry } from "../data/entity_registry";
|
import type { EntityRegistryDisplayEntry } from "../data/entity/entity_registry";
|
||||||
import {
|
import {
|
||||||
createFloorRegistryEntry,
|
createFloorRegistryEntry,
|
||||||
getFloorAreaLookup,
|
getFloorAreaLookup,
|
||||||
@@ -291,7 +291,6 @@ export class HaFloorPicker extends LitElement {
|
|||||||
id: floor.floor_id,
|
id: floor.floor_id,
|
||||||
primary: floorName,
|
primary: floorName,
|
||||||
floor: floor,
|
floor: floor,
|
||||||
sorting_label: floor.level?.toString() || "zzzzz",
|
|
||||||
search_labels: {
|
search_labels: {
|
||||||
floorName,
|
floorName,
|
||||||
floor_id: floor.floor_id,
|
floor_id: floor.floor_id,
|
||||||
|
|||||||
@@ -367,7 +367,10 @@ export class HaGenericPicker extends LitElement {
|
|||||||
|
|
||||||
wa-popover::part(body) {
|
wa-popover::part(body) {
|
||||||
width: max(var(--body-width), 250px);
|
width: max(var(--body-width), 250px);
|
||||||
max-width: max(var(--body-width), 250px);
|
max-width: var(
|
||||||
|
--ha-generic-picker-max-width,
|
||||||
|
max(var(--body-width), 250px)
|
||||||
|
);
|
||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
height: 70vh;
|
height: 70vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { TemplateResult } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
import { css, html, LitElement } from "lit";
|
import { css, html, LitElement } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import { isUnavailableState, OFF } from "../data/entity";
|
import { isUnavailableState, OFF } from "../data/entity/entity";
|
||||||
import type { HumidifierEntity } from "../data/humidifier";
|
import type { HumidifierEntity } from "../data/humidifier";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,12 @@ import {
|
|||||||
} from "lit/decorators";
|
} from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import type { LabelRegistryEntry } from "../data/label_registry";
|
import { getLabels, labelComboBoxKeys } from "../data/label/label_picker";
|
||||||
import {
|
import {
|
||||||
createLabelRegistryEntry,
|
createLabelRegistryEntry,
|
||||||
getLabels,
|
|
||||||
labelComboBoxKeys,
|
|
||||||
subscribeLabelRegistry,
|
subscribeLabelRegistry,
|
||||||
} from "../data/label_registry";
|
type LabelRegistryEntry,
|
||||||
|
} from "../data/label/label_registry";
|
||||||
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
||||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||||
import { showLabelDetailDialog } from "../panels/config/labels/show-dialog-label-detail";
|
import { showLabelDetailDialog } from "../panels/config/labels/show-dialog-label-detail";
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import memoizeOne from "memoize-one";
|
|||||||
import { computeCssColor } from "../common/color/compute-color";
|
import { computeCssColor } from "../common/color/compute-color";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { stringCompare } from "../common/string/compare";
|
import { stringCompare } from "../common/string/compare";
|
||||||
import type { LabelRegistryEntry } from "../data/label_registry";
|
import type { LabelRegistryEntry } from "../data/label/label_registry";
|
||||||
import {
|
import {
|
||||||
subscribeLabelRegistry,
|
subscribeLabelRegistry,
|
||||||
updateLabelRegistryEntry,
|
updateLabelRegistryEntry,
|
||||||
} from "../data/label_registry";
|
} from "../data/label/label_registry";
|
||||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||||
import { showLabelDetailDialog } from "../panels/config/labels/show-dialog-label-detail";
|
import { showLabelDetailDialog } from "../panels/config/labels/show-dialog-label-detail";
|
||||||
import type { HomeAssistant, ValueChangedEvent } from "../types";
|
import type { HomeAssistant, ValueChangedEvent } from "../types";
|
||||||
|
|||||||
@@ -288,13 +288,30 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
|
|||||||
let items = [...this.getItems(this._search, this.selectedSection)];
|
let items = [...this.getItems(this._search, this.selectedSection)];
|
||||||
|
|
||||||
if (!this.sections?.length) {
|
if (!this.sections?.length) {
|
||||||
items = items.sort((entityA, entityB) =>
|
items = items.sort((entityA, entityB) => {
|
||||||
caseInsensitiveStringCompare(
|
const sortLabelA =
|
||||||
(entityA as PickerComboBoxItem).sorting_label!,
|
typeof entityA === "string" ? entityA : entityA.sorting_label;
|
||||||
(entityB as PickerComboBoxItem).sorting_label!,
|
const sortLabelB =
|
||||||
|
typeof entityB === "string" ? entityB : entityB.sorting_label;
|
||||||
|
|
||||||
|
if (!sortLabelA || !sortLabelB) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sortLabelB) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sortLabelA) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return caseInsensitiveStringCompare(
|
||||||
|
sortLabelA,
|
||||||
|
sortLabelB,
|
||||||
this.hass?.locale.language ?? navigator.language
|
this.hass?.locale.language ?? navigator.language
|
||||||
)
|
);
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!items.length) {
|
if (!items.length) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { fullEntitiesContext } from "../../data/context";
|
|||||||
import {
|
import {
|
||||||
subscribeEntityRegistry,
|
subscribeEntityRegistry,
|
||||||
type EntityRegistryEntry,
|
type EntityRegistryEntry,
|
||||||
} from "../../data/entity_registry";
|
} from "../../data/entity/entity_registry";
|
||||||
import type { Action } from "../../data/script";
|
import type { Action } from "../../data/script";
|
||||||
import { migrateAutomationAction } from "../../data/script";
|
import { migrateAutomationAction } from "../../data/script";
|
||||||
import type { ActionSelector } from "../../data/selector";
|
import type { ActionSelector } from "../../data/selector";
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { html, LitElement, nothing } from "lit";
|
|||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { ensureArray } from "../../common/array/ensure-array";
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
|
||||||
import { getDeviceIntegrationLookup } from "../../data/device_registry";
|
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import type { EntitySources } from "../../data/entity_sources";
|
|
||||||
import { fetchEntitySourcesWithCache } from "../../data/entity_sources";
|
|
||||||
import type { AreaSelector } from "../../data/selector";
|
|
||||||
import type { ConfigEntry } from "../../data/config_entries";
|
import type { ConfigEntry } from "../../data/config_entries";
|
||||||
import { getConfigEntries } from "../../data/config_entries";
|
import { getConfigEntries } from "../../data/config_entries";
|
||||||
|
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
|
||||||
|
import { getDeviceIntegrationLookup } from "../../data/device/device_registry";
|
||||||
|
import type { EntitySources } from "../../data/entity/entity_sources";
|
||||||
|
import { fetchEntitySourcesWithCache } from "../../data/entity/entity_sources";
|
||||||
|
import type { AreaSelector } from "../../data/selector";
|
||||||
import {
|
import {
|
||||||
filterSelectorDevices,
|
filterSelectorDevices,
|
||||||
filterSelectorEntities,
|
filterSelectorEntities,
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { ensureArray } from "../../common/array/ensure-array";
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
|
||||||
import { getDeviceIntegrationLookup } from "../../data/device_registry";
|
|
||||||
import type { EntitySources } from "../../data/entity_sources";
|
|
||||||
import { fetchEntitySourcesWithCache } from "../../data/entity_sources";
|
|
||||||
import type { DeviceSelector } from "../../data/selector";
|
|
||||||
import type { ConfigEntry } from "../../data/config_entries";
|
import type { ConfigEntry } from "../../data/config_entries";
|
||||||
import { getConfigEntries } from "../../data/config_entries";
|
import { getConfigEntries } from "../../data/config_entries";
|
||||||
|
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
|
||||||
|
import { getDeviceIntegrationLookup } from "../../data/device/device_registry";
|
||||||
|
import type { EntitySources } from "../../data/entity/entity_sources";
|
||||||
|
import { fetchEntitySourcesWithCache } from "../../data/entity/entity_sources";
|
||||||
|
import type { DeviceSelector } from "../../data/selector";
|
||||||
import {
|
import {
|
||||||
filterSelectorDevices,
|
filterSelectorDevices,
|
||||||
filterSelectorEntities,
|
filterSelectorEntities,
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import { html, LitElement, nothing } from "lit";
|
|||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { ensureArray } from "../../common/array/ensure-array";
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import type { EntitySources } from "../../data/entity_sources";
|
import type { EntitySources } from "../../data/entity/entity_sources";
|
||||||
import { fetchEntitySourcesWithCache } from "../../data/entity_sources";
|
import { fetchEntitySourcesWithCache } from "../../data/entity/entity_sources";
|
||||||
import type { EntitySelector } from "../../data/selector";
|
import type { EntitySelector } from "../../data/selector";
|
||||||
import {
|
import {
|
||||||
filterSelectorEntities,
|
|
||||||
computeCreateDomains,
|
computeCreateDomains,
|
||||||
|
filterSelectorEntities,
|
||||||
} from "../../data/selector";
|
} from "../../data/selector";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "../entity/ha-entities-picker";
|
import "../entity/ha-entities-picker";
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { html, LitElement, nothing } from "lit";
|
|||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { ensureArray } from "../../common/array/ensure-array";
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
|
||||||
import { getDeviceIntegrationLookup } from "../../data/device_registry";
|
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import type { EntitySources } from "../../data/entity_sources";
|
|
||||||
import { fetchEntitySourcesWithCache } from "../../data/entity_sources";
|
|
||||||
import type { FloorSelector } from "../../data/selector";
|
|
||||||
import type { ConfigEntry } from "../../data/config_entries";
|
import type { ConfigEntry } from "../../data/config_entries";
|
||||||
import { getConfigEntries } from "../../data/config_entries";
|
import { getConfigEntries } from "../../data/config_entries";
|
||||||
|
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
|
||||||
|
import { getDeviceIntegrationLookup } from "../../data/device/device_registry";
|
||||||
|
import type { EntitySources } from "../../data/entity/entity_sources";
|
||||||
|
import { fetchEntitySourcesWithCache } from "../../data/entity/entity_sources";
|
||||||
|
import type { FloorSelector } from "../../data/selector";
|
||||||
import {
|
import {
|
||||||
filterSelectorDevices,
|
filterSelectorDevices,
|
||||||
filterSelectorEntities,
|
filterSelectorEntities,
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ import { css, html, LitElement, nothing } from "lit";
|
|||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { ensureArray } from "../../common/array/ensure-array";
|
import { ensureArray } from "../../common/array/ensure-array";
|
||||||
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
|
||||||
import { getDeviceIntegrationLookup } from "../../data/device_registry";
|
import { getDeviceIntegrationLookup } from "../../data/device/device_registry";
|
||||||
import type { EntitySources } from "../../data/entity_sources";
|
import type { EntitySources } from "../../data/entity/entity_sources";
|
||||||
import { fetchEntitySourcesWithCache } from "../../data/entity_sources";
|
import { fetchEntitySourcesWithCache } from "../../data/entity/entity_sources";
|
||||||
import type { TargetSelector } from "../../data/selector";
|
import type { TargetSelector } from "../../data/selector";
|
||||||
import {
|
import {
|
||||||
|
computeCreateDomains,
|
||||||
filterSelectorDevices,
|
filterSelectorDevices,
|
||||||
filterSelectorEntities,
|
filterSelectorEntities,
|
||||||
computeCreateDomains,
|
|
||||||
} from "../../data/selector";
|
} from "../../data/selector";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "../ha-target-picker";
|
import "../ha-target-picker";
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ interface ServiceComboBoxItem extends PickerComboBoxItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SEARCH_KEYS = [
|
const SEARCH_KEYS = [
|
||||||
{ name: "name", weight: 10 },
|
{ name: "search_labels.name", weight: 10 },
|
||||||
{ name: "description", weight: 8 },
|
{ name: "search_labels.description", weight: 8 },
|
||||||
{ name: "domainName", weight: 6 },
|
{ name: "search_labels.domainName", weight: 6 },
|
||||||
{ name: "serviceId", weight: 3 },
|
{ name: "search_labels.serviceId", weight: 3 },
|
||||||
];
|
];
|
||||||
|
|
||||||
@customElement("ha-service-picker")
|
@customElement("ha-service-picker")
|
||||||
|
|||||||
@@ -13,32 +13,30 @@ import memoizeOne from "memoize-one";
|
|||||||
import { ensureArray } from "../common/array/ensure-array";
|
import { ensureArray } from "../common/array/ensure-array";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { isValidEntityId } from "../common/entity/valid_entity_id";
|
import { isValidEntityId } from "../common/entity/valid_entity_id";
|
||||||
|
import { caseInsensitiveStringCompare } from "../common/string/compare";
|
||||||
import { computeRTL } from "../common/util/compute_rtl";
|
import { computeRTL } from "../common/util/compute_rtl";
|
||||||
import {
|
import {
|
||||||
areaFloorComboBoxKeys,
|
areaFloorComboBoxKeys,
|
||||||
getAreasAndFloors,
|
getAreasAndFloors,
|
||||||
type AreaFloorValue,
|
type AreaFloorValue,
|
||||||
type FloorComboBoxItem,
|
type FloorComboBoxItem,
|
||||||
} from "../data/area_floor";
|
} from "../data/area_floor_picker";
|
||||||
import { getConfigEntries, type ConfigEntry } from "../data/config_entries";
|
import { getConfigEntries, type ConfigEntry } from "../data/config_entries";
|
||||||
import { labelsContext } from "../data/context";
|
import { labelsContext } from "../data/context";
|
||||||
import {
|
import {
|
||||||
deviceComboBoxKeys,
|
deviceComboBoxKeys,
|
||||||
getDevices,
|
getDevices,
|
||||||
type DevicePickerItem,
|
type DevicePickerItem,
|
||||||
} from "../data/device_registry";
|
} from "../data/device/device_picker";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "../data/entity";
|
import type { HaEntityPickerEntityFilterFunc } from "../data/entity/entity";
|
||||||
import {
|
import {
|
||||||
entityComboBoxKeys,
|
entityComboBoxKeys,
|
||||||
getEntities,
|
getEntities,
|
||||||
type EntityComboBoxItem,
|
type EntityComboBoxItem,
|
||||||
} from "../data/entity_registry";
|
} from "../data/entity/entity_picker";
|
||||||
import { domainToName } from "../data/integration";
|
import { domainToName } from "../data/integration";
|
||||||
import {
|
import { getLabels, labelComboBoxKeys } from "../data/label/label_picker";
|
||||||
getLabels,
|
import type { LabelRegistryEntry } from "../data/label/label_registry";
|
||||||
labelComboBoxKeys,
|
|
||||||
type LabelRegistryEntry,
|
|
||||||
} from "../data/label_registry";
|
|
||||||
import {
|
import {
|
||||||
areaMeetsFilter,
|
areaMeetsFilter,
|
||||||
deviceMeetsFilter,
|
deviceMeetsFilter,
|
||||||
@@ -745,7 +743,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
: undefined,
|
: undefined,
|
||||||
undefined,
|
undefined,
|
||||||
`entity${SEPARATOR}`
|
`entity${SEPARATOR}`
|
||||||
);
|
).sort(this._sortBySortingLabel);
|
||||||
|
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
entityItems = this._filterGroup(
|
entityItems = this._filterGroup(
|
||||||
@@ -778,7 +776,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
: undefined,
|
: undefined,
|
||||||
undefined,
|
undefined,
|
||||||
`device${SEPARATOR}`
|
`device${SEPARATOR}`
|
||||||
);
|
).sort(this._sortBySortingLabel);
|
||||||
|
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
deviceItems = this._filterGroup(
|
deviceItems = this._filterGroup(
|
||||||
@@ -864,7 +862,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
entityFilter,
|
entityFilter,
|
||||||
targetValue?.label_id ? ensureArray(targetValue.label_id) : undefined,
|
targetValue?.label_id ? ensureArray(targetValue.label_id) : undefined,
|
||||||
`label${SEPARATOR}`
|
`label${SEPARATOR}`
|
||||||
);
|
).sort(this._sortBySortingLabel);
|
||||||
|
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
labels = this._filterGroup(
|
labels = this._filterGroup(
|
||||||
@@ -964,10 +962,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
let hasFloor = false;
|
let hasFloor = false;
|
||||||
let rtl = false;
|
let rtl = false;
|
||||||
let showEntityId = false;
|
let showEntityId = false;
|
||||||
|
|
||||||
if (type === "area" || type === "floor") {
|
if (type === "area" || type === "floor") {
|
||||||
item.id = item[type]?.[`${type}_id`];
|
|
||||||
|
|
||||||
rtl = computeRTL(this.hass);
|
rtl = computeRTL(this.hass);
|
||||||
hasFloor =
|
hasFloor =
|
||||||
type === "area" && !!(item as FloorComboBoxItem).area?.floor_id;
|
type === "area" && !!(item as FloorComboBoxItem).area?.floor_id;
|
||||||
@@ -1073,6 +1068,13 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
term: html`<b>‘${search}’</b>`,
|
term: html`<b>‘${search}’</b>`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
private _sortBySortingLabel = (entityA, entityB) =>
|
||||||
|
caseInsensitiveStringCompare(
|
||||||
|
(entityA as PickerComboBoxItem).sorting_label!,
|
||||||
|
(entityB as PickerComboBoxItem).sorting_label!,
|
||||||
|
this.hass?.locale.language ?? navigator.language
|
||||||
|
);
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
.add-target-wrapper {
|
.add-target-wrapper {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export class HaToast extends Snackbar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mdc-snackbar {
|
.mdc-snackbar {
|
||||||
|
z-index: 10;
|
||||||
margin: 8px;
|
margin: 8px;
|
||||||
right: calc(8px + var(--safe-area-inset-right));
|
right: calc(8px + var(--safe-area-inset-right));
|
||||||
bottom: calc(8px + var(--safe-area-inset-bottom));
|
bottom: calc(8px + var(--safe-area-inset-bottom));
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { fireEvent } from "../../common/dom/fire_event";
|
|||||||
import { computeDomain } from "../../common/entity/compute_domain";
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import { supportsFeature } from "../../common/entity/supports-feature";
|
import { supportsFeature } from "../../common/entity/supports-feature";
|
||||||
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
|
import type { EntityRegistryDisplayEntry } from "../../data/entity/entity_registry";
|
||||||
import { extractApiErrorMessage } from "../../data/hassio/common";
|
import { extractApiErrorMessage } from "../../data/hassio/common";
|
||||||
import {
|
import {
|
||||||
type MediaPlayerEntity,
|
type MediaPlayerEntity,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { until } from "lit/directives/until";
|
|||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import { slugify } from "../../common/string/slugify";
|
import { slugify } from "../../common/string/slugify";
|
||||||
import { debounce } from "../../common/util/debounce";
|
import { debounce } from "../../common/util/debounce";
|
||||||
import { isUnavailableState } from "../../data/entity";
|
import { isUnavailableState } from "../../data/entity/entity";
|
||||||
import type {
|
import type {
|
||||||
MediaPickedEvent,
|
MediaPickedEvent,
|
||||||
MediaPlayerBrowseAction,
|
MediaPlayerBrowseAction,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "../../../data/entity";
|
import type { HaEntityPickerEntityFilterFunc } from "../../../data/entity/entity";
|
||||||
import type { TargetType } from "../../../data/target";
|
import type { TargetType } from "../../../data/target";
|
||||||
import type { HaDevicePickerDeviceFilterFunc } from "../../device/ha-device-picker";
|
import type { HaDevicePickerDeviceFilterFunc } from "../../device/ha-device-picker";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity";
|
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity/entity";
|
||||||
import type { TargetType, TargetTypeFloorless } from "../../data/target";
|
import type { TargetType, TargetTypeFloorless } from "../../data/target";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import type { HaDevicePickerDeviceFilterFunc } from "../device/ha-device-picker";
|
import type { HaDevicePickerDeviceFilterFunc } from "../device/ha-device-picker";
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ import { computeRTL } from "../../common/util/compute_rtl";
|
|||||||
import type { AreaRegistryEntry } from "../../data/area_registry";
|
import type { AreaRegistryEntry } from "../../data/area_registry";
|
||||||
import { getConfigEntry } from "../../data/config_entries";
|
import { getConfigEntry } from "../../data/config_entries";
|
||||||
import { labelsContext } from "../../data/context";
|
import { labelsContext } from "../../data/context";
|
||||||
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../data/device/device_registry";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity";
|
import type { HaEntityPickerEntityFilterFunc } from "../../data/entity/entity";
|
||||||
import type { FloorRegistryEntry } from "../../data/floor_registry";
|
import type { FloorRegistryEntry } from "../../data/floor_registry";
|
||||||
import { domainToName } from "../../data/integration";
|
import { domainToName } from "../../data/integration";
|
||||||
import type { LabelRegistryEntry } from "../../data/label_registry";
|
import type { LabelRegistryEntry } from "../../data/label/label_registry";
|
||||||
import {
|
import {
|
||||||
areaMeetsFilter,
|
areaMeetsFilter,
|
||||||
deviceMeetsFilter,
|
deviceMeetsFilter,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { slugify } from "../../common/string/slugify";
|
|||||||
import { getConfigEntry } from "../../data/config_entries";
|
import { getConfigEntry } from "../../data/config_entries";
|
||||||
import { labelsContext } from "../../data/context";
|
import { labelsContext } from "../../data/context";
|
||||||
import { domainToName } from "../../data/integration";
|
import { domainToName } from "../../data/integration";
|
||||||
import type { LabelRegistryEntry } from "../../data/label_registry";
|
import type { LabelRegistryEntry } from "../../data/label/label_registry";
|
||||||
import type { TargetType } from "../../data/target";
|
import type { TargetType } from "../../data/target";
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { brandsUrl } from "../../util/brands-url";
|
import { brandsUrl } from "../../util/brands-url";
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export class HaTraceBlueprintConfig extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-code-editor
|
<ha-code-editor
|
||||||
.value=${dump(this.trace.blueprint_inputs || "").trimRight()}
|
.value=${dump(this.trace.blueprint_inputs || "").trimRight()}
|
||||||
|
.hass=${this.hass}
|
||||||
read-only
|
read-only
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
></ha-code-editor>
|
></ha-code-editor>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export class HaTraceConfig extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-code-editor
|
<ha-code-editor
|
||||||
.value=${dump(this.trace.config).trimRight()}
|
.value=${dump(this.trace.config).trimRight()}
|
||||||
|
.hass=${this.hass}
|
||||||
read-only
|
read-only
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
></ha-code-editor>
|
></ha-code-editor>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { dump } from "js-yaml";
|
|
||||||
import { consume } from "@lit/context";
|
import { consume } from "@lit/context";
|
||||||
|
import { dump } from "js-yaml";
|
||||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
||||||
import "../ha-code-editor";
|
import { describeCondition, describeTrigger } from "../../data/automation_i18n";
|
||||||
import "../ha-icon-button";
|
import { fullEntitiesContext, labelsContext } from "../../data/context";
|
||||||
import "./hat-logbook-note";
|
import type { EntityRegistryEntry } from "../../data/entity/entity_registry";
|
||||||
|
import type { LabelRegistryEntry } from "../../data/label/label_registry";
|
||||||
import type { LogbookEntry } from "../../data/logbook";
|
import type { LogbookEntry } from "../../data/logbook";
|
||||||
|
import { describeAction } from "../../data/script_i18n";
|
||||||
import type {
|
import type {
|
||||||
ActionTraceStep,
|
ActionTraceStep,
|
||||||
ChooseActionTraceStep,
|
ChooseActionTraceStep,
|
||||||
@@ -16,19 +18,12 @@ import type {
|
|||||||
} from "../../data/trace";
|
} from "../../data/trace";
|
||||||
import { getDataFromPath } from "../../data/trace";
|
import { getDataFromPath } from "../../data/trace";
|
||||||
import "../../panels/logbook/ha-logbook-renderer";
|
import "../../panels/logbook/ha-logbook-renderer";
|
||||||
import { traceTabStyles } from "./trace-tab-styles";
|
|
||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
|
import "../ha-code-editor";
|
||||||
|
import "../ha-icon-button";
|
||||||
|
import "./hat-logbook-note";
|
||||||
import type { NodeInfo } from "./hat-script-graph";
|
import type { NodeInfo } from "./hat-script-graph";
|
||||||
import { describeCondition, describeTrigger } from "../../data/automation_i18n";
|
import { traceTabStyles } from "./trace-tab-styles";
|
||||||
import type { EntityRegistryEntry } from "../../data/entity_registry";
|
|
||||||
import type { LabelRegistryEntry } from "../../data/label_registry";
|
|
||||||
import type { FloorRegistryEntry } from "../../data/floor_registry";
|
|
||||||
import {
|
|
||||||
floorsContext,
|
|
||||||
fullEntitiesContext,
|
|
||||||
labelsContext,
|
|
||||||
} from "../../data/context";
|
|
||||||
import { describeAction } from "../../data/script_i18n";
|
|
||||||
|
|
||||||
const TRACE_PATH_TABS = [
|
const TRACE_PATH_TABS = [
|
||||||
"step_config",
|
"step_config",
|
||||||
@@ -63,10 +58,6 @@ export class HaTracePathDetails extends LitElement {
|
|||||||
@consume({ context: labelsContext, subscribe: true })
|
@consume({ context: labelsContext, subscribe: true })
|
||||||
_labelReg!: LabelRegistryEntry[];
|
_labelReg!: LabelRegistryEntry[];
|
||||||
|
|
||||||
@state()
|
|
||||||
@consume({ context: floorsContext, subscribe: true })
|
|
||||||
_floorReg!: Record<string, FloorRegistryEntry>;
|
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<div class="padded-box trace-info">
|
<div class="padded-box trace-info">
|
||||||
@@ -193,8 +184,6 @@ export class HaTracePathDetails extends LitElement {
|
|||||||
${describeAction(
|
${describeAction(
|
||||||
this.hass,
|
this.hass,
|
||||||
this._entityReg,
|
this._entityReg,
|
||||||
this._labelReg,
|
|
||||||
this._floorReg,
|
|
||||||
currentDetail
|
currentDetail
|
||||||
)}
|
)}
|
||||||
</h2>`
|
</h2>`
|
||||||
@@ -278,6 +267,7 @@ export class HaTracePathDetails extends LitElement {
|
|||||||
return config
|
return config
|
||||||
? html`<ha-code-editor
|
? html`<ha-code-editor
|
||||||
.value=${dump(config).trimEnd()}
|
.value=${dump(config).trimEnd()}
|
||||||
|
.hass=${this.hass}
|
||||||
read-only
|
read-only
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
></ha-code-editor>`
|
></ha-code-editor>`
|
||||||
|
|||||||
@@ -15,19 +15,13 @@ import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_tim
|
|||||||
import { relativeTime } from "../../common/datetime/relative_time";
|
import { relativeTime } from "../../common/datetime/relative_time";
|
||||||
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 {
|
import { fullEntitiesContext } from "../../data/context";
|
||||||
floorsContext,
|
import type { EntityRegistryEntry } from "../../data/entity/entity_registry";
|
||||||
fullEntitiesContext,
|
|
||||||
labelsContext,
|
|
||||||
} from "../../data/context";
|
|
||||||
import type { EntityRegistryEntry } from "../../data/entity_registry";
|
|
||||||
import type { FloorRegistryEntry } from "../../data/floor_registry";
|
|
||||||
import type { LabelRegistryEntry } from "../../data/label_registry";
|
|
||||||
import type { LogbookEntry } from "../../data/logbook";
|
import type { LogbookEntry } from "../../data/logbook";
|
||||||
import type {
|
import type {
|
||||||
ChooseAction,
|
ChooseAction,
|
||||||
Option,
|
|
||||||
IfAction,
|
IfAction,
|
||||||
|
Option,
|
||||||
ParallelAction,
|
ParallelAction,
|
||||||
RepeatAction,
|
RepeatAction,
|
||||||
SequenceAction,
|
SequenceAction,
|
||||||
@@ -197,8 +191,6 @@ class ActionRenderer {
|
|||||||
constructor(
|
constructor(
|
||||||
private hass: HomeAssistant,
|
private hass: HomeAssistant,
|
||||||
private entityReg: EntityRegistryEntry[],
|
private entityReg: EntityRegistryEntry[],
|
||||||
private labelReg: LabelRegistryEntry[],
|
|
||||||
private floorReg: Record<string, FloorRegistryEntry>,
|
|
||||||
private entries: TemplateResult[],
|
private entries: TemplateResult[],
|
||||||
private trace: AutomationTraceExtended,
|
private trace: AutomationTraceExtended,
|
||||||
private logbookRenderer: LogbookRenderer,
|
private logbookRenderer: LogbookRenderer,
|
||||||
@@ -313,14 +305,7 @@ class ActionRenderer {
|
|||||||
|
|
||||||
this._renderEntry(
|
this._renderEntry(
|
||||||
path,
|
path,
|
||||||
describeAction(
|
describeAction(this.hass, this.entityReg, data, actionType),
|
||||||
this.hass,
|
|
||||||
this.entityReg,
|
|
||||||
this.labelReg,
|
|
||||||
this.floorReg,
|
|
||||||
data,
|
|
||||||
actionType
|
|
||||||
),
|
|
||||||
undefined,
|
undefined,
|
||||||
data.enabled === false
|
data.enabled === false
|
||||||
);
|
);
|
||||||
@@ -485,13 +470,7 @@ class ActionRenderer {
|
|||||||
|
|
||||||
const name =
|
const name =
|
||||||
repeatConfig.alias ||
|
repeatConfig.alias ||
|
||||||
describeAction(
|
describeAction(this.hass, this.entityReg, repeatConfig);
|
||||||
this.hass,
|
|
||||||
this.entityReg,
|
|
||||||
this.labelReg,
|
|
||||||
this.floorReg,
|
|
||||||
repeatConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
this._renderEntry(repeatPath, name, undefined, disabled);
|
this._renderEntry(repeatPath, name, undefined, disabled);
|
||||||
|
|
||||||
@@ -585,14 +564,7 @@ class ActionRenderer {
|
|||||||
this._renderEntry(
|
this._renderEntry(
|
||||||
sequencePath,
|
sequencePath,
|
||||||
sequenceConfig.alias ||
|
sequenceConfig.alias ||
|
||||||
describeAction(
|
describeAction(this.hass, this.entityReg, sequenceConfig, "sequence"),
|
||||||
this.hass,
|
|
||||||
this.entityReg,
|
|
||||||
this.labelReg,
|
|
||||||
this.floorReg,
|
|
||||||
sequenceConfig,
|
|
||||||
"sequence"
|
|
||||||
),
|
|
||||||
undefined,
|
undefined,
|
||||||
sequenceConfig.enabled === false
|
sequenceConfig.enabled === false
|
||||||
);
|
);
|
||||||
@@ -683,14 +655,6 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||||
_entityReg!: EntityRegistryEntry[];
|
_entityReg!: EntityRegistryEntry[];
|
||||||
|
|
||||||
@state()
|
|
||||||
@consume({ context: labelsContext, subscribe: true })
|
|
||||||
_labelReg!: LabelRegistryEntry[];
|
|
||||||
|
|
||||||
@state()
|
|
||||||
@consume({ context: floorsContext, subscribe: true })
|
|
||||||
_floorReg!: Record<string, FloorRegistryEntry>;
|
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
if (!this.trace) {
|
if (!this.trace) {
|
||||||
return nothing;
|
return nothing;
|
||||||
@@ -707,8 +671,6 @@ export class HaAutomationTracer extends LitElement {
|
|||||||
const actionRenderer = new ActionRenderer(
|
const actionRenderer = new ActionRenderer(
|
||||||
this.hass,
|
this.hass,
|
||||||
this._entityReg,
|
this._entityReg,
|
||||||
this._labelReg,
|
|
||||||
this._floorReg,
|
|
||||||
entries,
|
entries,
|
||||||
this.trace,
|
this.trace,
|
||||||
logbookRenderer,
|
logbookRenderer,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import type {
|
|||||||
import { supportsFeature } from "../common/entity/supports-feature";
|
import { supportsFeature } from "../common/entity/supports-feature";
|
||||||
import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog";
|
import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { getExtendedEntityRegistryEntry } from "./entity_registry";
|
import { getExtendedEntityRegistryEntry } from "./entity/entity_registry";
|
||||||
|
|
||||||
export const FORMAT_TEXT = "text";
|
export const FORMAT_TEXT = "text";
|
||||||
export const FORMAT_NUMBER = "number";
|
export const FORMAT_NUMBER = "number";
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import {
|
|||||||
getDeviceEntityDisplayLookup,
|
getDeviceEntityDisplayLookup,
|
||||||
type DeviceEntityDisplayLookup,
|
type DeviceEntityDisplayLookup,
|
||||||
type DeviceRegistryEntry,
|
type DeviceRegistryEntry,
|
||||||
} from "./device_registry";
|
} from "./device/device_registry";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "./entity";
|
import type { HaEntityPickerEntityFilterFunc } from "./entity/entity";
|
||||||
import type { EntityRegistryDisplayEntry } from "./entity_registry";
|
import type { EntityRegistryDisplayEntry } from "./entity/entity_registry";
|
||||||
import type { FloorRegistryEntry } from "./floor_registry";
|
import type { FloorRegistryEntry } from "./floor_registry";
|
||||||
|
|
||||||
export interface FloorComboBoxItem extends PickerComboBoxItem {
|
export interface FloorComboBoxItem extends PickerComboBoxItem {
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import type { DeviceRegistryEntry } from "./device_registry";
|
import type { DeviceRegistryEntry } from "./device/device_registry";
|
||||||
import type {
|
import type {
|
||||||
EntityRegistryDisplayEntry,
|
EntityRegistryDisplayEntry,
|
||||||
EntityRegistryEntry,
|
EntityRegistryEntry,
|
||||||
} from "./entity_registry";
|
} from "./entity/entity_registry";
|
||||||
import type { RegistryEntry } from "./registry";
|
import type { RegistryEntry } from "./registry";
|
||||||
|
|
||||||
export { subscribeAreaRegistry } from "./ws-area_registry";
|
export { subscribeAreaRegistry } from "./ws-area_registry";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
import { supportsFeature } from "../common/entity/supports-feature";
|
import { supportsFeature } from "../common/entity/supports-feature";
|
||||||
import { UNAVAILABLE } from "./entity";
|
import type { HomeAssistant } from "../types";
|
||||||
|
import { UNAVAILABLE } from "./entity/entity";
|
||||||
|
|
||||||
export const enum AssistSatelliteEntityFeature {
|
export const enum AssistSatelliteEntityFeature {
|
||||||
ANNOUNCE = 1,
|
ANNOUNCE = 1,
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ import type { Context, HomeAssistant } from "../types";
|
|||||||
import type { BlueprintInput } from "./blueprint";
|
import type { BlueprintInput } from "./blueprint";
|
||||||
import type { ConditionDescription } from "./condition";
|
import type { ConditionDescription } from "./condition";
|
||||||
import { CONDITION_BUILDING_BLOCKS } from "./condition";
|
import { CONDITION_BUILDING_BLOCKS } from "./condition";
|
||||||
import type { DeviceCondition, DeviceTrigger } from "./device_automation";
|
import type {
|
||||||
|
DeviceCondition,
|
||||||
|
DeviceTrigger,
|
||||||
|
} from "./device/device_automation";
|
||||||
import type { Action, Field, MODES } from "./script";
|
import type { Action, Field, MODES } from "./script";
|
||||||
import { migrateAutomationAction } from "./script";
|
import { migrateAutomationAction } from "./script";
|
||||||
import type { TriggerDescription } from "./trigger";
|
import type { TriggerDescription } from "./trigger";
|
||||||
|
|||||||
@@ -26,12 +26,15 @@ import type {
|
|||||||
Trigger,
|
Trigger,
|
||||||
} from "./automation";
|
} from "./automation";
|
||||||
import { getConditionDomain, getConditionObjectId } from "./condition";
|
import { getConditionDomain, getConditionObjectId } from "./condition";
|
||||||
import type { DeviceCondition, DeviceTrigger } from "./device_automation";
|
import type {
|
||||||
|
DeviceCondition,
|
||||||
|
DeviceTrigger,
|
||||||
|
} from "./device/device_automation";
|
||||||
import {
|
import {
|
||||||
localizeDeviceAutomationCondition,
|
localizeDeviceAutomationCondition,
|
||||||
localizeDeviceAutomationTrigger,
|
localizeDeviceAutomationTrigger,
|
||||||
} from "./device_automation";
|
} from "./device/device_automation";
|
||||||
import type { EntityRegistryEntry } from "./entity_registry";
|
import type { EntityRegistryEntry } from "./entity/entity_registry";
|
||||||
import type { FrontendLocaleData } from "./translation";
|
import type { FrontendLocaleData } from "./translation";
|
||||||
import { getTriggerDomain, getTriggerObjectId, isTriggerList } from "./trigger";
|
import { getTriggerDomain, getTriggerObjectId, isTriggerList } from "./trigger";
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { getColorByIndex } from "../common/color/colors";
|
|||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
import { computeStateName } from "../common/entity/compute_state_name";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { isUnavailableState } from "./entity";
|
import { isUnavailableState } from "./entity/entity";
|
||||||
|
|
||||||
export interface Calendar {
|
export interface Calendar {
|
||||||
entity_id: string;
|
entity_id: string;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createContext } from "@lit/context";
|
import { createContext } from "@lit/context";
|
||||||
import type { HassConfig } from "home-assistant-js-websocket";
|
import type { HassConfig } from "home-assistant-js-websocket";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import type { EntityRegistryEntry } from "./entity_registry";
|
import type { EntityRegistryEntry } from "./entity/entity_registry";
|
||||||
import type { LabelRegistryEntry } from "./label_registry";
|
import type { LabelRegistryEntry } from "./label/label_registry";
|
||||||
|
|
||||||
export const connectionContext =
|
export const connectionContext =
|
||||||
createContext<HomeAssistant["connection"]>("connection");
|
createContext<HomeAssistant["connection"]>("connection");
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type {
|
|||||||
import { stateActive } from "../common/entity/state_active";
|
import { stateActive } from "../common/entity/state_active";
|
||||||
import { supportsFeature } from "../common/entity/supports-feature";
|
import { supportsFeature } from "../common/entity/supports-feature";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { UNAVAILABLE } from "./entity";
|
import { UNAVAILABLE } from "./entity/entity";
|
||||||
|
|
||||||
export const enum CoverEntityFeature {
|
export const enum CoverEntityFeature {
|
||||||
OPEN = 1,
|
OPEN = 1,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import type { HaFormSchema } from "../components/ha-form/types";
|
import type { HaFormSchema } from "../../components/ha-form/types";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import type { BaseTrigger } from "./automation";
|
import type { BaseTrigger } from "../automation";
|
||||||
import { migrateAutomationTrigger } from "./automation";
|
import { migrateAutomationTrigger } from "../automation";
|
||||||
import type { EntityRegistryEntry } from "./entity_registry";
|
import type { EntityRegistryEntry } from "../entity/entity_registry";
|
||||||
import {
|
import {
|
||||||
computeEntityRegistryName,
|
computeEntityRegistryName,
|
||||||
entityRegistryByEntityId,
|
entityRegistryByEntityId,
|
||||||
entityRegistryById,
|
entityRegistryById,
|
||||||
} from "./entity_registry";
|
} from "../entity/entity_registry";
|
||||||
|
|
||||||
export interface DeviceAutomation {
|
export interface DeviceAutomation {
|
||||||
alias?: string;
|
alias?: string;
|
||||||
182
src/data/device/device_picker.ts
Normal file
182
src/data/device/device_picker.ts
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
import { computeAreaName } from "../../common/entity/compute_area_name";
|
||||||
|
import { computeDeviceNameDisplay } from "../../common/entity/compute_device_name";
|
||||||
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
|
import { getDeviceContext } from "../../common/entity/context/get_device_context";
|
||||||
|
import type { HaDevicePickerDeviceFilterFunc } from "../../components/device/ha-device-picker";
|
||||||
|
import type { PickerComboBoxItem } from "../../components/ha-picker-combo-box";
|
||||||
|
import type { FuseWeightedKey } from "../../resources/fuseMultiTerm";
|
||||||
|
import type { HomeAssistant } from "../../types";
|
||||||
|
import type { ConfigEntry } from "../config_entries";
|
||||||
|
import type { HaEntityPickerEntityFilterFunc } from "../entity/entity";
|
||||||
|
import { domainToName } from "../integration";
|
||||||
|
import {
|
||||||
|
getDeviceEntityDisplayLookup,
|
||||||
|
type DeviceEntityDisplayLookup,
|
||||||
|
} from "./device_registry";
|
||||||
|
|
||||||
|
export interface DevicePickerItem extends PickerComboBoxItem {
|
||||||
|
domain?: string;
|
||||||
|
domain_name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deviceComboBoxKeys: FuseWeightedKey[] = [
|
||||||
|
{
|
||||||
|
name: "search_labels.deviceName",
|
||||||
|
weight: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.areaName",
|
||||||
|
weight: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.domainName",
|
||||||
|
weight: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.domain",
|
||||||
|
weight: 4,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const getDevices = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
configEntryLookup: Record<string, ConfigEntry>,
|
||||||
|
includeDomains?: string[],
|
||||||
|
excludeDomains?: string[],
|
||||||
|
includeDeviceClasses?: string[],
|
||||||
|
deviceFilter?: HaDevicePickerDeviceFilterFunc,
|
||||||
|
entityFilter?: HaEntityPickerEntityFilterFunc,
|
||||||
|
excludeDevices?: string[],
|
||||||
|
value?: string,
|
||||||
|
idPrefix = ""
|
||||||
|
): DevicePickerItem[] => {
|
||||||
|
const devices = Object.values(hass.devices);
|
||||||
|
const entities = Object.values(hass.entities);
|
||||||
|
|
||||||
|
let deviceEntityLookup: DeviceEntityDisplayLookup = {};
|
||||||
|
|
||||||
|
if (
|
||||||
|
includeDomains ||
|
||||||
|
excludeDomains ||
|
||||||
|
includeDeviceClasses ||
|
||||||
|
entityFilter
|
||||||
|
) {
|
||||||
|
deviceEntityLookup = getDeviceEntityDisplayLookup(entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
let inputDevices = devices.filter(
|
||||||
|
(device) => device.id === value || !device.disabled_by
|
||||||
|
);
|
||||||
|
|
||||||
|
if (includeDomains) {
|
||||||
|
inputDevices = inputDevices.filter((device) => {
|
||||||
|
const devEntities = deviceEntityLookup[device.id];
|
||||||
|
if (!devEntities || !devEntities.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return deviceEntityLookup[device.id].some((entity) =>
|
||||||
|
includeDomains.includes(computeDomain(entity.entity_id))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludeDomains) {
|
||||||
|
inputDevices = inputDevices.filter((device) => {
|
||||||
|
const devEntities = deviceEntityLookup[device.id];
|
||||||
|
if (!devEntities || !devEntities.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return entities.every(
|
||||||
|
(entity) => !excludeDomains.includes(computeDomain(entity.entity_id))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludeDevices) {
|
||||||
|
inputDevices = inputDevices.filter(
|
||||||
|
(device) => !excludeDevices!.includes(device.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeDeviceClasses) {
|
||||||
|
inputDevices = inputDevices.filter((device) => {
|
||||||
|
const devEntities = deviceEntityLookup[device.id];
|
||||||
|
if (!devEntities || !devEntities.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return deviceEntityLookup[device.id].some((entity) => {
|
||||||
|
const stateObj = hass.states[entity.entity_id];
|
||||||
|
if (!stateObj) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
stateObj.attributes.device_class &&
|
||||||
|
includeDeviceClasses.includes(stateObj.attributes.device_class)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityFilter) {
|
||||||
|
inputDevices = inputDevices.filter((device) => {
|
||||||
|
const devEntities = deviceEntityLookup[device.id];
|
||||||
|
if (!devEntities || !devEntities.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return devEntities.some((entity) => {
|
||||||
|
const stateObj = hass.states[entity.entity_id];
|
||||||
|
if (!stateObj) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return entityFilter(stateObj);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceFilter) {
|
||||||
|
inputDevices = inputDevices.filter(
|
||||||
|
(device) =>
|
||||||
|
// We always want to include the device of the current value
|
||||||
|
device.id === value || deviceFilter!(device)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const outputDevices = inputDevices.map<DevicePickerItem>((device) => {
|
||||||
|
const deviceName = computeDeviceNameDisplay(
|
||||||
|
device,
|
||||||
|
hass,
|
||||||
|
deviceEntityLookup[device.id]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { area } = getDeviceContext(device, hass);
|
||||||
|
|
||||||
|
const areaName = area ? computeAreaName(area) : undefined;
|
||||||
|
|
||||||
|
const configEntry = device.primary_config_entry
|
||||||
|
? configEntryLookup?.[device.primary_config_entry]
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const domain = configEntry?.domain;
|
||||||
|
const domainName = domain ? domainToName(hass.localize, domain) : undefined;
|
||||||
|
const primary =
|
||||||
|
deviceName || hass.localize("ui.components.device-picker.unnamed_device");
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: `${idPrefix}${device.id}`,
|
||||||
|
label: "",
|
||||||
|
primary,
|
||||||
|
secondary: areaName,
|
||||||
|
domain: configEntry?.domain,
|
||||||
|
domain_name: domainName,
|
||||||
|
search_labels: {
|
||||||
|
deviceName,
|
||||||
|
areaName: areaName || null,
|
||||||
|
domain: domain || null,
|
||||||
|
domainName: domainName || null,
|
||||||
|
},
|
||||||
|
sorting_label: [primary, areaName, domainName].filter(Boolean).join("_"),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return outputDevices;
|
||||||
|
};
|
||||||
169
src/data/device/device_registry.ts
Normal file
169
src/data/device/device_registry.ts
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
|
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
||||||
|
import type { HomeAssistant } from "../../types";
|
||||||
|
import type { ConfigEntry } from "../config_entries";
|
||||||
|
import type {
|
||||||
|
EntityRegistryDisplayEntry,
|
||||||
|
EntityRegistryEntry,
|
||||||
|
} from "../entity/entity_registry";
|
||||||
|
import type { EntitySources } from "../entity/entity_sources";
|
||||||
|
import type { RegistryEntry } from "../registry";
|
||||||
|
|
||||||
|
export {
|
||||||
|
fetchDeviceRegistry,
|
||||||
|
subscribeDeviceRegistry,
|
||||||
|
} from "../ws-device_registry";
|
||||||
|
|
||||||
|
export interface DeviceRegistryEntry extends RegistryEntry {
|
||||||
|
id: string;
|
||||||
|
config_entries: string[];
|
||||||
|
config_entries_subentries: Record<string, (string | null)[]>;
|
||||||
|
connections: [string, string][];
|
||||||
|
identifiers: [string, string][];
|
||||||
|
manufacturer: string | null;
|
||||||
|
model: string | null;
|
||||||
|
model_id: string | null;
|
||||||
|
name: string | null;
|
||||||
|
labels: string[];
|
||||||
|
sw_version: string | null;
|
||||||
|
hw_version: string | null;
|
||||||
|
serial_number: string | null;
|
||||||
|
via_device_id: string | null;
|
||||||
|
area_id: string | null;
|
||||||
|
name_by_user: string | null;
|
||||||
|
entry_type: "service" | null;
|
||||||
|
disabled_by: "user" | "integration" | "config_entry" | null;
|
||||||
|
configuration_url: string | null;
|
||||||
|
primary_config_entry: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DeviceEntityDisplayLookup = Record<
|
||||||
|
string,
|
||||||
|
EntityRegistryDisplayEntry[]
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type DeviceEntityLookup<
|
||||||
|
T extends EntityRegistryEntry | EntityRegistryDisplayEntry =
|
||||||
|
| EntityRegistryEntry
|
||||||
|
| EntityRegistryDisplayEntry,
|
||||||
|
> = Record<string, T[]>;
|
||||||
|
|
||||||
|
export interface DeviceRegistryEntryMutableParams {
|
||||||
|
area_id?: string | null;
|
||||||
|
name_by_user?: string | null;
|
||||||
|
disabled_by?: string | null;
|
||||||
|
labels?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fallbackDeviceName = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entities: EntityRegistryEntry[] | EntityRegistryDisplayEntry[] | string[]
|
||||||
|
) => {
|
||||||
|
for (const entity of entities || []) {
|
||||||
|
const entityId = typeof entity === "string" ? entity : entity.entity_id;
|
||||||
|
const stateObj = hass.states[entityId];
|
||||||
|
if (stateObj) {
|
||||||
|
return computeStateName(stateObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const devicesInArea = (devices: DeviceRegistryEntry[], areaId: string) =>
|
||||||
|
devices.filter((device) => device.area_id === areaId);
|
||||||
|
|
||||||
|
export const updateDeviceRegistryEntry = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
deviceId: string,
|
||||||
|
updates: Partial<DeviceRegistryEntryMutableParams>
|
||||||
|
) =>
|
||||||
|
hass.callWS<DeviceRegistryEntry>({
|
||||||
|
type: "config/device_registry/update",
|
||||||
|
device_id: deviceId,
|
||||||
|
...updates,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const removeConfigEntryFromDevice = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
deviceId: string,
|
||||||
|
configEntryId: string
|
||||||
|
) =>
|
||||||
|
hass.callWS<DeviceRegistryEntry>({
|
||||||
|
type: "config/device_registry/remove_config_entry",
|
||||||
|
device_id: deviceId,
|
||||||
|
config_entry_id: configEntryId,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const sortDeviceRegistryByName = (
|
||||||
|
entries: DeviceRegistryEntry[],
|
||||||
|
language: string
|
||||||
|
) =>
|
||||||
|
entries.sort((entry1, entry2) =>
|
||||||
|
caseInsensitiveStringCompare(entry1.name || "", entry2.name || "", language)
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getDeviceEntityLookup = (
|
||||||
|
entities: (EntityRegistryEntry | EntityRegistryDisplayEntry)[]
|
||||||
|
): DeviceEntityLookup => {
|
||||||
|
const deviceEntityLookup: DeviceEntityLookup = {};
|
||||||
|
for (const entity of entities) {
|
||||||
|
if (!entity.device_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(entity.device_id in deviceEntityLookup)) {
|
||||||
|
deviceEntityLookup[entity.device_id] = [];
|
||||||
|
}
|
||||||
|
deviceEntityLookup[entity.device_id].push(entity);
|
||||||
|
}
|
||||||
|
return deviceEntityLookup;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDeviceEntityDisplayLookup = (
|
||||||
|
entities: EntityRegistryDisplayEntry[]
|
||||||
|
): DeviceEntityDisplayLookup => {
|
||||||
|
const deviceEntityLookup: DeviceEntityDisplayLookup = {};
|
||||||
|
for (const entity of entities) {
|
||||||
|
if (!entity.device_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!(entity.device_id in deviceEntityLookup)) {
|
||||||
|
deviceEntityLookup[entity.device_id] = [];
|
||||||
|
}
|
||||||
|
deviceEntityLookup[entity.device_id].push(entity);
|
||||||
|
}
|
||||||
|
return deviceEntityLookup;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDeviceIntegrationLookup = (
|
||||||
|
entitySources: EntitySources,
|
||||||
|
entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[],
|
||||||
|
devices?: DeviceRegistryEntry[],
|
||||||
|
configEntries?: ConfigEntry[]
|
||||||
|
): Record<string, Set<string>> => {
|
||||||
|
const deviceIntegrations: Record<string, Set<string>> = {};
|
||||||
|
|
||||||
|
for (const entity of entities) {
|
||||||
|
const source = entitySources[entity.entity_id];
|
||||||
|
if (!source?.domain || entity.device_id === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceIntegrations[entity.device_id!] =
|
||||||
|
deviceIntegrations[entity.device_id!] || new Set<string>();
|
||||||
|
deviceIntegrations[entity.device_id!].add(source.domain);
|
||||||
|
}
|
||||||
|
// Lookup devices that have no entities
|
||||||
|
if (devices && configEntries) {
|
||||||
|
for (const device of devices) {
|
||||||
|
for (const config_entry_id of device.config_entries) {
|
||||||
|
const entry = configEntries.find((e) => e.entry_id === config_entry_id);
|
||||||
|
if (entry?.domain) {
|
||||||
|
deviceIntegrations[device.id] =
|
||||||
|
deviceIntegrations[device.id] || new Set<string>();
|
||||||
|
deviceIntegrations[device.id].add(entry.domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceIntegrations;
|
||||||
|
};
|
||||||
@@ -1,345 +0,0 @@
|
|||||||
import { computeAreaName } from "../common/entity/compute_area_name";
|
|
||||||
import { computeDeviceNameDisplay } from "../common/entity/compute_device_name";
|
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
|
||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
|
||||||
import { getDeviceContext } from "../common/entity/context/get_device_context";
|
|
||||||
import { caseInsensitiveStringCompare } from "../common/string/compare";
|
|
||||||
import type { HaDevicePickerDeviceFilterFunc } from "../components/device/ha-device-picker";
|
|
||||||
import type { PickerComboBoxItem } from "../components/ha-picker-combo-box";
|
|
||||||
import type { FuseWeightedKey } from "../resources/fuseMultiTerm";
|
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
import type { ConfigEntry } from "./config_entries";
|
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "./entity";
|
|
||||||
import type {
|
|
||||||
EntityRegistryDisplayEntry,
|
|
||||||
EntityRegistryEntry,
|
|
||||||
} from "./entity_registry";
|
|
||||||
import type { EntitySources } from "./entity_sources";
|
|
||||||
import { domainToName } from "./integration";
|
|
||||||
import type { RegistryEntry } from "./registry";
|
|
||||||
|
|
||||||
export {
|
|
||||||
fetchDeviceRegistry,
|
|
||||||
subscribeDeviceRegistry,
|
|
||||||
} from "./ws-device_registry";
|
|
||||||
|
|
||||||
export interface DeviceRegistryEntry extends RegistryEntry {
|
|
||||||
id: string;
|
|
||||||
config_entries: string[];
|
|
||||||
config_entries_subentries: Record<string, (string | null)[]>;
|
|
||||||
connections: [string, string][];
|
|
||||||
identifiers: [string, string][];
|
|
||||||
manufacturer: string | null;
|
|
||||||
model: string | null;
|
|
||||||
model_id: string | null;
|
|
||||||
name: string | null;
|
|
||||||
labels: string[];
|
|
||||||
sw_version: string | null;
|
|
||||||
hw_version: string | null;
|
|
||||||
serial_number: string | null;
|
|
||||||
via_device_id: string | null;
|
|
||||||
area_id: string | null;
|
|
||||||
name_by_user: string | null;
|
|
||||||
entry_type: "service" | null;
|
|
||||||
disabled_by: "user" | "integration" | "config_entry" | null;
|
|
||||||
configuration_url: string | null;
|
|
||||||
primary_config_entry: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DeviceEntityDisplayLookup = Record<
|
|
||||||
string,
|
|
||||||
EntityRegistryDisplayEntry[]
|
|
||||||
>;
|
|
||||||
|
|
||||||
export type DeviceEntityLookup<
|
|
||||||
T extends EntityRegistryEntry | EntityRegistryDisplayEntry =
|
|
||||||
| EntityRegistryEntry
|
|
||||||
| EntityRegistryDisplayEntry,
|
|
||||||
> = Record<string, T[]>;
|
|
||||||
|
|
||||||
export interface DeviceRegistryEntryMutableParams {
|
|
||||||
area_id?: string | null;
|
|
||||||
name_by_user?: string | null;
|
|
||||||
disabled_by?: string | null;
|
|
||||||
labels?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fallbackDeviceName = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
entities: EntityRegistryEntry[] | EntityRegistryDisplayEntry[] | string[]
|
|
||||||
) => {
|
|
||||||
for (const entity of entities || []) {
|
|
||||||
const entityId = typeof entity === "string" ? entity : entity.entity_id;
|
|
||||||
const stateObj = hass.states[entityId];
|
|
||||||
if (stateObj) {
|
|
||||||
return computeStateName(stateObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const devicesInArea = (devices: DeviceRegistryEntry[], areaId: string) =>
|
|
||||||
devices.filter((device) => device.area_id === areaId);
|
|
||||||
|
|
||||||
export const updateDeviceRegistryEntry = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
deviceId: string,
|
|
||||||
updates: Partial<DeviceRegistryEntryMutableParams>
|
|
||||||
) =>
|
|
||||||
hass.callWS<DeviceRegistryEntry>({
|
|
||||||
type: "config/device_registry/update",
|
|
||||||
device_id: deviceId,
|
|
||||||
...updates,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const removeConfigEntryFromDevice = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
deviceId: string,
|
|
||||||
configEntryId: string
|
|
||||||
) =>
|
|
||||||
hass.callWS<DeviceRegistryEntry>({
|
|
||||||
type: "config/device_registry/remove_config_entry",
|
|
||||||
device_id: deviceId,
|
|
||||||
config_entry_id: configEntryId,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const sortDeviceRegistryByName = (
|
|
||||||
entries: DeviceRegistryEntry[],
|
|
||||||
language: string
|
|
||||||
) =>
|
|
||||||
entries.sort((entry1, entry2) =>
|
|
||||||
caseInsensitiveStringCompare(entry1.name || "", entry2.name || "", language)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getDeviceEntityLookup = (
|
|
||||||
entities: (EntityRegistryEntry | EntityRegistryDisplayEntry)[]
|
|
||||||
): DeviceEntityLookup => {
|
|
||||||
const deviceEntityLookup: DeviceEntityLookup = {};
|
|
||||||
for (const entity of entities) {
|
|
||||||
if (!entity.device_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!(entity.device_id in deviceEntityLookup)) {
|
|
||||||
deviceEntityLookup[entity.device_id] = [];
|
|
||||||
}
|
|
||||||
deviceEntityLookup[entity.device_id].push(entity);
|
|
||||||
}
|
|
||||||
return deviceEntityLookup;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getDeviceEntityDisplayLookup = (
|
|
||||||
entities: EntityRegistryDisplayEntry[]
|
|
||||||
): DeviceEntityDisplayLookup => {
|
|
||||||
const deviceEntityLookup: DeviceEntityDisplayLookup = {};
|
|
||||||
for (const entity of entities) {
|
|
||||||
if (!entity.device_id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!(entity.device_id in deviceEntityLookup)) {
|
|
||||||
deviceEntityLookup[entity.device_id] = [];
|
|
||||||
}
|
|
||||||
deviceEntityLookup[entity.device_id].push(entity);
|
|
||||||
}
|
|
||||||
return deviceEntityLookup;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getDeviceIntegrationLookup = (
|
|
||||||
entitySources: EntitySources,
|
|
||||||
entities: EntityRegistryDisplayEntry[] | EntityRegistryEntry[],
|
|
||||||
devices?: DeviceRegistryEntry[],
|
|
||||||
configEntries?: ConfigEntry[]
|
|
||||||
): Record<string, Set<string>> => {
|
|
||||||
const deviceIntegrations: Record<string, Set<string>> = {};
|
|
||||||
|
|
||||||
for (const entity of entities) {
|
|
||||||
const source = entitySources[entity.entity_id];
|
|
||||||
if (!source?.domain || entity.device_id === null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceIntegrations[entity.device_id!] =
|
|
||||||
deviceIntegrations[entity.device_id!] || new Set<string>();
|
|
||||||
deviceIntegrations[entity.device_id!].add(source.domain);
|
|
||||||
}
|
|
||||||
// Lookup devices that have no entities
|
|
||||||
if (devices && configEntries) {
|
|
||||||
for (const device of devices) {
|
|
||||||
for (const config_entry_id of device.config_entries) {
|
|
||||||
const entry = configEntries.find((e) => e.entry_id === config_entry_id);
|
|
||||||
if (entry?.domain) {
|
|
||||||
deviceIntegrations[device.id] =
|
|
||||||
deviceIntegrations[device.id] || new Set<string>();
|
|
||||||
deviceIntegrations[device.id].add(entry.domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return deviceIntegrations;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface DevicePickerItem extends PickerComboBoxItem {
|
|
||||||
domain?: string;
|
|
||||||
domain_name?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const deviceComboBoxKeys: FuseWeightedKey[] = [
|
|
||||||
{
|
|
||||||
name: "search_labels.deviceName",
|
|
||||||
weight: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.areaName",
|
|
||||||
weight: 8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.domainName",
|
|
||||||
weight: 4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.domain",
|
|
||||||
weight: 4,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const getDevices = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
configEntryLookup: Record<string, ConfigEntry>,
|
|
||||||
includeDomains?: string[],
|
|
||||||
excludeDomains?: string[],
|
|
||||||
includeDeviceClasses?: string[],
|
|
||||||
deviceFilter?: HaDevicePickerDeviceFilterFunc,
|
|
||||||
entityFilter?: HaEntityPickerEntityFilterFunc,
|
|
||||||
excludeDevices?: string[],
|
|
||||||
value?: string,
|
|
||||||
idPrefix = ""
|
|
||||||
): DevicePickerItem[] => {
|
|
||||||
const devices = Object.values(hass.devices);
|
|
||||||
const entities = Object.values(hass.entities);
|
|
||||||
|
|
||||||
let deviceEntityLookup: DeviceEntityDisplayLookup = {};
|
|
||||||
|
|
||||||
if (
|
|
||||||
includeDomains ||
|
|
||||||
excludeDomains ||
|
|
||||||
includeDeviceClasses ||
|
|
||||||
entityFilter
|
|
||||||
) {
|
|
||||||
deviceEntityLookup = getDeviceEntityDisplayLookup(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
let inputDevices = devices.filter(
|
|
||||||
(device) => device.id === value || !device.disabled_by
|
|
||||||
);
|
|
||||||
|
|
||||||
if (includeDomains) {
|
|
||||||
inputDevices = inputDevices.filter((device) => {
|
|
||||||
const devEntities = deviceEntityLookup[device.id];
|
|
||||||
if (!devEntities || !devEntities.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return deviceEntityLookup[device.id].some((entity) =>
|
|
||||||
includeDomains.includes(computeDomain(entity.entity_id))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludeDomains) {
|
|
||||||
inputDevices = inputDevices.filter((device) => {
|
|
||||||
const devEntities = deviceEntityLookup[device.id];
|
|
||||||
if (!devEntities || !devEntities.length) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return entities.every(
|
|
||||||
(entity) => !excludeDomains.includes(computeDomain(entity.entity_id))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludeDevices) {
|
|
||||||
inputDevices = inputDevices.filter(
|
|
||||||
(device) => !excludeDevices!.includes(device.id)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeDeviceClasses) {
|
|
||||||
inputDevices = inputDevices.filter((device) => {
|
|
||||||
const devEntities = deviceEntityLookup[device.id];
|
|
||||||
if (!devEntities || !devEntities.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return deviceEntityLookup[device.id].some((entity) => {
|
|
||||||
const stateObj = hass.states[entity.entity_id];
|
|
||||||
if (!stateObj) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
stateObj.attributes.device_class &&
|
|
||||||
includeDeviceClasses.includes(stateObj.attributes.device_class)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entityFilter) {
|
|
||||||
inputDevices = inputDevices.filter((device) => {
|
|
||||||
const devEntities = deviceEntityLookup[device.id];
|
|
||||||
if (!devEntities || !devEntities.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return devEntities.some((entity) => {
|
|
||||||
const stateObj = hass.states[entity.entity_id];
|
|
||||||
if (!stateObj) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return entityFilter(stateObj);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deviceFilter) {
|
|
||||||
inputDevices = inputDevices.filter(
|
|
||||||
(device) =>
|
|
||||||
// We always want to include the device of the current value
|
|
||||||
device.id === value || deviceFilter!(device)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const outputDevices = inputDevices.map<DevicePickerItem>((device) => {
|
|
||||||
const deviceName = computeDeviceNameDisplay(
|
|
||||||
device,
|
|
||||||
hass,
|
|
||||||
deviceEntityLookup[device.id]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { area } = getDeviceContext(device, hass);
|
|
||||||
|
|
||||||
const areaName = area ? computeAreaName(area) : undefined;
|
|
||||||
|
|
||||||
const configEntry = device.primary_config_entry
|
|
||||||
? configEntryLookup?.[device.primary_config_entry]
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const domain = configEntry?.domain;
|
|
||||||
const domainName = domain ? domainToName(hass.localize, domain) : undefined;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: `${idPrefix}${device.id}`,
|
|
||||||
label: "",
|
|
||||||
primary:
|
|
||||||
deviceName ||
|
|
||||||
hass.localize("ui.components.device-picker.unnamed_device"),
|
|
||||||
secondary: areaName,
|
|
||||||
domain: configEntry?.domain,
|
|
||||||
domain_name: domainName,
|
|
||||||
search_labels: {
|
|
||||||
deviceName,
|
|
||||||
areaName: areaName || null,
|
|
||||||
domain: domain || null,
|
|
||||||
domainName: domainName || null,
|
|
||||||
},
|
|
||||||
sorting_label: deviceName || "zzz",
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return outputDevices;
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { HassEntity } from "home-assistant-js-websocket";
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { arrayLiteralIncludes } from "../common/array/literal-includes";
|
import { arrayLiteralIncludes } from "../../common/array/literal-includes";
|
||||||
|
|
||||||
export const UNAVAILABLE = "unavailable";
|
export const UNAVAILABLE = "unavailable";
|
||||||
export const UNKNOWN = "unknown";
|
export const UNKNOWN = "unknown";
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { formatDurationDigital } from "../common/datetime/format_duration";
|
import { formatDurationDigital } from "../../common/datetime/format_duration";
|
||||||
import type { FrontendLocaleData } from "./translation";
|
import type { FrontendLocaleData } from "../translation";
|
||||||
|
|
||||||
// These attributes are hidden from the more-info window for all entities.
|
// These attributes are hidden from the more-info window for all entities.
|
||||||
export const STATE_ATTRIBUTES = [
|
export const STATE_ATTRIBUTES = [
|
||||||
155
src/data/entity/entity_picker.ts
Normal file
155
src/data/entity/entity_picker.ts
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
|
import { computeEntityNameList } from "../../common/entity/compute_entity_name_display";
|
||||||
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
|
import { computeRTL } from "../../common/util/compute_rtl";
|
||||||
|
import type { PickerComboBoxItem } from "../../components/ha-picker-combo-box";
|
||||||
|
import type { FuseWeightedKey } from "../../resources/fuseMultiTerm";
|
||||||
|
import type { HomeAssistant } from "../../types";
|
||||||
|
import { domainToName } from "../integration";
|
||||||
|
import type { HaEntityPickerEntityFilterFunc } from "./entity";
|
||||||
|
|
||||||
|
export interface EntityComboBoxItem extends PickerComboBoxItem {
|
||||||
|
domain_name?: string;
|
||||||
|
stateObj?: HassEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const entityComboBoxKeys: FuseWeightedKey[] = [
|
||||||
|
{
|
||||||
|
name: "search_labels.entityName",
|
||||||
|
weight: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.friendlyName",
|
||||||
|
weight: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.deviceName",
|
||||||
|
weight: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.areaName",
|
||||||
|
weight: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.domainName",
|
||||||
|
weight: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "search_labels.entityId",
|
||||||
|
weight: 3,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const getEntities = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
includeDomains?: string[],
|
||||||
|
excludeDomains?: string[],
|
||||||
|
entityFilter?: HaEntityPickerEntityFilterFunc,
|
||||||
|
includeDeviceClasses?: string[],
|
||||||
|
includeUnitOfMeasurement?: string[],
|
||||||
|
includeEntities?: string[],
|
||||||
|
excludeEntities?: string[],
|
||||||
|
value?: string,
|
||||||
|
idPrefix = ""
|
||||||
|
): EntityComboBoxItem[] => {
|
||||||
|
let items: EntityComboBoxItem[] = [];
|
||||||
|
|
||||||
|
let entityIds = Object.keys(hass.states);
|
||||||
|
|
||||||
|
if (includeEntities) {
|
||||||
|
entityIds = entityIds.filter((entityId) =>
|
||||||
|
includeEntities.includes(entityId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludeEntities) {
|
||||||
|
entityIds = entityIds.filter(
|
||||||
|
(entityId) => !excludeEntities.includes(entityId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeDomains) {
|
||||||
|
entityIds = entityIds.filter((eid) =>
|
||||||
|
includeDomains.includes(computeDomain(eid))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (excludeDomains) {
|
||||||
|
entityIds = entityIds.filter(
|
||||||
|
(eid) => !excludeDomains.includes(computeDomain(eid))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
items = entityIds.map<EntityComboBoxItem>((entityId) => {
|
||||||
|
const stateObj = hass.states[entityId];
|
||||||
|
|
||||||
|
const friendlyName = computeStateName(stateObj); // Keep this for search
|
||||||
|
const [entityName, deviceName, areaName] = computeEntityNameList(
|
||||||
|
stateObj,
|
||||||
|
[{ type: "entity" }, { type: "device" }, { type: "area" }],
|
||||||
|
hass.entities,
|
||||||
|
hass.devices,
|
||||||
|
hass.areas,
|
||||||
|
hass.floors
|
||||||
|
);
|
||||||
|
|
||||||
|
const domainName = domainToName(hass.localize, computeDomain(entityId));
|
||||||
|
|
||||||
|
const isRTL = computeRTL(hass);
|
||||||
|
|
||||||
|
const primary = entityName || deviceName || entityId;
|
||||||
|
const secondary = [areaName, entityName ? deviceName : undefined]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(isRTL ? " ◂ " : " ▸ ");
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: `${idPrefix}${entityId}`,
|
||||||
|
primary: primary,
|
||||||
|
secondary: secondary,
|
||||||
|
domain_name: domainName,
|
||||||
|
sorting_label: [primary, secondary].filter(Boolean).join("_"),
|
||||||
|
search_labels: {
|
||||||
|
entityName: entityName || null,
|
||||||
|
deviceName: deviceName || null,
|
||||||
|
areaName: areaName || null,
|
||||||
|
domainName: domainName || null,
|
||||||
|
friendlyName: friendlyName || null,
|
||||||
|
entityId: entityId,
|
||||||
|
},
|
||||||
|
stateObj: stateObj,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (includeDeviceClasses) {
|
||||||
|
items = items.filter(
|
||||||
|
(item) =>
|
||||||
|
// We always want to include the entity of the current value
|
||||||
|
item.id === value ||
|
||||||
|
(item.stateObj?.attributes.device_class &&
|
||||||
|
includeDeviceClasses.includes(item.stateObj.attributes.device_class))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeUnitOfMeasurement) {
|
||||||
|
items = items.filter(
|
||||||
|
(item) =>
|
||||||
|
// We always want to include the entity of the current value
|
||||||
|
item.id === value ||
|
||||||
|
(item.stateObj?.attributes.unit_of_measurement &&
|
||||||
|
includeUnitOfMeasurement.includes(
|
||||||
|
item.stateObj.attributes.unit_of_measurement
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityFilter) {
|
||||||
|
items = items.filter(
|
||||||
|
(item) =>
|
||||||
|
// We always want to include the entity of the current value
|
||||||
|
item.id === value || (item.stateObj && entityFilter!(item.stateObj))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
};
|
||||||
@@ -1,20 +1,14 @@
|
|||||||
import type { Connection, HassEntity } from "home-assistant-js-websocket";
|
import type { Connection } from "home-assistant-js-websocket";
|
||||||
import { createCollection } from "home-assistant-js-websocket";
|
import { createCollection } from "home-assistant-js-websocket";
|
||||||
import type { Store } from "home-assistant-js-websocket/dist/store";
|
import type { Store } from "home-assistant-js-websocket/dist/store";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
import { computeEntityNameList } from "../common/entity/compute_entity_name_display";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
||||||
import { caseInsensitiveStringCompare } from "../common/string/compare";
|
import { debounce } from "../../common/util/debounce";
|
||||||
import { computeRTL } from "../common/util/compute_rtl";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { debounce } from "../common/util/debounce";
|
import type { LightColor } from "../light";
|
||||||
import type { PickerComboBoxItem } from "../components/ha-picker-combo-box";
|
import type { RegistryEntry } from "../registry";
|
||||||
import type { FuseWeightedKey } from "../resources/fuseMultiTerm";
|
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "./entity";
|
|
||||||
import { domainToName } from "./integration";
|
|
||||||
import type { LightColor } from "./light";
|
|
||||||
import type { RegistryEntry } from "./registry";
|
|
||||||
|
|
||||||
type EntityCategory = "config" | "diagnostic";
|
type EntityCategory = "config" | "diagnostic";
|
||||||
|
|
||||||
@@ -330,148 +324,3 @@ export const getAutomaticEntityIds = (
|
|||||||
type: "config/entity_registry/get_automatic_entity_ids",
|
type: "config/entity_registry/get_automatic_entity_ids",
|
||||||
entity_ids,
|
entity_ids,
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface EntityComboBoxItem extends PickerComboBoxItem {
|
|
||||||
domain_name?: string;
|
|
||||||
stateObj?: HassEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const entityComboBoxKeys: FuseWeightedKey[] = [
|
|
||||||
{
|
|
||||||
name: "search_labels.entityName",
|
|
||||||
weight: 10,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.friendlyName",
|
|
||||||
weight: 8,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.deviceName",
|
|
||||||
weight: 7,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.areaName",
|
|
||||||
weight: 6,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.domainName",
|
|
||||||
weight: 6,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "search_labels.entityId",
|
|
||||||
weight: 3,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const getEntities = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
includeDomains?: string[],
|
|
||||||
excludeDomains?: string[],
|
|
||||||
entityFilter?: HaEntityPickerEntityFilterFunc,
|
|
||||||
includeDeviceClasses?: string[],
|
|
||||||
includeUnitOfMeasurement?: string[],
|
|
||||||
includeEntities?: string[],
|
|
||||||
excludeEntities?: string[],
|
|
||||||
value?: string,
|
|
||||||
idPrefix = ""
|
|
||||||
): EntityComboBoxItem[] => {
|
|
||||||
let items: EntityComboBoxItem[] = [];
|
|
||||||
|
|
||||||
let entityIds = Object.keys(hass.states);
|
|
||||||
|
|
||||||
if (includeEntities) {
|
|
||||||
entityIds = entityIds.filter((entityId) =>
|
|
||||||
includeEntities.includes(entityId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludeEntities) {
|
|
||||||
entityIds = entityIds.filter(
|
|
||||||
(entityId) => !excludeEntities.includes(entityId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeDomains) {
|
|
||||||
entityIds = entityIds.filter((eid) =>
|
|
||||||
includeDomains.includes(computeDomain(eid))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (excludeDomains) {
|
|
||||||
entityIds = entityIds.filter(
|
|
||||||
(eid) => !excludeDomains.includes(computeDomain(eid))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
items = entityIds.map<EntityComboBoxItem>((entityId) => {
|
|
||||||
const stateObj = hass.states[entityId];
|
|
||||||
|
|
||||||
const friendlyName = computeStateName(stateObj); // Keep this for search
|
|
||||||
const [entityName, deviceName, areaName] = computeEntityNameList(
|
|
||||||
stateObj,
|
|
||||||
[{ type: "entity" }, { type: "device" }, { type: "area" }],
|
|
||||||
hass.entities,
|
|
||||||
hass.devices,
|
|
||||||
hass.areas,
|
|
||||||
hass.floors
|
|
||||||
);
|
|
||||||
|
|
||||||
const domainName = domainToName(hass.localize, computeDomain(entityId));
|
|
||||||
|
|
||||||
const isRTL = computeRTL(hass);
|
|
||||||
|
|
||||||
const primary = entityName || deviceName || entityId;
|
|
||||||
const secondary = [areaName, entityName ? deviceName : undefined]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(isRTL ? " ◂ " : " ▸ ");
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: `${idPrefix}${entityId}`,
|
|
||||||
primary: primary,
|
|
||||||
secondary: secondary,
|
|
||||||
domain_name: domainName,
|
|
||||||
sorting_label: [deviceName, entityName].filter(Boolean).join("_"),
|
|
||||||
search_labels: {
|
|
||||||
entityName: entityName || null,
|
|
||||||
deviceName: deviceName || null,
|
|
||||||
areaName: areaName || null,
|
|
||||||
domainName: domainName || null,
|
|
||||||
friendlyName: friendlyName || null,
|
|
||||||
entityId: entityId,
|
|
||||||
},
|
|
||||||
stateObj: stateObj,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (includeDeviceClasses) {
|
|
||||||
items = items.filter(
|
|
||||||
(item) =>
|
|
||||||
// We always want to include the entity of the current value
|
|
||||||
item.id === value ||
|
|
||||||
(item.stateObj?.attributes.device_class &&
|
|
||||||
includeDeviceClasses.includes(item.stateObj.attributes.device_class))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeUnitOfMeasurement) {
|
|
||||||
items = items.filter(
|
|
||||||
(item) =>
|
|
||||||
// We always want to include the entity of the current value
|
|
||||||
item.id === value ||
|
|
||||||
(item.stateObj?.attributes.unit_of_measurement &&
|
|
||||||
includeUnitOfMeasurement.includes(
|
|
||||||
item.stateObj.attributes.unit_of_measurement
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entityFilter) {
|
|
||||||
items = items.filter(
|
|
||||||
(item) =>
|
|
||||||
// We always want to include the entity of the current value
|
|
||||||
item.id === value || (item.stateObj && entityFilter!(item.stateObj))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise";
|
import { timeCachePromiseFunc } from "../../common/util/time-cache-function-promise";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
interface EntitySource {
|
interface EntitySource {
|
||||||
domain: string;
|
domain: string;
|
||||||
@@ -56,11 +56,11 @@ import type { HomeAssistant } from "../types";
|
|||||||
import type {
|
import type {
|
||||||
EntityRegistryDisplayEntry,
|
EntityRegistryDisplayEntry,
|
||||||
EntityRegistryEntry,
|
EntityRegistryEntry,
|
||||||
} from "./entity_registry";
|
} from "./entity/entity_registry";
|
||||||
|
|
||||||
import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg";
|
import { mdiHomeAssistant } from "../resources/home-assistant-logo-svg";
|
||||||
import { getTriggerDomain, getTriggerObjectId } from "./trigger";
|
|
||||||
import { getConditionDomain, getConditionObjectId } from "./condition";
|
import { getConditionDomain, getConditionObjectId } from "./condition";
|
||||||
|
import { getTriggerDomain, getTriggerObjectId } from "./trigger";
|
||||||
|
|
||||||
/** Icon to use when no icon specified for service. */
|
/** Icon to use when no icon specified for service. */
|
||||||
export const DEFAULT_SERVICE_ICON = mdiRoomService;
|
export const DEFAULT_SERVICE_ICON = mdiRoomService;
|
||||||
|
|||||||
@@ -1,105 +1,17 @@
|
|||||||
import { mdiLabel } from "@mdi/js";
|
import { mdiLabel } from "@mdi/js";
|
||||||
import type { Connection } from "home-assistant-js-websocket";
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
import { createCollection } from "home-assistant-js-websocket";
|
import type { HaDevicePickerDeviceFilterFunc } from "../../components/device/ha-device-picker";
|
||||||
import type { Store } from "home-assistant-js-websocket/dist/store";
|
import type { PickerComboBoxItem } from "../../components/ha-picker-combo-box";
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import type { FuseWeightedKey } from "../../resources/fuseMultiTerm";
|
||||||
import { stringCompare } from "../common/string/compare";
|
import type { HomeAssistant } from "../../types";
|
||||||
import { debounce } from "../common/util/debounce";
|
|
||||||
import type { HaDevicePickerDeviceFilterFunc } from "../components/device/ha-device-picker";
|
|
||||||
import type { PickerComboBoxItem } from "../components/ha-picker-combo-box";
|
|
||||||
import type { FuseWeightedKey } from "../resources/fuseMultiTerm";
|
|
||||||
import type { HomeAssistant } from "../types";
|
|
||||||
import {
|
import {
|
||||||
getDeviceEntityDisplayLookup,
|
getDeviceEntityDisplayLookup,
|
||||||
type DeviceEntityDisplayLookup,
|
type DeviceEntityDisplayLookup,
|
||||||
type DeviceRegistryEntry,
|
type DeviceRegistryEntry,
|
||||||
} from "./device_registry";
|
} from "../device/device_registry";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "./entity";
|
import type { HaEntityPickerEntityFilterFunc } from "../entity/entity";
|
||||||
import type { EntityRegistryDisplayEntry } from "./entity_registry";
|
import type { EntityRegistryDisplayEntry } from "../entity/entity_registry";
|
||||||
import type { RegistryEntry } from "./registry";
|
import type { LabelRegistryEntry } from "./label_registry";
|
||||||
|
|
||||||
export interface LabelRegistryEntry extends RegistryEntry {
|
|
||||||
label_id: string;
|
|
||||||
name: string;
|
|
||||||
icon: string | null;
|
|
||||||
color: string | null;
|
|
||||||
description: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LabelRegistryEntryMutableParams {
|
|
||||||
name: string;
|
|
||||||
icon?: string | null;
|
|
||||||
color?: string | null;
|
|
||||||
description?: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchLabelRegistry = (conn: Connection) =>
|
|
||||||
conn
|
|
||||||
.sendMessagePromise({
|
|
||||||
type: "config/label_registry/list",
|
|
||||||
})
|
|
||||||
.then((labels) =>
|
|
||||||
(labels as LabelRegistryEntry[]).sort((ent1, ent2) =>
|
|
||||||
stringCompare(ent1.name, ent2.name)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const subscribeLabelRegistryUpdates = (
|
|
||||||
conn: Connection,
|
|
||||||
store: Store<LabelRegistryEntry[]>
|
|
||||||
) =>
|
|
||||||
conn.subscribeEvents(
|
|
||||||
debounce(
|
|
||||||
() =>
|
|
||||||
fetchLabelRegistry(conn).then((labels: LabelRegistryEntry[]) =>
|
|
||||||
store.setState(labels, true)
|
|
||||||
),
|
|
||||||
500,
|
|
||||||
true
|
|
||||||
),
|
|
||||||
"label_registry_updated"
|
|
||||||
);
|
|
||||||
|
|
||||||
export const subscribeLabelRegistry = (
|
|
||||||
conn: Connection,
|
|
||||||
onChange: (labels: LabelRegistryEntry[]) => void
|
|
||||||
) =>
|
|
||||||
createCollection<LabelRegistryEntry[]>(
|
|
||||||
"_labelRegistry",
|
|
||||||
fetchLabelRegistry,
|
|
||||||
subscribeLabelRegistryUpdates,
|
|
||||||
conn,
|
|
||||||
onChange
|
|
||||||
);
|
|
||||||
|
|
||||||
export const createLabelRegistryEntry = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
values: LabelRegistryEntryMutableParams
|
|
||||||
) =>
|
|
||||||
hass.callWS<LabelRegistryEntry>({
|
|
||||||
type: "config/label_registry/create",
|
|
||||||
...values,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const updateLabelRegistryEntry = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
labelId: string,
|
|
||||||
updates: Partial<LabelRegistryEntryMutableParams>
|
|
||||||
) =>
|
|
||||||
hass.callWS<LabelRegistryEntry>({
|
|
||||||
type: "config/label_registry/update",
|
|
||||||
label_id: labelId,
|
|
||||||
...updates,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const deleteLabelRegistryEntry = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
labelId: string
|
|
||||||
) =>
|
|
||||||
hass.callWS({
|
|
||||||
type: "config/label_registry/delete",
|
|
||||||
label_id: labelId,
|
|
||||||
});
|
|
||||||
|
|
||||||
export const labelComboBoxKeys: FuseWeightedKey[] = [
|
export const labelComboBoxKeys: FuseWeightedKey[] = [
|
||||||
{
|
{
|
||||||
90
src/data/label/label_registry.ts
Normal file
90
src/data/label/label_registry.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import type { Connection } from "home-assistant-js-websocket";
|
||||||
|
import { createCollection } from "home-assistant-js-websocket";
|
||||||
|
import type { Store } from "home-assistant-js-websocket/dist/store";
|
||||||
|
import { stringCompare } from "../../common/string/compare";
|
||||||
|
import { debounce } from "../../common/util/debounce";
|
||||||
|
import type { HomeAssistant } from "../../types";
|
||||||
|
import type { RegistryEntry } from "../registry";
|
||||||
|
|
||||||
|
export interface LabelRegistryEntry extends RegistryEntry {
|
||||||
|
label_id: string;
|
||||||
|
name: string;
|
||||||
|
icon: string | null;
|
||||||
|
color: string | null;
|
||||||
|
description: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LabelRegistryEntryMutableParams {
|
||||||
|
name: string;
|
||||||
|
icon?: string | null;
|
||||||
|
color?: string | null;
|
||||||
|
description?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchLabelRegistry = (conn: Connection) =>
|
||||||
|
conn
|
||||||
|
.sendMessagePromise({
|
||||||
|
type: "config/label_registry/list",
|
||||||
|
})
|
||||||
|
.then((labels) =>
|
||||||
|
(labels as LabelRegistryEntry[]).sort((ent1, ent2) =>
|
||||||
|
stringCompare(ent1.name, ent2.name)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
export const subscribeLabelRegistryUpdates = (
|
||||||
|
conn: Connection,
|
||||||
|
store: Store<LabelRegistryEntry[]>
|
||||||
|
) =>
|
||||||
|
conn.subscribeEvents(
|
||||||
|
debounce(
|
||||||
|
() =>
|
||||||
|
fetchLabelRegistry(conn).then((labels: LabelRegistryEntry[]) =>
|
||||||
|
store.setState(labels, true)
|
||||||
|
),
|
||||||
|
500,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
"label_registry_updated"
|
||||||
|
);
|
||||||
|
|
||||||
|
export const subscribeLabelRegistry = (
|
||||||
|
conn: Connection,
|
||||||
|
onChange: (labels: LabelRegistryEntry[]) => void
|
||||||
|
) =>
|
||||||
|
createCollection<LabelRegistryEntry[]>(
|
||||||
|
"_labelRegistry",
|
||||||
|
fetchLabelRegistry,
|
||||||
|
subscribeLabelRegistryUpdates,
|
||||||
|
conn,
|
||||||
|
onChange
|
||||||
|
);
|
||||||
|
|
||||||
|
export const createLabelRegistryEntry = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
values: LabelRegistryEntryMutableParams
|
||||||
|
) =>
|
||||||
|
hass.callWS<LabelRegistryEntry>({
|
||||||
|
type: "config/label_registry/create",
|
||||||
|
...values,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const updateLabelRegistryEntry = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
labelId: string,
|
||||||
|
updates: Partial<LabelRegistryEntryMutableParams>
|
||||||
|
) =>
|
||||||
|
hass.callWS<LabelRegistryEntry>({
|
||||||
|
type: "config/label_registry/update",
|
||||||
|
label_id: labelId,
|
||||||
|
...updates,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const deleteLabelRegistryEntry = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
labelId: string
|
||||||
|
) =>
|
||||||
|
hass.callWS({
|
||||||
|
type: "config/label_registry/delete",
|
||||||
|
label_id: labelId,
|
||||||
|
});
|
||||||
@@ -2,7 +2,7 @@ import type {
|
|||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { UNAVAILABLE } from "./entity";
|
import { UNAVAILABLE } from "./entity/entity";
|
||||||
|
|
||||||
export type LawnMowerEntityState =
|
export type LawnMowerEntityState =
|
||||||
| "paused"
|
| "paused"
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import type {
|
|||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { getExtendedEntityRegistryEntry } from "./entity_registry";
|
|
||||||
import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog";
|
import { showEnterCodeDialog } from "../dialogs/enter-code/show-enter-code-dialog";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { UNAVAILABLE } from "./entity";
|
import { UNAVAILABLE } from "./entity/entity";
|
||||||
|
import { getExtendedEntityRegistryEntry } from "./entity/entity_registry";
|
||||||
|
|
||||||
export const enum LockEntityFeature {
|
export const enum LockEntityFeature {
|
||||||
OPEN = 1,
|
OPEN = 1,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { computeStateDomain } from "../common/entity/compute_state_domain";
|
|||||||
import { autoCaseNoun } from "../common/translations/auto_case_noun";
|
import { autoCaseNoun } from "../common/translations/auto_case_noun";
|
||||||
import type { LocalizeFunc } from "../common/translations/localize";
|
import type { LocalizeFunc } from "../common/translations/localize";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { UNAVAILABLE, UNKNOWN } from "./entity";
|
import { UNAVAILABLE, UNKNOWN } from "./entity/entity";
|
||||||
import { isNumericEntity } from "./history";
|
import { isNumericEntity } from "./history";
|
||||||
|
|
||||||
const LOGBOOK_LOCALIZE_PATH = "ui.components.logbook.messages";
|
const LOGBOOK_LOCALIZE_PATH = "ui.components.logbook.messages";
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
|
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||||
import { navigate } from "../common/navigate";
|
import { navigate } from "../common/navigate";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { subscribeDeviceRegistry } from "./device_registry";
|
import { subscribeDeviceRegistry } from "./device/device_registry";
|
||||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
|
||||||
import { getThreadDataSetTLV, listThreadDataSets } from "./thread";
|
import { getThreadDataSetTLV, listThreadDataSets } from "./thread";
|
||||||
|
|
||||||
export enum NetworkType {
|
export enum NetworkType {
|
||||||
|
|||||||
@@ -32,11 +32,11 @@ import type {
|
|||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { supportsFeature } from "../common/entity/supports-feature";
|
|
||||||
import { stateActive } from "../common/entity/state_active";
|
import { stateActive } from "../common/entity/state_active";
|
||||||
|
import { supportsFeature } from "../common/entity/supports-feature";
|
||||||
import type { MediaPlayerItemId } from "../components/media-player/ha-media-player-browse";
|
import type { MediaPlayerItemId } from "../components/media-player/ha-media-player-browse";
|
||||||
import type { HomeAssistant, TranslationDict } from "../types";
|
import type { HomeAssistant, TranslationDict } from "../types";
|
||||||
import { isUnavailableState } from "./entity";
|
import { isUnavailableState } from "./entity/entity";
|
||||||
import { isTTSMediaSource } from "./tts";
|
import { isTTSMediaSource } from "./tts";
|
||||||
|
|
||||||
interface MediaPlayerEntityAttributes extends HassEntityAttributeBase {
|
interface MediaPlayerEntityAttributes extends HassEntityAttributeBase {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { html, nothing } from "lit";
|
import { html, nothing } from "lit";
|
||||||
|
import "../components/ha-expansion-panel";
|
||||||
import {
|
import {
|
||||||
showAlertDialog,
|
showAlertDialog,
|
||||||
showConfirmationDialog,
|
showConfirmationDialog,
|
||||||
@@ -7,8 +8,7 @@ import type { HomeAssistant } from "../types";
|
|||||||
import {
|
import {
|
||||||
getAutomaticEntityIds,
|
getAutomaticEntityIds,
|
||||||
updateEntityRegistryEntry,
|
updateEntityRegistryEntry,
|
||||||
} from "./entity_registry";
|
} from "./entity/entity_registry";
|
||||||
import "../components/ha-expansion-panel";
|
|
||||||
|
|
||||||
export const regenerateEntityIds = async (
|
export const regenerateEntityIds = async (
|
||||||
element: HTMLElement,
|
element: HTMLElement,
|
||||||
|
|||||||
@@ -1,22 +1,15 @@
|
|||||||
import { ensureArray } from "../common/array/ensure-array";
|
import { ensureArray } from "../common/array/ensure-array";
|
||||||
import { formatNumericDuration } from "../common/datetime/format_duration";
|
import { formatNumericDuration } from "../common/datetime/format_duration";
|
||||||
import secondsToDuration from "../common/datetime/seconds_to_duration";
|
import secondsToDuration from "../common/datetime/seconds_to_duration";
|
||||||
import { computeDeviceNameDisplay } from "../common/entity/compute_device_name";
|
|
||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
import { computeStateName } from "../common/entity/compute_state_name";
|
||||||
import { formatListWithAnds } from "../common/string/format-list";
|
import { formatListWithAnds } from "../common/string/format-list";
|
||||||
import { isTemplate } from "../common/string/has-template";
|
import { isTemplate } from "../common/string/has-template";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import type { Condition } from "./automation";
|
import type { Condition } from "./automation";
|
||||||
import { describeCondition } from "./automation_i18n";
|
import { describeCondition } from "./automation_i18n";
|
||||||
import { localizeDeviceAutomationAction } from "./device_automation";
|
import { localizeDeviceAutomationAction } from "./device/device_automation";
|
||||||
import type { EntityRegistryEntry } from "./entity_registry";
|
import type { EntityRegistryEntry } from "./entity/entity_registry";
|
||||||
import {
|
|
||||||
computeEntityRegistryName,
|
|
||||||
entityRegistryById,
|
|
||||||
} from "./entity_registry";
|
|
||||||
import type { FloorRegistryEntry } from "./floor_registry";
|
|
||||||
import { domainToName } from "./integration";
|
import { domainToName } from "./integration";
|
||||||
import type { LabelRegistryEntry } from "./label_registry";
|
|
||||||
import type {
|
import type {
|
||||||
ActionType,
|
ActionType,
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
@@ -41,8 +34,6 @@ const actionTranslationBaseKey =
|
|||||||
export const describeAction = <T extends ActionType>(
|
export const describeAction = <T extends ActionType>(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entityRegistry: EntityRegistryEntry[],
|
entityRegistry: EntityRegistryEntry[],
|
||||||
labelRegistry: LabelRegistryEntry[],
|
|
||||||
floorRegistry: Record<string, FloorRegistryEntry>,
|
|
||||||
action: ActionTypes[T],
|
action: ActionTypes[T],
|
||||||
actionType?: T,
|
actionType?: T,
|
||||||
ignoreAlias = false
|
ignoreAlias = false
|
||||||
@@ -51,8 +42,6 @@ export const describeAction = <T extends ActionType>(
|
|||||||
const description = tryDescribeAction(
|
const description = tryDescribeAction(
|
||||||
hass,
|
hass,
|
||||||
entityRegistry,
|
entityRegistry,
|
||||||
labelRegistry,
|
|
||||||
floorRegistry,
|
|
||||||
action,
|
action,
|
||||||
actionType,
|
actionType,
|
||||||
ignoreAlias
|
ignoreAlias
|
||||||
@@ -75,8 +64,6 @@ export const describeAction = <T extends ActionType>(
|
|||||||
const tryDescribeAction = <T extends ActionType>(
|
const tryDescribeAction = <T extends ActionType>(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entityRegistry: EntityRegistryEntry[],
|
entityRegistry: EntityRegistryEntry[],
|
||||||
labelRegistry: LabelRegistryEntry[],
|
|
||||||
floorRegistry: Record<string, FloorRegistryEntry>,
|
|
||||||
action: ActionTypes[T],
|
action: ActionTypes[T],
|
||||||
actionType?: T,
|
actionType?: T,
|
||||||
ignoreAlias = false
|
ignoreAlias = false
|
||||||
@@ -100,107 +87,6 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
{ name: "target" }
|
{ name: "target" }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else if (targetOrData) {
|
|
||||||
for (const [key, name] of Object.entries({
|
|
||||||
area_id: "areas",
|
|
||||||
device_id: "devices",
|
|
||||||
entity_id: "entities",
|
|
||||||
floor_id: "floors",
|
|
||||||
label_id: "labels",
|
|
||||||
})) {
|
|
||||||
if (!(key in targetOrData)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const keyConf: string[] = ensureArray(targetOrData[key]) || [];
|
|
||||||
|
|
||||||
for (const targetThing of keyConf) {
|
|
||||||
if (isTemplate(targetThing)) {
|
|
||||||
targets.push(
|
|
||||||
hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.service.description.target_template`,
|
|
||||||
{ name }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
} else if (key === "entity_id") {
|
|
||||||
if (targetThing.includes(".")) {
|
|
||||||
const state = hass.states[targetThing];
|
|
||||||
if (state) {
|
|
||||||
targets.push(computeStateName(state));
|
|
||||||
} else {
|
|
||||||
targets.push(targetThing);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const entityReg = entityRegistryById(entityRegistry)[targetThing];
|
|
||||||
if (entityReg) {
|
|
||||||
targets.push(
|
|
||||||
computeEntityRegistryName(hass, entityReg) || targetThing
|
|
||||||
);
|
|
||||||
} else if (targetThing === "all") {
|
|
||||||
targets.push(
|
|
||||||
hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.service.description.target_every_entity`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
targets.push(
|
|
||||||
hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.service.description.target_unknown_entity`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (key === "device_id") {
|
|
||||||
const device = hass.devices[targetThing];
|
|
||||||
if (device) {
|
|
||||||
targets.push(computeDeviceNameDisplay(device, hass));
|
|
||||||
} else {
|
|
||||||
targets.push(
|
|
||||||
hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.service.description.target_unknown_device`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (key === "area_id") {
|
|
||||||
const area = hass.areas[targetThing];
|
|
||||||
if (area?.name) {
|
|
||||||
targets.push(area.name);
|
|
||||||
} else {
|
|
||||||
targets.push(
|
|
||||||
hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.service.description.target_unknown_area`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (key === "floor_id") {
|
|
||||||
const floor = floorRegistry[targetThing] ?? undefined;
|
|
||||||
if (floor?.name) {
|
|
||||||
targets.push(floor.name);
|
|
||||||
} else {
|
|
||||||
targets.push(
|
|
||||||
hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.service.description.target_unknown_floor`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (key === "label_id") {
|
|
||||||
const label = labelRegistry.find(
|
|
||||||
(lbl) => lbl.label_id === targetThing
|
|
||||||
);
|
|
||||||
if (label?.name) {
|
|
||||||
targets.push(label.name);
|
|
||||||
} else {
|
|
||||||
targets.push(
|
|
||||||
hass.localize(
|
|
||||||
`${actionTranslationBaseKey}.service.description.target_unknown_label`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
targets.push(targetThing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -229,26 +115,20 @@ const tryDescribeAction = <T extends ActionType>(
|
|||||||
|
|
||||||
if (config.metadata) {
|
if (config.metadata) {
|
||||||
return hass.localize(
|
return hass.localize(
|
||||||
targets.length
|
`${actionTranslationBaseKey}.service.description.service_name_no_targets`,
|
||||||
? `${actionTranslationBaseKey}.service.description.service_name`
|
|
||||||
: `${actionTranslationBaseKey}.service.description.service_name_no_targets`,
|
|
||||||
{
|
{
|
||||||
domain: domainToName(hass.localize, domain),
|
domain: domainToName(hass.localize, domain),
|
||||||
name: service || config.action,
|
name: service || config.action,
|
||||||
targets: formatListWithAnds(hass.locale, targets),
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hass.localize(
|
return hass.localize(
|
||||||
targets.length
|
`${actionTranslationBaseKey}.service.description.service_based_on_name_no_targets`,
|
||||||
? `${actionTranslationBaseKey}.service.description.service_based_on_name`
|
|
||||||
: `${actionTranslationBaseKey}.service.description.service_based_on_name_no_targets`,
|
|
||||||
{
|
{
|
||||||
name: service
|
name: service
|
||||||
? `${domainToName(hass.localize, domain)}: ${service}`
|
? `${domainToName(hass.localize, domain)}: ${service}`
|
||||||
: config.action,
|
: config.action,
|
||||||
targets: formatListWithAnds(hass.locale, targets),
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type {
|
|||||||
HassServiceTarget,
|
HassServiceTarget,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { ensureArray } from "../common/array/ensure-array";
|
import { ensureArray } from "../common/array/ensure-array";
|
||||||
|
import type { EntityNameItem } from "../common/entity/compute_entity_name_display";
|
||||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||||
import { supportsFeature } from "../common/entity/supports-feature";
|
import { supportsFeature } from "../common/entity/supports-feature";
|
||||||
import { isHelperDomain } from "../panels/config/helpers/const";
|
import { isHelperDomain } from "../panels/config/helpers/const";
|
||||||
@@ -11,13 +12,12 @@ import type { HomeAssistant } from "../types";
|
|||||||
import {
|
import {
|
||||||
type DeviceRegistryEntry,
|
type DeviceRegistryEntry,
|
||||||
getDeviceIntegrationLookup,
|
getDeviceIntegrationLookup,
|
||||||
} from "./device_registry";
|
} from "./device/device_registry";
|
||||||
import type {
|
import type {
|
||||||
EntityRegistryDisplayEntry,
|
EntityRegistryDisplayEntry,
|
||||||
EntityRegistryEntry,
|
EntityRegistryEntry,
|
||||||
} from "./entity_registry";
|
} from "./entity/entity_registry";
|
||||||
import type { EntitySources } from "./entity_sources";
|
import type { EntitySources } from "./entity/entity_sources";
|
||||||
import type { EntityNameItem } from "../common/entity/compute_entity_name_display";
|
|
||||||
|
|
||||||
export type Selector =
|
export type Selector =
|
||||||
| ActionSelector
|
| ActionSelector
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ import { computeDomain } from "../common/entity/compute_domain";
|
|||||||
import type { HaDevicePickerDeviceFilterFunc } from "../components/device/ha-device-picker";
|
import type { HaDevicePickerDeviceFilterFunc } from "../components/device/ha-device-picker";
|
||||||
import type { PickerComboBoxItem } from "../components/ha-picker-combo-box";
|
import type { PickerComboBoxItem } from "../components/ha-picker-combo-box";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import type { FloorComboBoxItem } from "./area_floor";
|
import type { FloorComboBoxItem } from "./area_floor_picker";
|
||||||
import type { AreaRegistryEntry } from "./area_registry";
|
import type { AreaRegistryEntry } from "./area_registry";
|
||||||
import type { DevicePickerItem, DeviceRegistryEntry } from "./device_registry";
|
import type { DevicePickerItem } from "./device/device_picker";
|
||||||
import type { HaEntityPickerEntityFilterFunc } from "./entity";
|
import type { DeviceRegistryEntry } from "./device/device_registry";
|
||||||
import type {
|
import type { HaEntityPickerEntityFilterFunc } from "./entity/entity";
|
||||||
EntityComboBoxItem,
|
import type { EntityComboBoxItem } from "./entity/entity_picker";
|
||||||
EntityRegistryDisplayEntry,
|
import type { EntityRegistryDisplayEntry } from "./entity/entity_registry";
|
||||||
} from "./entity_registry";
|
|
||||||
|
|
||||||
export const TARGET_SEPARATOR = "________";
|
export const TARGET_SEPARATOR = "________";
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { HomeAssistant, ServiceCallResponse } from "../types";
|
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
import { computeStateName } from "../common/entity/compute_state_name";
|
||||||
import { isUnavailableState } from "./entity";
|
|
||||||
import { stringCompare } from "../common/string/compare";
|
import { stringCompare } from "../common/string/compare";
|
||||||
|
import type { HomeAssistant, ServiceCallResponse } from "../types";
|
||||||
|
import { isUnavailableState } from "./entity/entity";
|
||||||
|
|
||||||
export interface TodoList {
|
export interface TodoList {
|
||||||
entity_id: string;
|
entity_id: string;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type {
|
|||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
HassEvent,
|
HassEvent,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { BINARY_STATE_ON, BINARY_STATE_OFF } from "../common/const";
|
import { BINARY_STATE_OFF, BINARY_STATE_ON } from "../common/const";
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||||
import { supportsFeature } from "../common/entity/supports-feature";
|
import { supportsFeature } from "../common/entity/supports-feature";
|
||||||
@@ -13,7 +13,7 @@ import { caseInsensitiveStringCompare } from "../common/string/compare";
|
|||||||
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import { showToast } from "../util/toast";
|
import { showToast } from "../util/toast";
|
||||||
import type { EntitySources } from "./entity_sources";
|
import type { EntitySources } from "./entity/entity_sources";
|
||||||
|
|
||||||
export enum UpdateEntityFeature {
|
export enum UpdateEntityFeature {
|
||||||
INSTALL = 1,
|
INSTALL = 1,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type {
|
|||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { UNAVAILABLE } from "./entity";
|
import { UNAVAILABLE } from "./entity/entity";
|
||||||
|
|
||||||
export type VacuumEntityState =
|
export type VacuumEntityState =
|
||||||
| "on"
|
| "on"
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import type {
|
|||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { UNAVAILABLE } from "./entity";
|
|
||||||
import { stateActive } from "../common/entity/state_active";
|
import { stateActive } from "../common/entity/state_active";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
|
import { UNAVAILABLE } from "./entity/entity";
|
||||||
|
|
||||||
export const enum ValveEntityFeature {
|
export const enum ValveEntityFeature {
|
||||||
OPEN = 1,
|
OPEN = 1,
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { Connection } from "home-assistant-js-websocket";
|
import type { Connection } from "home-assistant-js-websocket";
|
||||||
import { createCollection } from "home-assistant-js-websocket";
|
import { createCollection } from "home-assistant-js-websocket";
|
||||||
import type { Store } from "home-assistant-js-websocket/dist/store";
|
import type { Store } from "home-assistant-js-websocket/dist/store";
|
||||||
import type { DeviceRegistryEntry } from "./device_registry";
|
|
||||||
import { debounce } from "../common/util/debounce";
|
import { debounce } from "../common/util/debounce";
|
||||||
|
import type { DeviceRegistryEntry } from "./device/device_registry";
|
||||||
|
|
||||||
export const fetchDeviceRegistry = (conn: Connection) =>
|
export const fetchDeviceRegistry = (conn: Connection) =>
|
||||||
conn.sendMessagePromise<DeviceRegistryEntry[]>({
|
conn.sendMessagePromise<DeviceRegistryEntry[]>({
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user