mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-24 21:37:21 +00:00
Add state and related to entity reg dialog (#4473)
* Add state and related to entity reg dialog * Replace more-info-settings, remove state tab add state button
This commit is contained in:
parent
a544295167
commit
ae8a9940ed
323
src/components/ha-related-items.ts
Normal file
323
src/components/ha-related-items.ts
Normal file
@ -0,0 +1,323 @@
|
||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
CSSResult,
|
||||
css,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import {
|
||||
AreaRegistryEntry,
|
||||
subscribeAreaRegistry,
|
||||
} from "../data/area_registry";
|
||||
import { ConfigEntry, getConfigEntries } from "../data/config_entries";
|
||||
import {
|
||||
DeviceRegistryEntry,
|
||||
subscribeDeviceRegistry,
|
||||
} from "../data/device_registry";
|
||||
import { SceneEntity } from "../data/scene";
|
||||
import { findRelated, ItemType, RelatedResult } from "../data/search";
|
||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||
import { HomeAssistant } from "../types";
|
||||
import "./ha-switch";
|
||||
|
||||
@customElement("ha-related-items")
|
||||
export class HaRelatedItems extends SubscribeMixin(LitElement) {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public itemType!: ItemType;
|
||||
@property() public itemId!: string;
|
||||
@property() private _entries?: ConfigEntry[];
|
||||
@property() private _devices?: DeviceRegistryEntry[];
|
||||
@property() private _areas?: AreaRegistryEntry[];
|
||||
@property() private _related?: RelatedResult;
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
|
||||
this._devices = devices;
|
||||
}),
|
||||
subscribeAreaRegistry(this.hass.connection!, (areas) => {
|
||||
this._areas = areas;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
getConfigEntries(this.hass).then((configEntries) => {
|
||||
this._entries = configEntries;
|
||||
});
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
if (
|
||||
(changedProps.has("itemId") || changedProps.has("itemType")) &&
|
||||
this.itemId &&
|
||||
this.itemType
|
||||
) {
|
||||
this._findRelated();
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this._related) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
${this._related.config_entry && this._entries
|
||||
? this._related.config_entry.map((relatedConfigEntryId) => {
|
||||
const entry: ConfigEntry | undefined = this._entries!.find(
|
||||
(configEntry) => configEntry.entry_id === relatedConfigEntryId
|
||||
);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.components.related-items.integration"
|
||||
)}:
|
||||
</h3>
|
||||
<a
|
||||
href="/config/integrations/config_entry/${relatedConfigEntryId}"
|
||||
@click=${this._close}
|
||||
>
|
||||
${this.hass.localize(`component.${entry.domain}.config.title`)}:
|
||||
${entry.title}
|
||||
</a>
|
||||
`;
|
||||
})
|
||||
: ""}
|
||||
${this._related.device && this._devices
|
||||
? this._related.device.map((relatedDeviceId) => {
|
||||
const device: DeviceRegistryEntry | undefined = this._devices!.find(
|
||||
(dev) => dev.id === relatedDeviceId
|
||||
);
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<h3>
|
||||
${this.hass.localize("ui.components.related-items.device")}:
|
||||
</h3>
|
||||
<a
|
||||
href="/config/devices/device/${relatedDeviceId}"
|
||||
@click=${this._close}
|
||||
>
|
||||
${device.name_by_user || device.name}
|
||||
</a>
|
||||
`;
|
||||
})
|
||||
: ""}
|
||||
${this._related.area && this._areas
|
||||
? this._related.area.map((relatedAreaId) => {
|
||||
const area: AreaRegistryEntry | undefined = this._areas!.find(
|
||||
(ar) => ar.area_id === relatedAreaId
|
||||
);
|
||||
if (!area) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<h3>
|
||||
${this.hass.localize("ui.components.related-items.area")}:
|
||||
</h3>
|
||||
${area.name}
|
||||
`;
|
||||
})
|
||||
: ""}
|
||||
${this._related.entity
|
||||
? html`
|
||||
<h3>
|
||||
${this.hass.localize("ui.components.related-items.entity")}:
|
||||
</h3>
|
||||
<ul>
|
||||
${this._related.entity.map((entityId) => {
|
||||
const entity: HassEntity | undefined = this.hass.states[
|
||||
entityId
|
||||
];
|
||||
if (!entity) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<li>
|
||||
<button
|
||||
@click=${this._openMoreInfo}
|
||||
.entityId="${entityId}"
|
||||
class="link"
|
||||
>
|
||||
${entity.attributes.friendly_name || entityId}
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
})}
|
||||
</ul>
|
||||
`
|
||||
: ""}
|
||||
${this._related.group
|
||||
? html`
|
||||
<h3>${this.hass.localize("ui.components.related-items.group")}:</h3>
|
||||
<ul>
|
||||
${this._related.group.map((groupId) => {
|
||||
const group: HassEntity | undefined = this.hass.states[groupId];
|
||||
if (!group) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<li>
|
||||
<button
|
||||
class="link"
|
||||
@click=${this._openMoreInfo}
|
||||
.entityId="${groupId}"
|
||||
>
|
||||
${group.attributes.friendly_name || group.entity_id}
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
})}
|
||||
</ul>
|
||||
`
|
||||
: ""}
|
||||
${this._related.scene
|
||||
? html`
|
||||
<h3>${this.hass.localize("ui.components.related-items.scene")}:</h3>
|
||||
<ul>
|
||||
${this._related.scene.map((sceneId) => {
|
||||
const scene: SceneEntity | undefined = this.hass.states[
|
||||
sceneId
|
||||
];
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<li>
|
||||
<button
|
||||
class="link"
|
||||
@click=${this._openMoreInfo}
|
||||
.entityId="${sceneId}"
|
||||
>
|
||||
${scene.attributes.friendly_name || scene.entity_id}
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
})}
|
||||
</ul>
|
||||
`
|
||||
: ""}
|
||||
${this._related.automation
|
||||
? html`
|
||||
<h3>
|
||||
${this.hass.localize("ui.components.related-items.automation")}:
|
||||
</h3>
|
||||
<ul>
|
||||
${this._related.automation.map((automationId) => {
|
||||
const automation: HassEntity | undefined = this.hass.states[
|
||||
automationId
|
||||
];
|
||||
if (!automation) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<li>
|
||||
<button
|
||||
class="link"
|
||||
@click=${this._openMoreInfo}
|
||||
.entityId="${automationId}"
|
||||
>
|
||||
${automation.attributes.friendly_name ||
|
||||
automation.entity_id}
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
})}
|
||||
</ul>
|
||||
`
|
||||
: ""}
|
||||
${this._related.script
|
||||
? html`
|
||||
<h3>
|
||||
${this.hass.localize("ui.components.related-items.script")}:
|
||||
</h3>
|
||||
<ul>
|
||||
${this._related.script.map((scriptId) => {
|
||||
const script: HassEntity | undefined = this.hass.states[
|
||||
scriptId
|
||||
];
|
||||
if (!script) {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
<li>
|
||||
<button
|
||||
class="link"
|
||||
@click=${this._openMoreInfo}
|
||||
.entityId="${scriptId}"
|
||||
>
|
||||
${script.attributes.friendly_name || script.entity_id}
|
||||
</button>
|
||||
</li>
|
||||
`;
|
||||
})}
|
||||
</ul>
|
||||
`
|
||||
: ""}
|
||||
`;
|
||||
}
|
||||
|
||||
private async _findRelated() {
|
||||
this._related = await findRelated(this.hass, this.itemType, this.itemId);
|
||||
await this.updateComplete;
|
||||
fireEvent(this, "iron-resize");
|
||||
}
|
||||
|
||||
private _openMoreInfo(ev: CustomEvent) {
|
||||
const entityId = (ev.target as any).entityId;
|
||||
fireEvent(this, "hass-more-info", { entityId });
|
||||
}
|
||||
|
||||
private _close() {
|
||||
fireEvent(this, "close-dialog");
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
button.link {
|
||||
color: var(--primary-color);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border-width: initial;
|
||||
border-style: none;
|
||||
border-color: initial;
|
||||
border-image: initial;
|
||||
padding: 0px;
|
||||
font: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
h3 {
|
||||
font-family: var(--paper-font-title_-_font-family);
|
||||
-webkit-font-smoothing: var(
|
||||
--paper-font-title_-_-webkit-font-smoothing
|
||||
);
|
||||
font-size: var(--paper-font-title_-_font-size);
|
||||
font-weight: var(--paper-font-headline-_font-weight);
|
||||
letter-spacing: var(--paper-font-title_-_letter-spacing);
|
||||
line-height: var(--paper-font-title_-_line-height);
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-related-items": HaRelatedItems;
|
||||
}
|
||||
}
|
33
src/data/search.ts
Normal file
33
src/data/search.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
export interface RelatedResult {
|
||||
area?: string[];
|
||||
automation?: string[];
|
||||
config_entry?: string[];
|
||||
device?: string[];
|
||||
entity?: string[];
|
||||
group?: string[];
|
||||
scene?: string[];
|
||||
script?: string[];
|
||||
}
|
||||
|
||||
export type ItemType =
|
||||
| "area"
|
||||
| "automation"
|
||||
| "config_entry"
|
||||
| "device"
|
||||
| "entity"
|
||||
| "group"
|
||||
| "scene"
|
||||
| "script";
|
||||
|
||||
export const findRelated = (
|
||||
hass: HomeAssistant,
|
||||
itemType: ItemType,
|
||||
itemId: string
|
||||
): Promise<RelatedResult> =>
|
||||
hass.callWS({
|
||||
type: "search/related",
|
||||
item_type: itemType,
|
||||
item_id: itemId,
|
||||
});
|
@ -6,7 +6,6 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import "../resources/ha-style";
|
||||
|
||||
import "./more-info/more-info-controls";
|
||||
import "./more-info/more-info-settings";
|
||||
|
||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
||||
import { isComponentLoaded } from "../common/config/is_component_loaded";
|
||||
@ -26,8 +25,7 @@ class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
more-info-controls,
|
||||
more-info-settings {
|
||||
more-info-controls {
|
||||
--more-info-header-background: var(--secondary-background-color);
|
||||
--more-info-header-color: var(--primary-text-color);
|
||||
--ha-more-info-app-toolbar-title: {
|
||||
@ -46,8 +44,7 @@ class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
||||
|
||||
/* overrule the ha-style-dialog max-height on small screens */
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
more-info-controls,
|
||||
more-info-settings {
|
||||
more-info-controls {
|
||||
--more-info-header-background: var(--primary-color);
|
||||
--more-info-header-color: var(--text-primary-color);
|
||||
}
|
||||
@ -79,24 +76,14 @@ class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
||||
}
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[!_page]]">
|
||||
<more-info-controls
|
||||
class="no-padding"
|
||||
hass="[[hass]]"
|
||||
state-obj="[[stateObj]]"
|
||||
dialog-element="[[_dialogElement]]"
|
||||
can-configure="[[_registryInfo]]"
|
||||
large="{{large}}"
|
||||
></more-info-controls>
|
||||
</template>
|
||||
<template is="dom-if" if='[[_equals(_page, "settings")]]'>
|
||||
<more-info-settings
|
||||
class="no-padding"
|
||||
hass="[[hass]]"
|
||||
state-obj="[[stateObj]]"
|
||||
registry-info="{{_registryInfo}}"
|
||||
></more-info-settings>
|
||||
</template>
|
||||
<more-info-controls
|
||||
class="no-padding"
|
||||
hass="[[hass]]"
|
||||
state-obj="[[stateObj]]"
|
||||
dialog-element="[[_dialogElement]]"
|
||||
registry-entry="[[_registryInfo]]"
|
||||
large="{{large}}"
|
||||
></more-info-controls>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -118,11 +105,6 @@ class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
||||
_dialogElement: Object,
|
||||
_registryInfo: Object,
|
||||
|
||||
_page: {
|
||||
type: String,
|
||||
value: null,
|
||||
},
|
||||
|
||||
dataDomain: {
|
||||
computed: "_computeDomain(stateObj)",
|
||||
reflectToAttribute: true,
|
||||
@ -137,9 +119,6 @@ class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
||||
ready() {
|
||||
super.ready();
|
||||
this._dialogElement = this;
|
||||
this.addEventListener("more-info-page", (ev) => {
|
||||
this._page = ev.detail.page;
|
||||
});
|
||||
}
|
||||
|
||||
_computeDomain(stateObj) {
|
||||
@ -154,7 +133,6 @@ class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
||||
if (!newVal) {
|
||||
this.setProperties({
|
||||
opened: false,
|
||||
_page: null,
|
||||
_registryInfo: null,
|
||||
large: false,
|
||||
});
|
||||
|
@ -5,6 +5,7 @@ declare global {
|
||||
// for fire event
|
||||
interface HASSDomEvents {
|
||||
"show-dialog": ShowDialogParams<unknown>;
|
||||
"close-dialog": undefined;
|
||||
}
|
||||
// for add event listener
|
||||
interface HTMLElementEventMap {
|
||||
|
@ -22,6 +22,7 @@ import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import { removeEntityRegistryEntry } from "../../data/entity_registry";
|
||||
import { showConfirmationDialog } from "../confirmation/show-dialog-confirmation";
|
||||
import { showEntityRegistryDetailDialog } from "../../panels/config/entities/show-dialog-entity-registry-detail";
|
||||
|
||||
const DOMAINS_NO_INFO = ["camera", "configurator", "history_graph"];
|
||||
const EDITABLE_DOMAINS_WITH_ID = ["scene", "automation"];
|
||||
@ -87,7 +88,7 @@ class MoreInfoControls extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
<div class="main-title" main-title="" on-click="enlarge">
|
||||
[[_computeStateName(stateObj)]]
|
||||
</div>
|
||||
<template is="dom-if" if="[[canConfigure]]">
|
||||
<template is="dom-if" if="[[registryEntry]]">
|
||||
<paper-icon-button
|
||||
aria-label$="[[localize('ui.dialogs.more_info_control.settings')]]"
|
||||
icon="hass:settings"
|
||||
@ -158,7 +159,7 @@ class MoreInfoControls extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
},
|
||||
|
||||
dialogElement: Object,
|
||||
canConfigure: Boolean,
|
||||
registryEntry: Object,
|
||||
|
||||
domain: {
|
||||
type: String,
|
||||
@ -259,7 +260,8 @@ class MoreInfoControls extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
}
|
||||
|
||||
_gotoSettings() {
|
||||
this.fire("more-info-page", { page: "settings" });
|
||||
showEntityRegistryDetailDialog(this, { entry: this.registryEntry });
|
||||
this.fire("hass-more-info", { entityId: null });
|
||||
}
|
||||
|
||||
_gotoEdit() {
|
||||
|
@ -1,141 +0,0 @@
|
||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-icon-button/paper-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import { EventsMixin } from "../../mixins/events-mixin";
|
||||
import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
|
||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||
import { computeDomain } from "../../common/entity/compute_domain";
|
||||
import { updateEntityRegistryEntry } from "../../data/entity_registry";
|
||||
import { showSaveSuccessToast } from "../../util/toast-saved-success";
|
||||
|
||||
import "../../components/ha-paper-icon-button-arrow-prev";
|
||||
/*
|
||||
* @appliesMixin EventsMixin
|
||||
* @appliesMixin LocalizeMixin
|
||||
*/
|
||||
class MoreInfoSettings extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
app-toolbar {
|
||||
color: var(--more-info-header-color);
|
||||
background-color: var(--more-info-header-background);
|
||||
|
||||
/* to fit save button */
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
app-toolbar [main-title] {
|
||||
@apply --ha-more-info-app-toolbar-title;
|
||||
}
|
||||
|
||||
app-toolbar mwc-button {
|
||||
font-size: 0.8em;
|
||||
margin: 0;
|
||||
--mdc-theme-primary: var(--more-info-header-color);
|
||||
}
|
||||
|
||||
.form {
|
||||
padding: 0 24px 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-toolbar>
|
||||
<ha-paper-icon-button-arrow-prev
|
||||
aria-label$="[[localize('ui.dialogs.more_info_settings.back')]]"
|
||||
on-click="_backTapped"
|
||||
></ha-paper-icon-button-arrow-prev>
|
||||
<div main-title="">[[_computeStateName(stateObj)]]</div>
|
||||
<mwc-button on-click="_save" disabled="[[_computeInvalid(_entityId)]]"
|
||||
>[[localize('ui.dialogs.more_info_settings.save')]]</mwc-button
|
||||
>
|
||||
</app-toolbar>
|
||||
|
||||
<div class="form">
|
||||
<paper-input
|
||||
value="{{_name}}"
|
||||
label="[[localize('ui.dialogs.more_info_settings.name')]]"
|
||||
></paper-input>
|
||||
<paper-input
|
||||
value="{{_entityId}}"
|
||||
label="[[localize('ui.dialogs.more_info_settings.entity_id')]]"
|
||||
error-message="Domain needs to stay the same"
|
||||
invalid="[[_computeInvalid(_entityId)]]"
|
||||
></paper-input>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
stateObj: Object,
|
||||
|
||||
registryInfo: {
|
||||
type: Object,
|
||||
observer: "_registryInfoChanged",
|
||||
notify: true,
|
||||
},
|
||||
|
||||
_name: String,
|
||||
_entityId: String,
|
||||
};
|
||||
}
|
||||
|
||||
_computeStateName(stateObj) {
|
||||
if (!stateObj) return "";
|
||||
return computeStateName(stateObj);
|
||||
}
|
||||
|
||||
_computeInvalid(entityId) {
|
||||
return computeDomain(this.stateObj.entity_id) !== computeDomain(entityId);
|
||||
}
|
||||
|
||||
_registryInfoChanged(newVal) {
|
||||
if (newVal) {
|
||||
this.setProperties({
|
||||
_name: newVal.name,
|
||||
_entityId: newVal.entity_id,
|
||||
});
|
||||
} else {
|
||||
this.setProperties({
|
||||
_name: "",
|
||||
_entityId: "",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_backTapped() {
|
||||
this.fire("more-info-page", { page: null });
|
||||
}
|
||||
|
||||
async _save() {
|
||||
try {
|
||||
const info = await updateEntityRegistryEntry(
|
||||
this.hass,
|
||||
this.stateObj.entity_id,
|
||||
{
|
||||
name: this._name,
|
||||
new_entity_id: this._entityId,
|
||||
}
|
||||
);
|
||||
|
||||
showSaveSuccessToast(this, this.hass);
|
||||
|
||||
this.registryInfo = info;
|
||||
|
||||
// Keep the more info dialog open at the new entity.
|
||||
if (this.stateObj.entity_id !== this._entityId) {
|
||||
this.fire("hass-more-info", { entityId: this._entityId });
|
||||
}
|
||||
} catch (err) {
|
||||
alert(`save failed: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
customElements.define("more-info-settings", MoreInfoSettings);
|
@ -1,206 +1,151 @@
|
||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||
import "@polymer/paper-tabs/paper-tab";
|
||||
import "@polymer/paper-tabs/paper-tabs";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import {
|
||||
LitElement,
|
||||
html,
|
||||
css,
|
||||
CSSResult,
|
||||
TemplateResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
|
||||
import { cache } from "lit-html/directives/cache";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import "../../../components/dialog/ha-paper-dialog";
|
||||
import "../../../components/ha-switch";
|
||||
|
||||
import { EntityRegistryDetailDialogParams } from "./show-dialog-entity-registry-detail";
|
||||
// tslint:disable-next-line: no-duplicate-imports
|
||||
import { HaPaperDialog } from "../../../components/dialog/ha-paper-dialog";
|
||||
import "../../../components/ha-related-items";
|
||||
import "../../../dialogs/more-info/controls/more-info-content";
|
||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import "../../../state-summary/state-card-content";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
// tslint:disable-next-line: no-duplicate-imports
|
||||
import { HaSwitch } from "../../../components/ha-switch";
|
||||
import "./entity-registry-settings";
|
||||
import { EntityRegistryDetailDialogParams } from "./show-dialog-entity-registry-detail";
|
||||
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import {
|
||||
updateEntityRegistryEntry,
|
||||
removeEntityRegistryEntry,
|
||||
} from "../../../data/entity_registry";
|
||||
import { showConfirmationDialog } from "../../../dialogs/confirmation/show-dialog-confirmation";
|
||||
|
||||
class DialogEntityRegistryDetail extends LitElement {
|
||||
@customElement("dialog-entity-registry-detail")
|
||||
export class DialogEntityRegistryDetail extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() private _name!: string;
|
||||
@property() private _entityId!: string;
|
||||
@property() private _disabledBy!: string | null;
|
||||
@property() private _error?: string;
|
||||
@property() private _params?: EntityRegistryDetailDialogParams;
|
||||
@property() private _submitting?: boolean;
|
||||
private _origEntityId!: string;
|
||||
@property() private _curTab?: string;
|
||||
@query("ha-paper-dialog") private _dialog!: HaPaperDialog;
|
||||
private _curTabIndex = 0;
|
||||
|
||||
public async showDialog(
|
||||
params: EntityRegistryDetailDialogParams
|
||||
): Promise<void> {
|
||||
this._params = params;
|
||||
this._error = undefined;
|
||||
this._name = this._params.entry.name || "";
|
||||
this._origEntityId = this._params.entry.entity_id;
|
||||
this._entityId = this._params.entry.entity_id;
|
||||
this._disabledBy = this._params.entry.disabled_by;
|
||||
await this.updateComplete;
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this._params = undefined;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this._params) {
|
||||
return html``;
|
||||
}
|
||||
const entry = this._params.entry;
|
||||
const stateObj: HassEntity | undefined = this.hass.states[entry.entity_id];
|
||||
const invalidDomainUpdate =
|
||||
computeDomain(this._entityId.trim()) !==
|
||||
computeDomain(this._params.entry.entity_id);
|
||||
|
||||
return html`
|
||||
<ha-paper-dialog
|
||||
with-backdrop
|
||||
opened
|
||||
@opened-changed="${this._openedChanged}"
|
||||
@opened-changed=${this._openedChanged}
|
||||
>
|
||||
<h2>
|
||||
${stateObj
|
||||
? computeStateName(stateObj)
|
||||
: entry.name || entry.entity_id}
|
||||
</h2>
|
||||
<paper-dialog-scrollable>
|
||||
${!stateObj
|
||||
? html`
|
||||
<div>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.config.entities.editor.unavailable"
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${this._error
|
||||
? html`
|
||||
<div class="error">${this._error}</div>
|
||||
`
|
||||
: ""}
|
||||
<div class="form">
|
||||
<paper-input
|
||||
.value=${this._name}
|
||||
@value-changed=${this._nameChanged}
|
||||
.label=${this.hass.localize("ui.dialogs.more_info_settings.name")}
|
||||
.placeholder=${stateObj ? computeStateName(stateObj) : ""}
|
||||
.disabled=${this._submitting}
|
||||
></paper-input>
|
||||
<paper-input
|
||||
.value=${this._entityId}
|
||||
@value-changed=${this._entityIdChanged}
|
||||
.label=${this.hass.localize(
|
||||
"ui.dialogs.more_info_settings.entity_id"
|
||||
)}
|
||||
error-message="Domain needs to stay the same"
|
||||
.invalid=${invalidDomainUpdate}
|
||||
.disabled=${this._submitting}
|
||||
></paper-input>
|
||||
<div class="row">
|
||||
<ha-switch
|
||||
.checked=${!this._disabledBy}
|
||||
@change=${this._disabledByChanged}
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entities.editor.enabled_label"
|
||||
)}
|
||||
</div>
|
||||
<div class="secondary">
|
||||
${this._disabledBy && this._disabledBy !== "user"
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.entities.editor.enabled_cause",
|
||||
"cause",
|
||||
this.hass.localize(
|
||||
`config_entry.disabled_by.${this._disabledBy}`
|
||||
)
|
||||
)
|
||||
: ""}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entities.editor.enabled_description"
|
||||
)}
|
||||
<br />${this.hass.localize(
|
||||
"ui.panel.config.entities.editor.note"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ha-switch>
|
||||
</div>
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
aria-label=${this.hass.localize(
|
||||
"ui.panel.config.entities.dialog.dismiss"
|
||||
)}
|
||||
icon="hass:close"
|
||||
dialog-dismiss
|
||||
></paper-icon-button>
|
||||
<div class="main-title" main-title>
|
||||
${stateObj
|
||||
? computeStateName(stateObj)
|
||||
: entry.name || entry.entity_id}
|
||||
</div>
|
||||
</paper-dialog-scrollable>
|
||||
<div class="paper-dialog-buttons">
|
||||
<mwc-button
|
||||
class="warning"
|
||||
@click="${this._confirmDeleteEntry}"
|
||||
.disabled=${this._submitting ||
|
||||
!(stateObj && stateObj.attributes.restored)}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.entities.editor.delete")}
|
||||
</mwc-button>
|
||||
<mwc-button
|
||||
@click="${this._updateEntry}"
|
||||
.disabled=${invalidDomainUpdate || this._submitting}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.entities.editor.update")}
|
||||
</mwc-button>
|
||||
</div>
|
||||
${stateObj
|
||||
? html`
|
||||
<paper-icon-button
|
||||
aria-label=${this.hass.localize(
|
||||
"ui.panel.config.entities.dialog.control"
|
||||
)}
|
||||
icon="hass:tune"
|
||||
@click=${this._openMoreInfo}
|
||||
></paper-icon-button>
|
||||
`
|
||||
: ""}
|
||||
</app-toolbar>
|
||||
<paper-tabs
|
||||
scrollable
|
||||
hide-scroll-buttons
|
||||
.selected=${this._curTabIndex}
|
||||
@selected-item-changed=${this._handleTabSelected}
|
||||
>
|
||||
<paper-tab id="tab-settings">
|
||||
${this.hass.localize("ui.panel.config.entities.dialog.settings")}
|
||||
</paper-tab>
|
||||
<paper-tab id="tab-related">
|
||||
${this.hass.localize("ui.panel.config.entities.dialog.related")}
|
||||
</paper-tab>
|
||||
</paper-tabs>
|
||||
${cache(
|
||||
this._curTab === "tab-settings"
|
||||
? html`
|
||||
<entity-registry-settings
|
||||
.hass=${this.hass}
|
||||
.entry=${entry}
|
||||
.dialogElement=${this._dialog}
|
||||
@close-dialog=${this._closeDialog}
|
||||
></entity-registry-settings>
|
||||
`
|
||||
: this._curTab === "tab-related"
|
||||
? html`
|
||||
<paper-dialog-scrollable>
|
||||
<ha-related-items
|
||||
.hass=${this.hass}
|
||||
.itemId=${entry.entity_id}
|
||||
itemType="entity"
|
||||
@close-dialog=${this._closeDialog}
|
||||
></ha-related-items>
|
||||
</paper-dialog-scrollable>
|
||||
`
|
||||
: html``
|
||||
)}
|
||||
</ha-paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _nameChanged(ev: PolymerChangedEvent<string>): void {
|
||||
this._error = undefined;
|
||||
this._name = ev.detail.value;
|
||||
}
|
||||
|
||||
private _entityIdChanged(ev: PolymerChangedEvent<string>): void {
|
||||
this._error = undefined;
|
||||
this._entityId = ev.detail.value;
|
||||
}
|
||||
|
||||
private async _updateEntry(): Promise<void> {
|
||||
this._submitting = true;
|
||||
try {
|
||||
await updateEntityRegistryEntry(this.hass!, this._origEntityId, {
|
||||
name: this._name.trim() || null,
|
||||
disabled_by: this._disabledBy,
|
||||
new_entity_id: this._entityId.trim(),
|
||||
});
|
||||
this._params = undefined;
|
||||
} catch (err) {
|
||||
this._error = err.message || "Unknown error";
|
||||
} finally {
|
||||
this._submitting = false;
|
||||
private _handleTabSelected(ev: CustomEvent): void {
|
||||
if (!ev.detail.value) {
|
||||
return;
|
||||
}
|
||||
this._curTab = ev.detail.value.id;
|
||||
this._resizeDialog();
|
||||
}
|
||||
|
||||
private async _deleteEntry(): Promise<void> {
|
||||
this._submitting = true;
|
||||
|
||||
try {
|
||||
await removeEntityRegistryEntry(this.hass!, this._entityId);
|
||||
this._params = undefined;
|
||||
} finally {
|
||||
this._submitting = false;
|
||||
}
|
||||
private async _resizeDialog(): Promise<void> {
|
||||
await this.updateComplete;
|
||||
fireEvent(this._dialog as HTMLElement, "iron-resize");
|
||||
}
|
||||
|
||||
private _confirmDeleteEntry(): void {
|
||||
showConfirmationDialog(this, {
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.entities.editor.confirm_delete"
|
||||
),
|
||||
confirm: () => this._deleteEntry(),
|
||||
private _openMoreInfo(): void {
|
||||
fireEvent(this, "hass-more-info", {
|
||||
entityId: this._params!.entry.entity_id,
|
||||
});
|
||||
this._params = undefined;
|
||||
}
|
||||
|
||||
private _closeDialog(): void {
|
||||
this._params = undefined;
|
||||
}
|
||||
|
||||
private _openedChanged(ev: PolymerChangedEvent<boolean>): void {
|
||||
@ -208,36 +153,88 @@ class DialogEntityRegistryDetail extends LitElement {
|
||||
this._params = undefined;
|
||||
}
|
||||
}
|
||||
private _disabledByChanged(ev: Event): void {
|
||||
this._disabledBy = (ev.target as HaSwitch).checked ? null : "user";
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
app-toolbar {
|
||||
color: var(--primary-text-color);
|
||||
background-color: var(--secondary-background-color);
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
app-toolbar [main-title] {
|
||||
/* Design guideline states 24px, changed to 16 to align with state info */
|
||||
margin-left: 16px;
|
||||
line-height: 1.3em;
|
||||
max-height: 2.6em;
|
||||
overflow: hidden;
|
||||
/* webkit and blink still support simple multiline text-overflow */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media all and (min-width: 451px) and (min-height: 501px) {
|
||||
.main-title {
|
||||
pointer-events: auto;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
ha-paper-dialog {
|
||||
width: 450px;
|
||||
}
|
||||
|
||||
/* overrule the ha-style-dialog max-height on small screens */
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
app-toolbar {
|
||||
background-color: var(--primary-color);
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
ha-paper-dialog {
|
||||
height: 100%;
|
||||
max-height: 100% !important;
|
||||
width: 100% !important;
|
||||
border-radius: 0px;
|
||||
position: fixed !important;
|
||||
margin: 0;
|
||||
}
|
||||
ha-paper-dialog::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
paper-dialog-scrollable {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
mwc-button.warning {
|
||||
--mdc-theme-primary: var(--google-red-500);
|
||||
}
|
||||
|
||||
:host([rtl]) app-toolbar {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
}
|
||||
:host {
|
||||
--paper-font-title_-_white-space: normal;
|
||||
}
|
||||
ha-paper-dialog {
|
||||
min-width: 400px;
|
||||
max-width: 450px;
|
||||
}
|
||||
.form {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
mwc-button.warning {
|
||||
margin-right: auto;
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.row {
|
||||
margin-top: 8px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.secondary {
|
||||
color: var(--secondary-text-color);
|
||||
paper-tabs {
|
||||
--paper-tabs-selection-bar-color: var(--primary-color);
|
||||
text-transform: uppercase;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
margin-top: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
@ -249,8 +246,3 @@ declare global {
|
||||
"dialog-entity-registry-detail": DialogEntityRegistryDetail;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(
|
||||
"dialog-entity-registry-detail",
|
||||
DialogEntityRegistryDetail
|
||||
);
|
||||
|
237
src/panels/config/entities/entity-registry-settings.ts
Normal file
237
src/panels/config/entities/entity-registry-settings.ts
Normal file
@ -0,0 +1,237 @@
|
||||
import {
|
||||
LitElement,
|
||||
html,
|
||||
css,
|
||||
CSSResult,
|
||||
TemplateResult,
|
||||
property,
|
||||
customElement,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
|
||||
import "../../../components/ha-switch";
|
||||
|
||||
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
// tslint:disable-next-line: no-duplicate-imports
|
||||
import { HaSwitch } from "../../../components/ha-switch";
|
||||
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import {
|
||||
updateEntityRegistryEntry,
|
||||
removeEntityRegistryEntry,
|
||||
EntityRegistryEntry,
|
||||
} from "../../../data/entity_registry";
|
||||
import { showConfirmationDialog } from "../../../dialogs/confirmation/show-dialog-confirmation";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
|
||||
@customElement("entity-registry-settings")
|
||||
export class EntityRegistrySettings extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public entry!: EntityRegistryEntry;
|
||||
@property() public dialogElement!: HTMLElement;
|
||||
@property() private _name!: string;
|
||||
@property() private _entityId!: string;
|
||||
@property() private _disabledBy!: string | null;
|
||||
@property() private _error?: string;
|
||||
@property() private _submitting?: boolean;
|
||||
private _origEntityId!: string;
|
||||
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
if (changedProperties.has("entry")) {
|
||||
this._error = undefined;
|
||||
this._name = this.entry.name || "";
|
||||
this._origEntityId = this.entry.entity_id;
|
||||
this._entityId = this.entry.entity_id;
|
||||
this._disabledBy = this.entry.disabled_by;
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (this.entry.entity_id !== this._origEntityId) {
|
||||
return;
|
||||
}
|
||||
const stateObj: HassEntity | undefined = this.hass.states[
|
||||
this.entry.entity_id
|
||||
];
|
||||
const invalidDomainUpdate =
|
||||
computeDomain(this._entityId.trim()) !==
|
||||
computeDomain(this.entry.entity_id);
|
||||
|
||||
return html`
|
||||
<paper-dialog-scrollable .dialogElement=${this.dialogElement}>
|
||||
${!stateObj
|
||||
? html`
|
||||
<div>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.config.entities.editor.unavailable"
|
||||
)}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
${this._error
|
||||
? html`
|
||||
<div class="error">${this._error}</div>
|
||||
`
|
||||
: ""}
|
||||
<div class="form">
|
||||
<paper-input
|
||||
.value=${this._name}
|
||||
@value-changed=${this._nameChanged}
|
||||
.label=${this.hass.localize("ui.panel.config.entities.editor.name")}
|
||||
.placeholder=${stateObj ? computeStateName(stateObj) : ""}
|
||||
.disabled=${this._submitting}
|
||||
></paper-input>
|
||||
<paper-input
|
||||
.value=${this._entityId}
|
||||
@value-changed=${this._entityIdChanged}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.entities.editor.entity_id"
|
||||
)}
|
||||
error-message="Domain needs to stay the same"
|
||||
.invalid=${invalidDomainUpdate}
|
||||
.disabled=${this._submitting}
|
||||
></paper-input>
|
||||
<div class="row">
|
||||
<ha-switch
|
||||
.checked=${!this._disabledBy}
|
||||
@change=${this._disabledByChanged}
|
||||
>
|
||||
<div>
|
||||
<div>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entities.editor.enabled_label"
|
||||
)}
|
||||
</div>
|
||||
<div class="secondary">
|
||||
${this._disabledBy && this._disabledBy !== "user"
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.entities.editor.enabled_cause",
|
||||
"cause",
|
||||
this.hass.localize(
|
||||
`config_entry.disabled_by.${this._disabledBy}`
|
||||
)
|
||||
)
|
||||
: ""}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entities.editor.enabled_description"
|
||||
)}
|
||||
<br />${this.hass.localize(
|
||||
"ui.panel.config.entities.editor.note"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ha-switch>
|
||||
</div>
|
||||
</div>
|
||||
</paper-dialog-scrollable>
|
||||
<div class="buttons">
|
||||
<mwc-button
|
||||
class="warning"
|
||||
@click="${this._confirmDeleteEntry}"
|
||||
.disabled=${this._submitting ||
|
||||
!(stateObj && stateObj.attributes.restored)}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.entities.editor.delete")}
|
||||
</mwc-button>
|
||||
<mwc-button
|
||||
@click="${this._updateEntry}"
|
||||
.disabled=${invalidDomainUpdate || this._submitting}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.entities.editor.update")}
|
||||
</mwc-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _nameChanged(ev: PolymerChangedEvent<string>): void {
|
||||
this._error = undefined;
|
||||
this._name = ev.detail.value;
|
||||
}
|
||||
|
||||
private _entityIdChanged(ev: PolymerChangedEvent<string>): void {
|
||||
this._error = undefined;
|
||||
this._entityId = ev.detail.value;
|
||||
}
|
||||
|
||||
private async _updateEntry(): Promise<void> {
|
||||
this._submitting = true;
|
||||
try {
|
||||
await updateEntityRegistryEntry(this.hass!, this._origEntityId, {
|
||||
name: this._name.trim() || null,
|
||||
disabled_by: this._disabledBy,
|
||||
new_entity_id: this._entityId.trim(),
|
||||
});
|
||||
fireEvent(this as HTMLElement, "close-dialog");
|
||||
} catch (err) {
|
||||
this._error = err.message || "Unknown error";
|
||||
} finally {
|
||||
this._submitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async _deleteEntry(): Promise<void> {
|
||||
this._submitting = true;
|
||||
|
||||
try {
|
||||
await removeEntityRegistryEntry(this.hass!, this._entityId);
|
||||
fireEvent(this as HTMLElement, "close-dialog");
|
||||
} finally {
|
||||
this._submitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
private _confirmDeleteEntry(): void {
|
||||
showConfirmationDialog(this, {
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.entities.editor.confirm_delete"
|
||||
),
|
||||
confirm: () => this._deleteEntry(),
|
||||
});
|
||||
}
|
||||
|
||||
private _disabledByChanged(ev: Event): void {
|
||||
this._disabledBy = (ev.target as HaSwitch).checked ? null : "user";
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
:host {
|
||||
display: block;
|
||||
margin-bottom: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.form {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 8px;
|
||||
}
|
||||
mwc-button.warning {
|
||||
margin-right: auto;
|
||||
--mdc-theme-primary: var(--google-red-500);
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.row {
|
||||
margin-top: 8px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.secondary {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"entity-registry-settings": EntityRegistrySettings;
|
||||
}
|
||||
}
|
@ -46,9 +46,11 @@ import {
|
||||
DataTableColumnData,
|
||||
} from "../../../components/data-table/ha-data-table";
|
||||
import { showConfirmationDialog } from "../../../dialogs/confirmation/show-dialog-confirmation";
|
||||
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
|
||||
import { DialogEntityRegistryDetail } from "./dialog-entity-registry-detail";
|
||||
|
||||
@customElement("ha-config-entities")
|
||||
export class HaConfigEntities extends LitElement {
|
||||
export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public isWide!: boolean;
|
||||
@property() public narrow!: boolean;
|
||||
@ -59,8 +61,6 @@ export class HaConfigEntities extends LitElement {
|
||||
@property() private _selectedEntities: string[] = [];
|
||||
@query("ha-data-table") private _dataTable!: HaDataTable;
|
||||
|
||||
private _unsubEntities?: UnsubscribeFunc;
|
||||
|
||||
private _columns = memoize(
|
||||
(narrow, _language): DataTableColumnContainer => {
|
||||
const columns: DataTableColumnContainer = {
|
||||
@ -196,10 +196,23 @@ export class HaConfigEntities extends LitElement {
|
||||
}
|
||||
);
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
||||
this._entities = entities;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
if (this._unsubEntities) {
|
||||
this._unsubEntities();
|
||||
const dialog = document
|
||||
.querySelector("home-assistant")!
|
||||
.shadowRoot!.querySelector("dialog-entity-registry-detail") as
|
||||
| DialogEntityRegistryDetail
|
||||
| undefined;
|
||||
if (dialog) {
|
||||
dialog.closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,18 +375,6 @@ export class HaConfigEntities extends LitElement {
|
||||
loadEntityRegistryDetailDialog();
|
||||
}
|
||||
|
||||
protected updated(changedProps) {
|
||||
super.updated(changedProps);
|
||||
if (!this._unsubEntities) {
|
||||
this._unsubEntities = subscribeEntityRegistry(
|
||||
this.hass.connection,
|
||||
(entities) => {
|
||||
this._entities = entities;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _showDisabledChanged() {
|
||||
this._showDisabled = !this._showDisabled;
|
||||
}
|
||||
|
@ -553,6 +553,16 @@
|
||||
},
|
||||
"service-picker": {
|
||||
"service": "Service"
|
||||
},
|
||||
"related-items": {
|
||||
"integration": "Integration",
|
||||
"device": "Device",
|
||||
"area": "Area",
|
||||
"entity": "Related entities",
|
||||
"group": "Part of the following groups",
|
||||
"scene": "Part of the following scenes",
|
||||
"script": "Part of the following scripts",
|
||||
"automation": "Part of the following automations"
|
||||
}
|
||||
},
|
||||
"dialogs": {
|
||||
@ -593,12 +603,6 @@
|
||||
"confirm_remove_text": "Are you sure you want to remove this entity?"
|
||||
}
|
||||
},
|
||||
"more_info_settings": {
|
||||
"back": "Go back",
|
||||
"save": "Save",
|
||||
"name": "Name Override",
|
||||
"entity_id": "Entity ID"
|
||||
},
|
||||
"options_flow": {
|
||||
"form": {
|
||||
"header": "Options"
|
||||
@ -1300,9 +1304,16 @@
|
||||
"confirm_text": "Entities can only be removed when the integration is no longer providing the entities."
|
||||
}
|
||||
},
|
||||
"dialog": {
|
||||
"settings": "Settings",
|
||||
"control": "Control",
|
||||
"related": "Related",
|
||||
"dismiss": "Dismiss"
|
||||
},
|
||||
"editor": {
|
||||
"name": "Name Override",
|
||||
"entity_id": "Entity ID",
|
||||
"unavailable": "This entity is not currently available.",
|
||||
"default_name": "New Area",
|
||||
"enabled_label": "Enable entity",
|
||||
"enabled_cause": "Disabled by {cause}.",
|
||||
"enabled_description": "Disabled entities will not be added to Home Assistant.",
|
||||
|
Loading…
x
Reference in New Issue
Block a user