From ae8a9940ed4d39a73537cc21e6429b73e602e4f6 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 23 Jan 2020 00:03:47 +0100 Subject: [PATCH] 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 --- src/components/ha-related-items.ts | 323 ++++++++++++++++ src/data/search.ts | 33 ++ src/dialogs/ha-more-info-dialog.js | 42 +- src/dialogs/make-dialog-manager.ts | 1 + src/dialogs/more-info/more-info-controls.js | 8 +- src/dialogs/more-info/more-info-settings.js | 141 ------- .../entities/dialog-entity-registry-detail.ts | 366 +++++++++--------- .../entities/entity-registry-settings.ts | 237 ++++++++++++ .../config/entities/ha-config-entities.ts | 35 +- src/translations/en.json | 25 +- 10 files changed, 824 insertions(+), 387 deletions(-) create mode 100644 src/components/ha-related-items.ts create mode 100644 src/data/search.ts delete mode 100644 src/dialogs/more-info/more-info-settings.js create mode 100644 src/panels/config/entities/entity-registry-settings.ts diff --git a/src/components/ha-related-items.ts b/src/components/ha-related-items.ts new file mode 100644 index 0000000000..0039e16575 --- /dev/null +++ b/src/components/ha-related-items.ts @@ -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` +

+ ${this.hass.localize( + "ui.components.related-items.integration" + )}: +

+ + ${this.hass.localize(`component.${entry.domain}.config.title`)}: + ${entry.title} + + `; + }) + : ""} + ${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` +

+ ${this.hass.localize("ui.components.related-items.device")}: +

+ + ${device.name_by_user || device.name} + + `; + }) + : ""} + ${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` +

+ ${this.hass.localize("ui.components.related-items.area")}: +

+ ${area.name} + `; + }) + : ""} + ${this._related.entity + ? html` +

+ ${this.hass.localize("ui.components.related-items.entity")}: +

+ + ` + : ""} + ${this._related.group + ? html` +

${this.hass.localize("ui.components.related-items.group")}:

+ + ` + : ""} + ${this._related.scene + ? html` +

${this.hass.localize("ui.components.related-items.scene")}:

+ + ` + : ""} + ${this._related.automation + ? html` +

+ ${this.hass.localize("ui.components.related-items.automation")}: +

+ + ` + : ""} + ${this._related.script + ? html` +

+ ${this.hass.localize("ui.components.related-items.script")}: +

+ + ` + : ""} + `; + } + + 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; + } +} diff --git a/src/data/search.ts b/src/data/search.ts new file mode 100644 index 0000000000..1e00372c9d --- /dev/null +++ b/src/data/search.ts @@ -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 => + hass.callWS({ + type: "search/related", + item_type: itemType, + item_id: itemId, + }); diff --git a/src/dialogs/ha-more-info-dialog.js b/src/dialogs/ha-more-info-dialog.js index 1d95816055..3a34c1cfc9 100644 --- a/src/dialogs/ha-more-info-dialog.js +++ b/src/dialogs/ha-more-info-dialog.js @@ -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) { } - - + `; } @@ -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, }); diff --git a/src/dialogs/make-dialog-manager.ts b/src/dialogs/make-dialog-manager.ts index 41e2cc5cba..02af7d4e96 100644 --- a/src/dialogs/make-dialog-manager.ts +++ b/src/dialogs/make-dialog-manager.ts @@ -5,6 +5,7 @@ declare global { // for fire event interface HASSDomEvents { "show-dialog": ShowDialogParams; + "close-dialog": undefined; } // for add event listener interface HTMLElementEventMap { diff --git a/src/dialogs/more-info/more-info-controls.js b/src/dialogs/more-info/more-info-controls.js index d0ac64aad9..65c24a5846 100644 --- a/src/dialogs/more-info/more-info-controls.js +++ b/src/dialogs/more-info/more-info-controls.js @@ -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)) {
[[_computeStateName(stateObj)]]
-