@@ -176,8 +176,6 @@ class HaConfigManagerDashboard extends LocalizeMixin(
*/
progress: Array,
- handlers: Array,
-
rtl: {
type: Boolean,
reflectToAttribute: true,
diff --git a/src/panels/config/integrations/ha-config-entry-page.js b/src/panels/config/integrations/ha-config-entry-page.js
deleted file mode 100644
index 59cb34878c..0000000000
--- a/src/panels/config/integrations/ha-config-entry-page.js
+++ /dev/null
@@ -1,184 +0,0 @@
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-
-import "../../../layouts/hass-subpage";
-
-import "../../../components/entity/state-badge";
-import { compare } from "../../../common/string/compare";
-
-import "./ha-device-card";
-import "./ha-ce-entities-card";
-import { EventsMixin } from "../../../mixins/events-mixin";
-import LocalizeMixin from "../../../mixins/localize-mixin";
-import NavigateMixin from "../../../mixins/navigate-mixin";
-import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
-
-class HaConfigEntryPage extends NavigateMixin(
- EventsMixin(LocalizeMixin(PolymerElement))
-) {
- static get template() {
- return html`
-
-
-
-
-
-
-
-
-
- [[localize('ui.panel.config.integrations.config_entry.no_devices')]]
-
-
-
-
-
-
-
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- isWide: Boolean,
- narrow: Boolean,
- configEntry: {
- type: Object,
- value: null,
- },
-
- _configEntryDevices: {
- type: Array,
- computed: "_computeConfigEntryDevices(configEntry, devices)",
- },
-
- /**
- * All entity registry entries for this config entry that do not belong
- * to a device.
- */
- _noDeviceEntities: {
- type: Array,
- computed: "_computeNoDeviceEntities(configEntry, entities)",
- },
-
- /**
- * Area registry entries
- */
- areas: Array,
-
- /**
- * Device registry entries
- */
- devices: Array,
-
- /**
- * Existing entries.
- */
- entries: Array,
-
- /**
- * Entity Registry entries.
- */
- entities: Array,
- };
- }
-
- _computeConfigEntryDevices(configEntry, devices) {
- if (!devices) return [];
- return devices
- .filter((device) => device.config_entries.includes(configEntry.entry_id))
- .sort(
- (dev1, dev2) =>
- !!dev1.via_device_id - !!dev2.via_device_id ||
- compare(dev1.name, dev2.name)
- );
- }
-
- _computeNoDeviceEntities(configEntry, entities) {
- if (!entities) return [];
- return entities.filter(
- (ent) => !ent.device_id && ent.config_entry_id === configEntry.entry_id
- );
- }
-
- _computeIsEmpty(configEntryDevices, noDeviceEntities) {
- return configEntryDevices.length === 0 && noDeviceEntities.length === 0;
- }
-
- _showSettings() {
- showOptionsFlowDialog(this, this.configEntry);
- }
-
- _removeEntry() {
- if (
- !confirm(
- this.localize(
- "ui.panel.config.integrations.config_entry.delete_confirm"
- )
- )
- )
- return;
-
- const entryId = this.configEntry.entry_id;
-
- this.hass
- .callApi("delete", `config/config_entries/entry/${entryId}`)
- .then((result) => {
- this.fire("hass-reload-entries");
- if (result.require_restart) {
- alert(
- this.localize(
- "ui.panel.config.integrations.config_entry.restart_confirm"
- )
- );
- }
- this.navigate("/config/integrations/dashboard", true);
- });
- }
-}
-
-customElements.define("ha-config-entry-page", HaConfigEntryPage);
diff --git a/src/panels/config/integrations/ha-config-entry-page.ts b/src/panels/config/integrations/ha-config-entry-page.ts
new file mode 100644
index 0000000000..b14e2fe469
--- /dev/null
+++ b/src/panels/config/integrations/ha-config-entry-page.ts
@@ -0,0 +1,189 @@
+import memoizeOne from "memoize-one";
+import "../../../layouts/hass-subpage";
+import "../../../layouts/hass-error-screen";
+
+import "../../../components/entity/state-badge";
+import { compare } from "../../../common/string/compare";
+
+import "./ha-device-card";
+import "./ha-ce-entities-card";
+import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
+import { property, LitElement, CSSResult, css, html } from "lit-element";
+import { navigate } from "../../../common/navigate";
+import { HomeAssistant } from "../../../types";
+import { ConfigEntry, deleteConfigEntry } from "../../../data/config_entries";
+import { EntityRegistryEntry } from "../../../data/entity_registry";
+import { DeviceRegistryEntry } from "../../../data/device_registry";
+import { AreaRegistryEntry } from "../../../data/area_registry";
+import { fireEvent } from "../../../common/dom/fire_event";
+
+class HaConfigEntryPage extends LitElement {
+ @property() public hass!: HomeAssistant;
+ @property() public narrow!: boolean;
+ @property() public configEntryId!: string;
+ @property() public configEntries!: ConfigEntry[];
+ @property() public entityRegistryEntries!: EntityRegistryEntry[];
+ @property() public deviceRegistryEntries!: DeviceRegistryEntry[];
+ @property() public areas!: AreaRegistryEntry[];
+
+ private get _configEntry(): ConfigEntry | undefined {
+ return this.configEntries
+ ? this.configEntries.find(
+ (entry) => entry.entry_id === this.configEntryId
+ )
+ : undefined;
+ }
+
+ private _computeConfigEntryDevices = memoizeOne(
+ (configEntry: ConfigEntry, devices: DeviceRegistryEntry[]) => {
+ if (!devices) {
+ return [];
+ }
+ return devices
+ .filter((device) =>
+ device.config_entries.includes(configEntry.entry_id)
+ )
+ .sort(
+ (dev1, dev2) =>
+ Number(!!dev1.via_device_id) - Number(!!dev2.via_device_id) ||
+ compare(dev1.name || "", dev2.name || "")
+ );
+ }
+ );
+
+ private _computeNoDeviceEntities = memoizeOne(
+ (configEntry: ConfigEntry, entities: EntityRegistryEntry[]) => {
+ if (!entities) {
+ return [];
+ }
+ return entities.filter(
+ (ent) => !ent.device_id && ent.config_entry_id === configEntry.entry_id
+ );
+ }
+ );
+
+ protected render() {
+ const configEntry = this._configEntry;
+
+ if (!configEntry) {
+ return html`
+
+ `;
+ }
+
+ const configEntryDevices = this._computeConfigEntryDevices(
+ configEntry,
+ this.deviceRegistryEntries
+ );
+
+ const noDeviceEntities = this._computeNoDeviceEntities(
+ configEntry,
+ this.entityRegistryEntries
+ );
+
+ return html`
+
+ ${configEntry.supports_options
+ ? html`
+
+ `
+ : ""}
+
+
+ ${configEntryDevices.length === 0 && noDeviceEntities.length === 0
+ ? html`
+
+ ${this.hass.localize(
+ "ui.panel.config.integrations.config_entry.no_devices"
+ )}
+
+ `
+ : ""}
+ ${configEntryDevices.map(
+ (device) => html`
+
+ `
+ )}
+ ${noDeviceEntities.length > 0
+ ? html`
+
+ `
+ : ""}
+
+
+ `;
+ }
+
+ private _showSettings() {
+ showOptionsFlowDialog(this, this._configEntry!);
+ }
+
+ private _removeEntry() {
+ if (
+ !confirm(
+ this.hass.localize(
+ "ui.panel.config.integrations.config_entry.delete_confirm"
+ )
+ )
+ ) {
+ return;
+ }
+
+ deleteConfigEntry(this.hass, this.configEntryId).then((result) => {
+ fireEvent(this, "hass-reload-entries");
+ if (result.require_restart) {
+ alert(
+ this.hass.localize(
+ "ui.panel.config.integrations.config_entry.restart_confirm"
+ )
+ );
+ }
+ navigate(this, "/config/integrations/dashboard", true);
+ });
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ .content {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 4px;
+ justify-content: center;
+ }
+ .card {
+ box-sizing: border-box;
+ display: flex;
+ flex: 1 0 300px;
+ min-width: 0;
+ max-width: 500px;
+ padding: 8px;
+ }
+ `;
+ }
+}
+
+customElements.define("ha-config-entry-page", HaConfigEntryPage);
diff --git a/src/panels/config/integrations/ha-config-integrations.js b/src/panels/config/integrations/ha-config-integrations.js
deleted file mode 100644
index 80ce069611..0000000000
--- a/src/panels/config/integrations/ha-config-integrations.js
+++ /dev/null
@@ -1,161 +0,0 @@
-import "@polymer/app-route/app-route";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import { Debouncer } from "@polymer/polymer/lib/utils/debounce";
-import { timeOut } from "@polymer/polymer/lib/utils/async";
-
-import "./ha-config-entries-dashboard";
-import "./ha-config-entry-page";
-import NavigateMixin from "../../../mixins/navigate-mixin";
-import { compare } from "../../../common/string/compare";
-import { subscribeAreaRegistry } from "../../../data/area_registry";
-
-class HaConfigIntegrations extends NavigateMixin(PolymerElement) {
- static get template() {
- return html`
-
-
-
-
-
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: Object,
- isWide: Boolean,
- narrow: Boolean,
- route: Object,
-
- _configEntry: {
- type: Object,
- computed: "_computeConfigEntry(_routeData, _entries)",
- },
-
- /**
- * Existing entries.
- */
- _entries: Array,
-
- /**
- * Entity Registry entries.
- */
- _entities: Array,
-
- /**
- * Device Registry entries.
- */
- _devices: Array,
-
- /**
- * Area Registry entries.
- */
- _areas: Array,
-
- /**
- * Current flows that are in progress and have not been started by a user.
- * For example, can be discovered devices that require more config.
- */
- _progress: Array,
-
- _handlers: Array,
-
- _routeData: Object,
- _routeTail: Object,
- };
- }
-
- ready() {
- super.ready();
- this.addEventListener("hass-reload-entries", () => this._loadData());
- }
-
- connectedCallback() {
- super.connectedCallback();
- this._loadData();
- this._unsubAreas = subscribeAreaRegistry(this.hass.connection, (areas) => {
- this._areas = areas;
- });
-
- this.hass.connection
- .subscribeEvents(() => {
- this._debouncer = Debouncer.debounce(
- this._debouncer,
- timeOut.after(500),
- () => this._loadData()
- );
- }, "config_entry_discovered")
- .then((unsub) => {
- this._unsubEvents = unsub;
- });
- }
-
- disconnectedCallback() {
- super.disconnectedCallback();
- if (this._unsubEvents) this._unsubEvents();
- if (this._unsubAreas) this._unsubAreas();
- }
-
- _loadData() {
- this.hass.callApi("get", "config/config_entries/entry").then((entries) => {
- this._entries = entries.sort((conf1, conf2) =>
- compare(conf1.title, conf2.title)
- );
- });
-
- this.hass.callApi("get", "config/config_entries/flow").then((progress) => {
- this._progress = progress;
- });
-
- this.hass
- .callApi("get", "config/config_entries/flow_handlers")
- .then((handlers) => {
- this._handlers = handlers;
- });
-
- this.hass
- .callWS({ type: "config/entity_registry/list" })
- .then((entities) => {
- this._entities = entities;
- });
-
- this.hass
- .callWS({ type: "config/device_registry/list" })
- .then((devices) => {
- this._devices = devices;
- });
- }
-
- _computeConfigEntry(routeData, entries) {
- return (
- !!entries &&
- !!routeData &&
- entries.find((ent) => ent.entry_id === routeData.page)
- );
- }
-}
-
-customElements.define("ha-config-integrations", HaConfigIntegrations);
diff --git a/src/panels/config/integrations/ha-config-integrations.ts b/src/panels/config/integrations/ha-config-integrations.ts
new file mode 100644
index 0000000000..07ccf9e1f2
--- /dev/null
+++ b/src/panels/config/integrations/ha-config-integrations.ts
@@ -0,0 +1,140 @@
+import "@polymer/app-route/app-route";
+
+import "./ha-config-entries-dashboard";
+import "./ha-config-entry-page";
+import { compare } from "../../../common/string/compare";
+import {
+ subscribeAreaRegistry,
+ AreaRegistryEntry,
+} from "../../../data/area_registry";
+import {
+ HassRouterPage,
+ RouterOptions,
+} from "../../../layouts/hass-router-page";
+import { property, customElement, PropertyValues } from "lit-element";
+import { HomeAssistant } from "../../../types";
+import { ConfigEntry, getConfigEntries } from "../../../data/config_entries";
+import {
+ EntityRegistryEntry,
+ subscribeEntityRegistry,
+} from "../../../data/entity_registry";
+import {
+ DeviceRegistryEntry,
+ subscribeDeviceRegistry,
+} from "../../../data/device_registry";
+import { UnsubscribeFunc } from "home-assistant-js-websocket";
+import { DataEntryFlowProgress } from "../../../data/data_entry_flow";
+import { subscribeConfigFlowInProgress } from "../../../data/config_flow";
+
+declare global {
+ interface HASSDomEvents {
+ "hass-reload-entries": undefined;
+ }
+}
+
+@customElement("ha-config-integrations")
+class HaConfigIntegrations extends HassRouterPage {
+ @property() public hass!: HomeAssistant;
+ @property() public narrow!: boolean;
+
+ protected routerOptions: RouterOptions = {
+ defaultPage: "dashboard",
+ preloadAll: true,
+ routes: {
+ dashboard: {
+ tag: "ha-config-entries-dashboard",
+ },
+ config_entry: {
+ tag: "ha-config-entry-page",
+ },
+ },
+ };
+
+ @property() private _configEntries?: ConfigEntry[];
+ @property() private _configEntriesInProgress?: DataEntryFlowProgress[];
+ @property() private _entityRegistryEntries?: EntityRegistryEntry[];
+ @property() private _deviceRegistryEntries?: DeviceRegistryEntry[];
+ @property() private _areas?: AreaRegistryEntry[];
+
+ private _unsubs?: UnsubscribeFunc[];
+
+ public connectedCallback() {
+ super.connectedCallback();
+
+ if (!this.hass) {
+ return;
+ }
+ this._loadData();
+ }
+
+ public disconnectedCallback() {
+ super.disconnectedCallback();
+ if (this._unsubs) {
+ while (this._unsubs.length) {
+ this._unsubs.pop()!();
+ }
+ this._unsubs = undefined;
+ }
+ }
+
+ protected firstUpdated(changedProps) {
+ super.firstUpdated(changedProps);
+ this.addEventListener("hass-reload-entries", () => this._loadData());
+ }
+
+ protected updated(changedProps: PropertyValues) {
+ super.updated(changedProps);
+ if (!this._unsubs && changedProps.has("hass")) {
+ this._loadData();
+ }
+ }
+
+ protected updatePageEl(pageEl) {
+ pageEl.hass = this.hass;
+
+ if (this._currentPage === "dashboard") {
+ pageEl.entities = this._entityRegistryEntries;
+ pageEl.entries = this._configEntries;
+ pageEl.progress = this._configEntriesInProgress;
+ return;
+ }
+
+ pageEl.entityRegistryEntries = this._entityRegistryEntries;
+ pageEl.configEntries = this._configEntries;
+ pageEl.configEntryId = this.routeTail.path.substr(1);
+ pageEl.deviceRegistryEntries = this._deviceRegistryEntries;
+ pageEl.areas = this._areas;
+ pageEl.narrow = this.narrow;
+ }
+
+ private _loadData() {
+ getConfigEntries(this.hass).then((configEntries) => {
+ this._configEntries = configEntries.sort((conf1, conf2) =>
+ compare(conf1.title, conf2.title)
+ );
+ });
+ if (this._unsubs) {
+ return;
+ }
+ this._unsubs = [
+ subscribeAreaRegistry(this.hass.connection, (areas) => {
+ this._areas = areas;
+ }),
+ subscribeEntityRegistry(this.hass.connection, (entries) => {
+ this._entityRegistryEntries = entries;
+ }),
+ subscribeDeviceRegistry(this.hass.connection, (entries) => {
+ this._deviceRegistryEntries = entries;
+ }),
+ subscribeConfigFlowInProgress(this.hass, (flowsInProgress) => {
+ this._configEntriesInProgress = flowsInProgress;
+ }),
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ha-config-integrations": HaConfigIntegrations;
+ }
+}
From 01da25d2d6eba3ee848865f9af5866a3f1f473ae Mon Sep 17 00:00:00 2001
From: Paulus Schoutsen
Date: Mon, 19 Aug 2019 23:59:32 -0700
Subject: [PATCH 5/8] Allow disabling entity in entity registry (#3496)
* Allow disabling entitiy in entity registry
* Make strings translatable
* Update dialog-entity-registry-detail.ts
* Change to enabled
---
src/data/entity_registry.ts | 7 +-
.../dialog-entity-registry-detail.ts | 73 ++++++++++++++-----
.../ha-config-entity-registry.ts | 30 ++++++--
src/translations/en.json | 13 +++-
4 files changed, 95 insertions(+), 28 deletions(-)
diff --git a/src/data/entity_registry.ts b/src/data/entity_registry.ts
index f6549ee533..a3037e45cb 100644
--- a/src/data/entity_registry.ts
+++ b/src/data/entity_registry.ts
@@ -9,12 +9,13 @@ export interface EntityRegistryEntry {
platform: string;
config_entry_id?: string;
device_id?: string;
- disabled_by?: string;
+ disabled_by: string | null;
}
export interface EntityRegistryEntryUpdateParams {
- name: string | null;
- new_entity_id: string;
+ name?: string | null;
+ disabled_by?: string | null;
+ new_entity_id?: string;
}
export const computeEntityRegistryName = (
diff --git a/src/panels/config/entity_registry/dialog-entity-registry-detail.ts b/src/panels/config/entity_registry/dialog-entity-registry-detail.ts
index 391e72d16c..2a6ac0553f 100644
--- a/src/panels/config/entity_registry/dialog-entity-registry-detail.ts
+++ b/src/panels/config/entity_registry/dialog-entity-registry-detail.ts
@@ -2,12 +2,13 @@ import {
LitElement,
html,
css,
- PropertyDeclarations,
CSSResult,
TemplateResult,
+ property,
} from "lit-element";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
import "@polymer/paper-input/paper-input";
+import "@polymer/paper-toggle-button/paper-toggle-button";
import "../../../components/dialog/ha-paper-dialog";
@@ -20,21 +21,13 @@ import { HassEntity } from "home-assistant-js-websocket";
import computeStateName from "../../../common/entity/compute_state_name";
class DialogEntityRegistryDetail extends LitElement {
- public hass!: HomeAssistant;
- private _name!: string;
- private _entityId!: string;
- private _error?: string;
- private _params?: EntityRegistryDetailDialogParams;
- private _submitting?: boolean;
-
- static get properties(): PropertyDeclarations {
- return {
- _error: {},
- _name: {},
- _entityId: {},
- _params: {},
- };
- }
+ @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;
public async showDialog(
params: EntityRegistryDetailDialogParams
@@ -43,6 +36,7 @@ class DialogEntityRegistryDetail extends LitElement {
this._error = undefined;
this._name = this._params.entry.name || "";
this._entityId = this._params.entry.entity_id;
+ this._disabledBy = this._params.entry.disabled_by;
await this.updateComplete;
}
@@ -62,7 +56,11 @@ class DialogEntityRegistryDetail extends LitElement {
opened
@opened-changed="${this._openedChanged}"
>
- ${entry.entity_id}
+
+ ${stateObj
+ ? computeStateName(stateObj)
+ : entry.name || entry.entity_id}
+
${!stateObj
? html`
@@ -96,6 +94,35 @@ class DialogEntityRegistryDetail extends LitElement {
.invalid=${invalidDomainUpdate}
.disabled=${this._submitting}
>
+
+
+
+
+ ${this.hass.localize(
+ "ui.panel.config.entity_registry.editor.enabled_label"
+ )}
+
+
+ ${this._disabledBy && this._disabledBy !== "user"
+ ? this.hass.localize(
+ "ui.panel.config.entity_registry.editor.enabled_cause",
+ "cause",
+ this.hass.localize(
+ `config_entry.disabled_by.${this._disabledBy}`
+ )
+ )
+ : ""}
+ ${this.hass.localize(
+ "ui.panel.config.entity_registry.editor.enabled_description"
+ )}
+
Note: this might not work yet with all integrations.
+
+
+
+