mirror of
https://github.com/home-assistant/frontend.git
synced 2026-05-13 04:36:53 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ad54953ef | |||
| c82f8c6090 | |||
| 0e3f712a3b | |||
| 7c12ee3cae | |||
| e0feb3a7f1 | |||
| 60e95b886c |
@@ -22,6 +22,14 @@ const isOn = (stateObj?: HassEntity) =>
|
||||
!STATES_OFF.includes(stateObj.state) &&
|
||||
!isUnavailableState(stateObj.state);
|
||||
|
||||
/**
|
||||
* @element ha-entity-toggle
|
||||
*
|
||||
* @cssprop --ha-entity-toggle-switch-width - Width of the switch track. Defaults to `38px`.
|
||||
* @cssprop --ha-entity-toggle-switch-size - Height of the switch track. Defaults to `20px`.
|
||||
* @cssprop --ha-entity-toggle-switch-thumb-size - Size of the switch thumb. Defaults to `14px`.
|
||||
*/
|
||||
|
||||
@customElement("ha-entity-toggle")
|
||||
export class HaEntityToggle extends LitElement {
|
||||
// hass is not a property so that we only re-render on stateObj changes
|
||||
@@ -165,9 +173,9 @@ export class HaEntityToggle extends LitElement {
|
||||
white-space: nowrap;
|
||||
}
|
||||
ha-switch {
|
||||
--ha-switch-width: 38px;
|
||||
--ha-switch-size: 20px;
|
||||
--ha-switch-thumb-size: 14px;
|
||||
--ha-switch-width: var(--ha-entity-toggle-switch-width, 38px);
|
||||
--ha-switch-size: var(--ha-entity-toggle-switch-size, 20px);
|
||||
--ha-switch-thumb-size: var(--ha-entity-toggle-switch-thumb-size, 14px);
|
||||
}
|
||||
ha-icon-button {
|
||||
--ha-icon-button-size: 40px;
|
||||
|
||||
@@ -3,24 +3,29 @@ import {
|
||||
mdiClipboardTextMultipleOutline,
|
||||
mdiInformationOutline,
|
||||
} from "@mdi/js";
|
||||
import { consume, type ContextType } from "@lit/context";
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { dump } from "js-yaml";
|
||||
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeAreaName } from "../../../../common/entity/compute_area_name";
|
||||
import { computeDeviceName } from "../../../../common/entity/compute_device_name";
|
||||
import { computeEntityEntryName } from "../../../../common/entity/compute_entity_name";
|
||||
import { copyToClipboard } from "../../../../common/util/copy-clipboard";
|
||||
import "../../../../components/ha-svg-icon";
|
||||
import {
|
||||
internationalizationContext,
|
||||
registriesContext,
|
||||
} from "../../../../data/context";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import { loadVirtualizer } from "../../../../resources/virtualizer";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { showToast } from "../../../../util/toast";
|
||||
|
||||
@customElement("developer-tools-state-renderer")
|
||||
class HaPanelDevStateRenderer extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public entities: HassEntity[] = [];
|
||||
|
||||
@property({ type: Boolean, attribute: "narrow" })
|
||||
@@ -32,7 +37,15 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
@property({ attribute: false })
|
||||
public showAttributes = true;
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues<this>) {
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
private _i18n!: ContextType<typeof internationalizationContext>;
|
||||
|
||||
@state()
|
||||
@consume({ context: registriesContext, subscribe: true })
|
||||
private _registries!: ContextType<typeof registriesContext>;
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues) {
|
||||
super.willUpdate(changedProps);
|
||||
if (
|
||||
(!this.hasUpdated && this.virtualize) ||
|
||||
@@ -42,87 +55,90 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues<this>) {
|
||||
super.shouldUpdate(changedProps);
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
const languageChanged =
|
||||
oldHass === undefined || oldHass.locale !== this.hass.locale;
|
||||
|
||||
return (
|
||||
changedProps.has("entities") ||
|
||||
changedProps.has("narrow") ||
|
||||
changedProps.has("virtualize") ||
|
||||
changedProps.has("showAttributes") ||
|
||||
languageChanged
|
||||
);
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const showAttributes = !this.narrow && this.showAttributes;
|
||||
return html`
|
||||
<div
|
||||
class=${classMap({ entities: true, "hide-attributes": !showAttributes })}
|
||||
role="table"
|
||||
>
|
||||
<div class="row" role="row" aria-rowindex="1">
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.entity"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.state"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.attributes"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class=${classMap({
|
||||
entities: true,
|
||||
"hide-attributes": !showAttributes,
|
||||
"hide-extra": this.narrow,
|
||||
})}
|
||||
role="table"
|
||||
>
|
||||
<div class="row" role="row" aria-rowindex="1">
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.entity"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div class="row filters" role="row" aria-rowindex="2">
|
||||
<div class="header filter-entities" role="columnheader">
|
||||
<slot name="filter-entities"></slot>
|
||||
</div></span>
|
||||
<div class="header filter-states" role="columnheader">
|
||||
<slot name="filter-states"></slot>
|
||||
</div>
|
||||
<div class="header filter-attributes" role="columnheader">
|
||||
<slot name="filter-attributes"></slot>
|
||||
</div>
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.state"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.entities.picker.headers.device"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this._i18n.localize("ui.panel.config.generic.headers.area")}
|
||||
</span>
|
||||
</div>
|
||||
<div class="header" role="columnheader">
|
||||
<span class="padded">
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.attributes"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
${
|
||||
this.entities.length === 0
|
||||
? html` <div class="row" role="row" aria-rowindex="3">
|
||||
<div class="cell" role="cell" aria-colspan="3">
|
||||
<span class="padded">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.no_entities"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>`
|
||||
: nothing
|
||||
}
|
||||
${
|
||||
this.virtualize
|
||||
? html`<lit-virtualizer
|
||||
.items=${this.entities}
|
||||
.renderItem=${this._renderStateItem}
|
||||
>
|
||||
</lit-virtualizer>`
|
||||
: this.entities.map((item, index) =>
|
||||
this._renderStateItem(item, index)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<div class="row filters" role="row" aria-rowindex="2">
|
||||
<div class="header filter-entities" role="columnheader">
|
||||
<slot name="filter-entities"></slot>
|
||||
</div>
|
||||
<div class="header filter-states" role="columnheader">
|
||||
<slot name="filter-states"></slot>
|
||||
</div>
|
||||
<div class="header filter-devices" role="columnheader">
|
||||
<slot name="filter-devices"></slot>
|
||||
</div>
|
||||
<div class="header filter-areas" role="columnheader">
|
||||
<slot name="filter-areas"></slot>
|
||||
</div>
|
||||
<div class="header filter-attributes" role="columnheader">
|
||||
<slot name="filter-attributes"></slot>
|
||||
</div>
|
||||
</div>
|
||||
${this.entities.length === 0
|
||||
? html` <div class="row" role="row" aria-rowindex="3">
|
||||
<div class="cell" role="cell" aria-colspan="5">
|
||||
<span class="padded">
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.no_entities"
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
</div>`
|
||||
: nothing}
|
||||
${this.virtualize
|
||||
? html`<lit-virtualizer
|
||||
.items=${this.entities}
|
||||
.renderItem=${this._renderStateItem}
|
||||
>
|
||||
</lit-virtualizer>`
|
||||
: this.entities.map((item, index) =>
|
||||
this._renderStateItem(item, index)
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -133,6 +149,20 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
if (!item || index === undefined) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const entry = this._registries?.entities?.[item.entity_id];
|
||||
const device = entry?.device_id
|
||||
? this._registries?.devices?.[entry.device_id]
|
||||
: undefined;
|
||||
const areaId = entry?.area_id || device?.area_id;
|
||||
const area = areaId ? this._registries?.areas?.[areaId] : undefined;
|
||||
|
||||
const displayName = entry
|
||||
? computeEntityEntryName(entry, this._registries.devices, item)
|
||||
: undefined;
|
||||
const deviceName = device ? computeDeviceName(device) : undefined;
|
||||
const areaName = area ? computeAreaName(area) : undefined;
|
||||
|
||||
return html`
|
||||
<div
|
||||
class=${classMap({
|
||||
@@ -150,10 +180,10 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
<ha-svg-icon
|
||||
@click=${this._copyEntity}
|
||||
.entity=${item}
|
||||
alt=${this.hass.localize(
|
||||
alt=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.copy_id"
|
||||
)}
|
||||
title=${this.hass.localize(
|
||||
title=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.copy_id"
|
||||
)}
|
||||
.path=${mdiClipboardTextMultipleOutline}
|
||||
@@ -166,16 +196,16 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
<ha-svg-icon
|
||||
@click=${this._entityMoreInfo}
|
||||
.entity=${item}
|
||||
alt=${this.hass.localize(
|
||||
alt=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.more_info"
|
||||
)}
|
||||
title=${this.hass.localize(
|
||||
title=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.more_info"
|
||||
)}
|
||||
.path=${mdiInformationOutline}
|
||||
></ha-svg-icon>
|
||||
<span class="secondary">
|
||||
${item.attributes.friendly_name}
|
||||
${displayName ?? deviceName ?? item.attributes.friendly_name}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -184,6 +214,12 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
<div class="cell" role="cell">
|
||||
<span class="padded">${item.state}</span>
|
||||
</div>
|
||||
<div class="cell" role="cell">
|
||||
<span class="padded">${deviceName ?? "\u2014"}</span>
|
||||
</div>
|
||||
<div class="cell" role="cell">
|
||||
<span class="padded">${areaName ?? "\u2014"}</span>
|
||||
</div>
|
||||
<div class="cell" role="cell">
|
||||
<span class="padded">${this._attributeString(item)}</span>
|
||||
</div>
|
||||
@@ -214,26 +250,29 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
return output;
|
||||
}
|
||||
|
||||
private _copyEntity = async (ev) => {
|
||||
private _copyEntity = async (ev: Event) => {
|
||||
ev.preventDefault();
|
||||
const entity = (ev.currentTarget! as any).entity;
|
||||
const entity = (ev.currentTarget as HTMLElement & { entity: HassEntity })
|
||||
.entity;
|
||||
await copyToClipboard(entity.entity_id, document.body);
|
||||
showToast(this, {
|
||||
message: this.hass.localize("ui.common.copied_clipboard"),
|
||||
message: this._i18n.localize("ui.common.copied_clipboard"),
|
||||
});
|
||||
};
|
||||
|
||||
private _entityMoreInfo(ev) {
|
||||
private _entityMoreInfo(ev: Event) {
|
||||
ev.preventDefault();
|
||||
const entity = (ev.currentTarget! as any).entity;
|
||||
const entity = (ev.currentTarget as HTMLElement & { entity: HassEntity })
|
||||
.entity;
|
||||
fireEvent(this, "hass-more-info", { entityId: entity.entity_id });
|
||||
}
|
||||
|
||||
private _entitySelected(ev) {
|
||||
private _entitySelected(ev: Event) {
|
||||
ev.preventDefault();
|
||||
const entity = (ev.currentTarget! as any).entity;
|
||||
const entity = (ev.currentTarget as HTMLElement & { entity: HassEntity })
|
||||
.entity;
|
||||
fireEvent(this, "states-tool-entity-selected", {
|
||||
entity: entity,
|
||||
entity,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -307,12 +346,12 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.entities .row .header:nth-child(3),
|
||||
.entities .row .cell:nth-child(3) {
|
||||
.entities .row .header:nth-child(5),
|
||||
.entities .row .cell:nth-child(5) {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.entities .row .cell:nth-child(3) {
|
||||
.entities .row .cell:nth-child(5) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
@@ -320,8 +359,20 @@ class HaPanelDevStateRenderer extends LitElement {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hide-attributes .row .header:nth-child(3),
|
||||
.hide-attributes .row .cell:nth-child(3) {
|
||||
.hide-attributes .row .header:nth-child(5),
|
||||
.hide-attributes .row .cell:nth-child(5) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hide-extra .row .header:nth-child(3),
|
||||
.hide-extra .row .cell:nth-child(3),
|
||||
.hide-extra .row .header:nth-child(4),
|
||||
.hide-extra .row .cell:nth-child(4) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hide-extra .filter-devices,
|
||||
.hide-extra .filter-areas {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { mdiContentCopy, mdiRefresh } from "@mdi/js";
|
||||
import { consume, type ContextType } from "@lit/context";
|
||||
import { addHours } from "date-fns";
|
||||
import type {
|
||||
HassEntities,
|
||||
@@ -12,6 +13,8 @@ import memoizeOne from "memoize-one";
|
||||
import { formatDateTimeWithSeconds } from "../../../../common/datetime/format_date_time";
|
||||
import { storage } from "../../../../common/decorators/storage";
|
||||
import { escapeRegExp } from "../../../../common/string/escape_regexp";
|
||||
import { computeAreaName } from "../../../../common/entity/compute_area_name";
|
||||
import { computeDeviceName } from "../../../../common/entity/compute_device_name";
|
||||
import { copyToClipboard } from "../../../../common/util/copy-clipboard";
|
||||
import "../../../../components/entity/ha-entity-picker";
|
||||
import "../../../../components/ha-alert";
|
||||
@@ -28,9 +31,16 @@ import "../../../../components/input/ha-input";
|
||||
import type { HaInput } from "../../../../components/input/ha-input";
|
||||
import "../../../../components/input/ha-input-search";
|
||||
import type { HaInputSearch } from "../../../../components/input/ha-input-search";
|
||||
import {
|
||||
apiContext,
|
||||
configContext,
|
||||
internationalizationContext,
|
||||
registriesContext,
|
||||
statesContext,
|
||||
} from "../../../../data/context";
|
||||
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { HomeAssistant, HomeAssistantRegistries } from "../../../../types";
|
||||
import { showToast } from "../../../../util/toast";
|
||||
import "./developer-tools-state-renderer";
|
||||
|
||||
@@ -55,6 +65,10 @@ class HaPanelDevState extends LitElement {
|
||||
|
||||
@state() private _attributeFilter = "";
|
||||
|
||||
@state() private _deviceFilter = "";
|
||||
|
||||
@state() private _areaFilter = "";
|
||||
|
||||
@state() private _entity?: HassEntity;
|
||||
|
||||
@state() private _state = "";
|
||||
@@ -75,6 +89,26 @@ class HaPanelDevState extends LitElement {
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public narrow = false;
|
||||
|
||||
@state()
|
||||
@consume({ context: apiContext, subscribe: true })
|
||||
private _api!: ContextType<typeof apiContext>;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
private _config!: ContextType<typeof configContext>;
|
||||
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
private _i18n!: ContextType<typeof internationalizationContext>;
|
||||
|
||||
@state()
|
||||
@consume({ context: registriesContext, subscribe: true })
|
||||
private _registries!: ContextType<typeof registriesContext>;
|
||||
|
||||
@state()
|
||||
@consume({ context: statesContext, subscribe: true })
|
||||
private _states!: ContextType<typeof statesContext>;
|
||||
|
||||
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
|
||||
|
||||
private _filteredEntities = memoizeOne(
|
||||
@@ -82,13 +116,23 @@ class HaPanelDevState extends LitElement {
|
||||
entityFilter: string,
|
||||
stateFilter: string,
|
||||
attributeFilter: string,
|
||||
states: HassEntities
|
||||
deviceFilter: string,
|
||||
areaFilter: string,
|
||||
states: HassEntities,
|
||||
entities: HomeAssistantRegistries["entities"],
|
||||
devices: HomeAssistantRegistries["devices"],
|
||||
areas: HomeAssistantRegistries["areas"]
|
||||
): HassEntity[] =>
|
||||
this._applyFiltersOnEntities(
|
||||
entityFilter,
|
||||
stateFilter,
|
||||
attributeFilter,
|
||||
states
|
||||
deviceFilter,
|
||||
areaFilter,
|
||||
states,
|
||||
entities,
|
||||
devices,
|
||||
areas
|
||||
)
|
||||
);
|
||||
|
||||
@@ -97,13 +141,18 @@ class HaPanelDevState extends LitElement {
|
||||
this._entityFilter,
|
||||
this._stateFilter,
|
||||
this._attributeFilter,
|
||||
this.hass.states
|
||||
this._deviceFilter,
|
||||
this._areaFilter,
|
||||
this._states,
|
||||
this._registries.entities,
|
||||
this._registries.devices,
|
||||
this._registries.areas
|
||||
);
|
||||
|
||||
return html`
|
||||
<div class="heading">
|
||||
<h1>
|
||||
${this.hass.localize(
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.current_entities"
|
||||
)}
|
||||
</h1>
|
||||
@@ -112,14 +161,14 @@ class HaPanelDevState extends LitElement {
|
||||
.checked=${this._showAttributes}
|
||||
@change=${this._saveAttributeCheckboxState}
|
||||
>
|
||||
${this.hass.localize(
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.attributes"
|
||||
)}
|
||||
</ha-checkbox>`
|
||||
: nothing}
|
||||
</div>
|
||||
<ha-expansion-panel
|
||||
.header=${this.hass.localize(
|
||||
.header=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.set_state"
|
||||
)}
|
||||
outlined
|
||||
@@ -127,10 +176,10 @@ class HaPanelDevState extends LitElement {
|
||||
@expanded-changed=${this._expandedChanged}
|
||||
>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.description1"
|
||||
)}<br />
|
||||
${this.hass.localize(
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.description2"
|
||||
)}
|
||||
</p>
|
||||
@@ -153,7 +202,7 @@ class HaPanelDevState extends LitElement {
|
||||
<ha-icon-button
|
||||
.path=${mdiContentCopy}
|
||||
@click=${this._copyStateEntity}
|
||||
title=${this.hass.localize(
|
||||
title=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.copy_id"
|
||||
)}
|
||||
></ha-icon-button>
|
||||
@@ -161,7 +210,7 @@ class HaPanelDevState extends LitElement {
|
||||
`
|
||||
: nothing}
|
||||
<ha-input
|
||||
.label=${this.hass.localize(
|
||||
.label=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.state"
|
||||
)}
|
||||
required
|
||||
@@ -174,7 +223,7 @@ class HaPanelDevState extends LitElement {
|
||||
class="state-input"
|
||||
></ha-input>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.state_attributes"
|
||||
)}
|
||||
</p>
|
||||
@@ -190,13 +239,13 @@ class HaPanelDevState extends LitElement {
|
||||
@click=${this._handleSetState}
|
||||
.disabled=${!this._validJSON}
|
||||
raised
|
||||
>${this.hass.localize(
|
||||
>${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.set_state"
|
||||
)}</ha-button
|
||||
>
|
||||
<ha-icon-button
|
||||
@click=${this._updateEntity}
|
||||
.label=${this.hass.localize("ui.common.refresh")}
|
||||
.label=${this._i18n.localize("ui.common.refresh")}
|
||||
.path=${mdiRefresh}
|
||||
></ha-icon-button>
|
||||
</div>
|
||||
@@ -205,7 +254,7 @@ class HaPanelDevState extends LitElement {
|
||||
${this._entity
|
||||
? html`<p>
|
||||
<b
|
||||
>${this.hass.localize(
|
||||
>${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.last_changed"
|
||||
)}:</b
|
||||
><br />
|
||||
@@ -215,7 +264,7 @@ class HaPanelDevState extends LitElement {
|
||||
</p>
|
||||
<p>
|
||||
<b
|
||||
>${this.hass.localize(
|
||||
>${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.last_updated"
|
||||
)}:</b
|
||||
><br />
|
||||
@@ -228,7 +277,6 @@ class HaPanelDevState extends LitElement {
|
||||
</div>
|
||||
</ha-expansion-panel>
|
||||
<developer-tools-state-renderer
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.entities=${entities}
|
||||
.virtualize=${entities.length > VIRTUALIZE_THRESHOLD}
|
||||
@@ -237,7 +285,7 @@ class HaPanelDevState extends LitElement {
|
||||
>
|
||||
<ha-input-search
|
||||
slot="filter-entities"
|
||||
.label=${this.hass.localize(
|
||||
.label=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.filter_entities"
|
||||
)}
|
||||
.value=${this._entityFilter}
|
||||
@@ -245,16 +293,32 @@ class HaPanelDevState extends LitElement {
|
||||
></ha-input-search>
|
||||
<ha-input-search
|
||||
slot="filter-states"
|
||||
.label=${this.hass.localize(
|
||||
.label=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.filter_states"
|
||||
)}
|
||||
type="search"
|
||||
.value=${this._stateFilter}
|
||||
@input=${this._stateFilterChanged}
|
||||
></ha-input-search>
|
||||
<ha-input-search
|
||||
slot="filter-devices"
|
||||
.label=${this._i18n.localize(
|
||||
"ui.panel.config.entities.picker.headers.device"
|
||||
)}
|
||||
type="search"
|
||||
.value=${this._deviceFilter}
|
||||
@input=${this._deviceFilterChanged}
|
||||
></ha-input-search>
|
||||
<ha-input-search
|
||||
slot="filter-areas"
|
||||
.label=${this._i18n.localize("ui.panel.config.generic.headers.area")}
|
||||
type="search"
|
||||
.value=${this._areaFilter}
|
||||
@input=${this._areaFilterChanged}
|
||||
></ha-input-search>
|
||||
<ha-input-search
|
||||
slot="filter-attributes"
|
||||
.label=${this.hass.localize(
|
||||
.label=${this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.filter_attributes"
|
||||
)}
|
||||
type="search"
|
||||
@@ -269,7 +333,7 @@ class HaPanelDevState extends LitElement {
|
||||
ev.preventDefault();
|
||||
await copyToClipboard(this._entityId);
|
||||
showToast(this, {
|
||||
message: this.hass.localize("ui.common.copied_clipboard"),
|
||||
message: this._i18n.localize("ui.common.copied_clipboard"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -296,7 +360,7 @@ class HaPanelDevState extends LitElement {
|
||||
|
||||
private _updateEntity() {
|
||||
const entityState = this._entityId
|
||||
? this.hass.states[this._entityId]
|
||||
? this._states[this._entityId]
|
||||
: undefined;
|
||||
if (!entityState) {
|
||||
this._entity = undefined;
|
||||
@@ -328,6 +392,14 @@ class HaPanelDevState extends LitElement {
|
||||
this._attributeFilter = (ev.target as HaInputSearch).value ?? "";
|
||||
}
|
||||
|
||||
private _deviceFilterChanged(ev: InputEvent) {
|
||||
this._deviceFilter = (ev.target as HaInputSearch).value ?? "";
|
||||
}
|
||||
|
||||
private _areaFilterChanged(ev: InputEvent) {
|
||||
this._areaFilter = (ev.target as HaInputSearch).value ?? "";
|
||||
}
|
||||
|
||||
private _getHistoryURL(entityId, inputDate) {
|
||||
const date = new Date(inputDate);
|
||||
const hourBefore = addHours(date, -1).toISOString();
|
||||
@@ -358,7 +430,7 @@ class HaPanelDevState extends LitElement {
|
||||
this._error = "";
|
||||
if (!this._entityId) {
|
||||
showAlertDialog(this, {
|
||||
text: this.hass.localize(
|
||||
text: this._i18n.localize(
|
||||
"ui.panel.config.developer-tools.tabs.states.alert_entity_field"
|
||||
),
|
||||
});
|
||||
@@ -366,7 +438,7 @@ class HaPanelDevState extends LitElement {
|
||||
}
|
||||
this._updateEditor();
|
||||
try {
|
||||
await this.hass.callApi("POST", "states/" + this._entityId, {
|
||||
await this._api.callApi("POST", "states/" + this._entityId, {
|
||||
state: this._state,
|
||||
attributes: this._stateAttributes,
|
||||
});
|
||||
@@ -379,7 +451,12 @@ class HaPanelDevState extends LitElement {
|
||||
entityFilter: string,
|
||||
stateFilter: string,
|
||||
attributeFilter: string,
|
||||
states: HassEntities
|
||||
deviceFilter: string,
|
||||
areaFilter: string,
|
||||
states: HassEntities,
|
||||
entities: HomeAssistantRegistries["entities"],
|
||||
devices: HomeAssistantRegistries["devices"],
|
||||
areas: HomeAssistantRegistries["areas"]
|
||||
) {
|
||||
const entityFilterRegExp =
|
||||
entityFilter &&
|
||||
@@ -389,6 +466,14 @@ class HaPanelDevState extends LitElement {
|
||||
stateFilter &&
|
||||
RegExp(escapeRegExp(stateFilter).replace(/\\\*/g, ".*"), "i");
|
||||
|
||||
const deviceFilterRegExp =
|
||||
deviceFilter &&
|
||||
RegExp(escapeRegExp(deviceFilter).replace(/\\\*/g, ".*"), "i");
|
||||
|
||||
const areaFilterRegExp =
|
||||
areaFilter &&
|
||||
RegExp(escapeRegExp(areaFilter).replace(/\\\*/g, ".*"), "i");
|
||||
|
||||
let keyFilterRegExp;
|
||||
let valueFilterRegExp;
|
||||
let multiMode = false;
|
||||
@@ -428,6 +513,30 @@ class HaPanelDevState extends LitElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (deviceFilterRegExp) {
|
||||
const entry = entities[value.entity_id];
|
||||
const device = entry?.device_id
|
||||
? devices[entry.device_id]
|
||||
: undefined;
|
||||
const deviceName = device ? computeDeviceName(device) : undefined;
|
||||
if (!deviceName || !deviceFilterRegExp.test(deviceName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (areaFilterRegExp) {
|
||||
const entry = entities[value.entity_id];
|
||||
const device = entry?.device_id
|
||||
? devices[entry.device_id]
|
||||
: undefined;
|
||||
const areaId = entry?.area_id || device?.area_id;
|
||||
const area = areaId ? areas[areaId] : undefined;
|
||||
const areaName = area ? computeAreaName(area) : undefined;
|
||||
if (!areaName || !areaFilterRegExp.test(areaName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (keyFilterRegExp && valueFilterRegExp) {
|
||||
for (const [key, attributeValue] of Object.entries(
|
||||
value.attributes
|
||||
@@ -468,16 +577,16 @@ class HaPanelDevState extends LitElement {
|
||||
private _lastChangedString(entity) {
|
||||
return formatDateTimeWithSeconds(
|
||||
new Date(entity.last_changed),
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
this._i18n.locale,
|
||||
this._config.config
|
||||
);
|
||||
}
|
||||
|
||||
private _lastUpdatedString(entity) {
|
||||
return formatDateTimeWithSeconds(
|
||||
new Date(entity.last_updated),
|
||||
this.hass.locale,
|
||||
this.hass.config
|
||||
this._i18n.locale,
|
||||
this._config.config
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user