Utilize Hide Hidden Entities

This commit is contained in:
Zack 2022-03-14 14:22:45 -05:00
parent 3358fc2b18
commit e01cb3ca82
7 changed files with 186 additions and 99 deletions

View File

@ -14,6 +14,7 @@ export interface EntityRegistryEntry {
device_id: string | null; device_id: string | null;
area_id: string | null; area_id: string | null;
disabled_by: string | null; disabled_by: string | null;
hidden_by: string | null;
entity_category: "config" | "diagnostic" | null; entity_category: "config" | "diagnostic" | null;
} }
@ -38,6 +39,7 @@ export interface EntityRegistryEntryUpdateParams {
device_class?: string | null; device_class?: string | null;
area_id?: string | null; area_id?: string | null;
disabled_by?: string | null; disabled_by?: string | null;
hidden_by: string | null;
new_entity_id?: string; new_entity_id?: string;
} }

View File

@ -40,7 +40,7 @@ export class HaDeviceEntitiesCard extends LitElement {
@property() public entities!: EntityRegistryStateEntry[]; @property() public entities!: EntityRegistryStateEntry[];
@property() public showDisabled = false; @property() public showHidden = false;
@state() private _extDisabledEntityEntries?: Record< @state() private _extDisabledEntityEntries?: Record<
string, string,
@ -60,77 +60,75 @@ export class HaDeviceEntitiesCard extends LitElement {
} }
protected render(): TemplateResult { protected render(): TemplateResult {
const disabledEntities: EntityRegistryStateEntry[] = []; if (!this.entities.length) {
return html`
<div class="empty card-content">
${this.hass.localize("ui.panel.config.devices.entities.none")}
</div>
`;
}
const shownEntities: EntityRegistryStateEntry[] = [];
const hiddenEntities: EntityRegistryStateEntry[] = [];
this._entityRows = []; this._entityRows = [];
this.entities.forEach((entry) => {
if (entry.disabled_by || entry.hidden_by) {
if (this._extDisabledEntityEntries) {
hiddenEntities.push(
this._extDisabledEntityEntries[entry.entity_id] || entry
);
} else {
hiddenEntities.push(entry);
}
} else {
shownEntities.push(entry);
}
});
return html` return html`
<ha-card .header=${this.header}> <ha-card .header=${this.header}>
${this.entities.length <div id="entities" @hass-more-info=${this._overrideMoreInfo}>
? html` ${shownEntities.map((entry) =>
<div id="entities" @hass-more-info=${this._overrideMoreInfo}> this.hass.states[entry.entity_id]
${this.entities.map((entry: EntityRegistryStateEntry) => { ? this._renderEntity(entry)
if (entry.disabled_by) { : this._renderEntry(entry)
if (this._extDisabledEntityEntries) { )}
disabledEntities.push( </div>
this._extDisabledEntityEntries[entry.entity_id] || entry ${hiddenEntities.length
); ? !this.showHidden
} else { ? html`
disabledEntities.push(entry); <button class="show-more" @click=${this._toggleShowHidden}>
}
return "";
}
return this.hass.states[entry.entity_id]
? this._renderEntity(entry)
: this._renderEntry(entry);
})}
</div>
${disabledEntities.length
? !this.showDisabled
? html`
<button
class="show-more"
@click=${this._toggleShowDisabled}
>
${this.hass.localize(
"ui.panel.config.devices.entities.disabled_entities",
"count",
disabledEntities.length
)}
</button>
`
: html`
${disabledEntities.map((entry) =>
this._renderEntry(entry)
)}
<button
class="show-more"
@click=${this._toggleShowDisabled}
>
${this.hass.localize(
"ui.panel.config.devices.entities.hide_disabled"
)}
</button>
`
: ""}
<div class="card-actions">
<mwc-button @click=${this._addToLovelaceView}>
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.devices.entities.add_entities_lovelace" "ui.panel.config.devices.entities.disabled_entities",
"count",
hiddenEntities.length
)} )}
</mwc-button> </button>
</div> `
` : html`
: html` ${hiddenEntities.map((entry) => this._renderEntry(entry))}
<div class="empty card-content"> <button class="show-more" @click=${this._toggleShowHidden}>
${this.hass.localize("ui.panel.config.devices.entities.none")} ${this.hass.localize(
</div> "ui.panel.config.devices.entities.hide_disabled"
`} )}
</button>
`
: ""}
<div class="card-actions">
<mwc-button @click=${this._addToLovelaceView}>
${this.hass.localize(
"ui.panel.config.devices.entities.add_entities_lovelace"
)}
</mwc-button>
</div>
</ha-card> </ha-card>
`; `;
} }
private _toggleShowDisabled() { private _toggleShowHidden() {
this.showDisabled = !this.showDisabled; this.showHidden = !this.showHidden;
if (!this.showDisabled || this._extDisabledEntityEntries !== undefined) { if (!this.showHidden || this._extDisabledEntityEntries !== undefined) {
return; return;
} }
this._extDisabledEntityEntries = {}; this._extDisabledEntityEntries = {};

View File

@ -557,7 +557,7 @@ export class HaConfigDevicePage extends LitElement {
)} )}
.deviceName=${deviceName} .deviceName=${deviceName}
.entities=${entitiesByCategory[category]} .entities=${entitiesByCategory[category]}
.showDisabled=${device.disabled_by !== null} .showHidden=${device.disabled_by !== null}
> >
</ha-device-entities-card> </ha-device-entities-card>
` `

View File

@ -76,6 +76,8 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
@state() private _disabledBy!: string | null; @state() private _disabledBy!: string | null;
@state() private _hiddenBy!: string | null;
private _deviceLookup?: Record<string, DeviceRegistryEntry>; private _deviceLookup?: Record<string, DeviceRegistryEntry>;
@state() private _device?: DeviceRegistryEntry; @state() private _device?: DeviceRegistryEntry;
@ -112,6 +114,7 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
this._areaId = this.entry.area_id; this._areaId = this.entry.area_id;
this._entityId = this.entry.entity_id; this._entityId = this.entry.entity_id;
this._disabledBy = this.entry.disabled_by; this._disabledBy = this.entry.disabled_by;
this._hiddenBy = this.entry.hidden_by;
this._device = this._device =
this.entry.device_id && this._deviceLookup this.entry.device_id && this._deviceLookup
? this._deviceLookup[this.entry.device_id] ? this._deviceLookup[this.entry.device_id]
@ -244,41 +247,75 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
</div> </div>
</div> </div>
${this.entry.device_id <div class="row">
? html`<ha-expansion-panel <ha-switch
.header=${this.hass.localize( .checked=${this._hiddenBy !== null}
"ui.dialogs.entity_registry.editor.advanced" .disabled=${this._hiddenBy && this._hiddenBy !== "user"}
@change=${this._hiddenByChanged}
>
</ha-switch>
<div>
<div>
${this.hass.localize(
"ui.dialogs.entity_registry.editor.hidden_label"
)} )}
outlined </div>
> <div class="secondary">
<p> ${this._hiddenBy && this._hiddenBy !== "user"
${this.hass.localize( ? this.hass.localize(
"ui.dialogs.entity_registry.editor.area_note" "ui.dialogs.entity_registry.editor.hidden_cause",
)} "cause",
</p> this.hass.localize(
${this._areaId `config_entry.hidden_by.${this._hiddenBy}`
? html`<mwc-button @click=${this._clearArea} )
>${this.hass.localize( )
"ui.dialogs.entity_registry.editor.follow_device_area"
)}</mwc-button
>`
: this._device
? html`<mwc-button @click=${this._openDeviceSettings}
>${this.hass.localize(
"ui.dialogs.entity_registry.editor.change_device_area"
)}</mwc-button
>`
: ""} : ""}
<ha-area-picker ${this.hass.localize(
.hass=${this.hass} "ui.dialogs.entity_registry.editor.hidden_description"
.value=${this._areaId} )}
.placeholder=${this._device?.area_id} <br />${this.hass.localize(
.label=${this.hass.localize( "ui.dialogs.entity_registry.editor.note"
"ui.dialogs.entity_registry.editor.area" )}
</div>
</div>
</div>
${this.entry.device_id
? html`
<ha-expansion-panel
.header=${this.hass.localize(
"ui.dialogs.entity_registry.editor.advanced"
)} )}
@value-changed=${this._areaPicked} outlined
></ha-area-picker >
></ha-expansion-panel>` <p>
${this.hass.localize(
"ui.dialogs.entity_registry.editor.area_note"
)}
</p>
${this._areaId
? html`<mwc-button @click=${this._clearArea}
>${this.hass.localize(
"ui.dialogs.entity_registry.editor.follow_device_area"
)}</mwc-button
>`
: this._device
? html`<mwc-button @click=${this._openDeviceSettings}
>${this.hass.localize(
"ui.dialogs.entity_registry.editor.change_device_area"
)}</mwc-button
>`
: ""}
<ha-area-picker
.hass=${this.hass}
.value=${this._areaId}
.placeholder=${this._device?.area_id}
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.area"
)}
@value-changed=${this._areaPicked}
></ha-area-picker>
</ha-expansion-panel>
`
: ""} : ""}
</div> </div>
<div class="buttons"> <div class="buttons">
@ -354,6 +391,12 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
) { ) {
params.disabled_by = this._disabledBy; params.disabled_by = this._disabledBy;
} }
if (
this.entry.hidden_by !== this._hiddenBy &&
(this._hiddenBy === null || this._hiddenBy === "user")
) {
params.hidden_by = this._hiddenBy;
}
try { try {
const result = await updateEntityRegistryEntry( const result = await updateEntityRegistryEntry(
this.hass!, this.hass!,
@ -409,6 +452,10 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
this._disabledBy = (ev.target as HaSwitch).checked ? null : "user"; this._disabledBy = (ev.target as HaSwitch).checked ? null : "user";
} }
private _hiddenByChanged(ev: Event): void {
this._hiddenBy = (ev.target as HaSwitch).checked ? "user" : null;
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [
haStyle, haStyle,

View File

@ -101,6 +101,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
@state() private _showDisabled = false; @state() private _showDisabled = false;
@state() private _showHidden = false;
@state() private _showUnavailable = true; @state() private _showUnavailable = true;
@state() private _showReadOnly = true; @state() private _showReadOnly = true;
@ -301,6 +303,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
showDisabled: boolean, showDisabled: boolean,
showUnavailable: boolean, showUnavailable: boolean,
showReadOnly: boolean, showReadOnly: boolean,
showHidden: boolean,
entries?: ConfigEntry[] entries?: ConfigEntry[]
) => { ) => {
const result: EntityRow[] = []; const result: EntityRow[] = [];
@ -362,6 +365,12 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
); );
} }
if (!showHidden) {
filteredEntities = filteredEntities.filter(
(entity) => !entity.hidden_by
);
}
for (const entry of filteredEntities) { for (const entry of filteredEntities) {
const entity = this.hass.states[entry.entity_id]; const entity = this.hass.states[entry.entity_id];
const unavailable = entity?.state === UNAVAILABLE; const unavailable = entity?.state === UNAVAILABLE;
@ -465,6 +474,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
this._showDisabled, this._showDisabled,
this._showUnavailable, this._showUnavailable,
this._showReadOnly, this._showReadOnly,
this._showHidden,
this._entries this._entries
); );
@ -603,6 +613,15 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
"ui.panel.config.entities.picker.filter.show_disabled" "ui.panel.config.entities.picker.filter.show_disabled"
)} )}
</ha-check-list-item> </ha-check-list-item>
<ha-check-list-item
@request-selected=${this._showHiddenChanged}
.selected=${this._showHidden}
left
>
${this.hass!.localize(
"ui.panel.config.entities.picker.filter.show_hidden"
)}
</ha-check-list-item>
<ha-check-list-item <ha-check-list-item
@request-selected=${this._showRestoredChanged} @request-selected=${this._showRestoredChanged}
graphic="control" graphic="control"
@ -671,6 +690,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
entity_id: entityId, entity_id: entityId,
platform: computeDomain(entityId), platform: computeDomain(entityId),
disabled_by: null, disabled_by: null,
hidden_by: null,
area_id: null, area_id: null,
config_entry_id: null, config_entry_id: null,
device_id: null, device_id: null,
@ -693,6 +713,13 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
this._showDisabled = ev.detail.selected; this._showDisabled = ev.detail.selected;
} }
private _showHiddenChanged(ev: CustomEvent<RequestSelectedDetail>) {
if (ev.detail.source !== "property") {
return;
}
this._showHidden = ev.detail.selected;
}
private _showRestoredChanged(ev: CustomEvent<RequestSelectedDetail>) { private _showRestoredChanged(ev: CustomEvent<RequestSelectedDetail>) {
if (ev.detail.source !== "property") { if (ev.detail.source !== "property") {
return; return;

View File

@ -238,7 +238,10 @@ const computeDefaultViewStates = (
const hiddenEntities = new Set( const hiddenEntities = new Set(
entityEntries entityEntries
.filter( .filter(
(entry) => entry.entity_category || HIDE_PLATFORM.has(entry.platform) (entry) =>
entry.entity_category ||
HIDE_PLATFORM.has(entry.platform) ||
entry.hidden_by
) )
.map((entry) => entry.entity_id) .map((entry) => entry.entity_id)
); );

View File

@ -102,6 +102,12 @@
"integration": "Integration", "integration": "Integration",
"config_entry": "Config entry", "config_entry": "Config entry",
"device": "Device" "device": "Device"
},
"hidden_by": {
"user": "User",
"integration": "Integration",
"config_entry": "Config entry",
"device": "Device"
} }
}, },
"ui": { "ui": {
@ -785,11 +791,14 @@
"unavailable": "This entity is unavailable.", "unavailable": "This entity is unavailable.",
"enabled_label": "Enable entity", "enabled_label": "Enable entity",
"enabled_cause": "Disabled by {cause}.", "enabled_cause": "Disabled by {cause}.",
"hidden_label": "Hide entity",
"hidden_cause": "Hidden by {cause}.",
"device_disabled": "The device of this entity is disabled.", "device_disabled": "The device of this entity is disabled.",
"open_device_settings": "Open device settings", "open_device_settings": "Open device settings",
"enabled_description": "Disabled entities will not be added to Home Assistant.", "enabled_description": "Disabled entities will not be added to Home Assistant.",
"enabled_delay_confirm": "The enabled entities will be added to Home Assistant in {delay} seconds", "enabled_delay_confirm": "The enabled entities will be added to Home Assistant in {delay} seconds",
"enabled_restart_confirm": "Restart Home Assistant to finish enabling the entities", "enabled_restart_confirm": "Restart Home Assistant to finish enabling the entities",
"hidden_description": "Hidden entities will not be shown in Home Assistant UI.",
"delete": "Delete", "delete": "Delete",
"confirm_delete": "Are you sure you want to delete this entity?", "confirm_delete": "Are you sure you want to delete this entity?",
"update": "Update", "update": "Update",
@ -2364,8 +2373,8 @@
"config": "Configuration", "config": "Configuration",
"add_entities_lovelace": "Add to Lovelace", "add_entities_lovelace": "Add to Lovelace",
"none": "This device has no entities", "none": "This device has no entities",
"hide_disabled": "Hide disabled", "hide_disabled": "Hide hidden",
"disabled_entities": "+{count} {count, plural,\n one {disabled entity}\n other {disabled entities}\n}" "disabled_entities": "+{count} {count, plural,\n one {hidden entity}\n other {hidden entities}\n}"
}, },
"confirm_rename_entity_ids": "Do you also want to rename the entity IDs of your entities?", "confirm_rename_entity_ids": "Do you also want to rename the entity IDs of your entities?",
"confirm_rename_entity_ids_warning": "This will not change any configuration (like automations, scripts, scenes, dashboards) that is currently using these entities! You will have to update them yourself to use the new entity IDs!", "confirm_rename_entity_ids_warning": "This will not change any configuration (like automations, scripts, scenes, dashboards) that is currently using these entities! You will have to update them yourself to use the new entity IDs!",
@ -2405,6 +2414,7 @@
"search": "Search entities", "search": "Search entities",
"filter": { "filter": {
"filter": "Filter", "filter": "Filter",
"show_hidden": "Show hidden entities",
"show_disabled": "Show disabled entities", "show_disabled": "Show disabled entities",
"show_unavailable": "Show unavailable entities", "show_unavailable": "Show unavailable entities",
"show_readonly": "Show read-only entities", "show_readonly": "Show read-only entities",