mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 11:46:42 +00:00
Add multi select to entity registry (#4424)
* Add multi select to entity registry * Fix filter and sort on status * Remove unused prop platform * Review * Update ha-config-entity-registry.ts
This commit is contained in:
parent
2ed6d0e73c
commit
f02fa6a94b
@ -14,7 +14,7 @@ import "@material/mwc-button";
|
||||
|
||||
@customElement("search-input")
|
||||
class SearchInput extends LitElement {
|
||||
@property() private filter?: string;
|
||||
@property() public filter?: string;
|
||||
|
||||
public focus() {
|
||||
this.shadowRoot!.querySelector("paper-input")!.focus();
|
||||
|
@ -75,7 +75,7 @@ export interface DataTableSortColumnData {
|
||||
export interface DataTableColumnData extends DataTableSortColumnData {
|
||||
title: string;
|
||||
type?: "numeric" | "icon";
|
||||
template?: <T>(data: any, row: T) => TemplateResult;
|
||||
template?: <T>(data: any, row: T) => TemplateResult | string;
|
||||
}
|
||||
|
||||
export interface DataTableRowData {
|
||||
@ -88,11 +88,11 @@ export class HaDataTable extends BaseElement {
|
||||
@property({ type: Array }) public data: DataTableRowData[] = [];
|
||||
@property({ type: Boolean }) public selectable = false;
|
||||
@property({ type: String }) public id = "id";
|
||||
@property({ type: String }) public filter = "";
|
||||
protected mdcFoundation!: MDCDataTableFoundation;
|
||||
protected readonly mdcFoundationClass = MDCDataTableFoundation;
|
||||
@query(".mdc-data-table") protected mdcRoot!: HTMLElement;
|
||||
@queryAll(".mdc-data-table__row") protected rowElements!: HTMLElement[];
|
||||
@query("#header-checkbox") private _headerCheckbox!: HaCheckbox;
|
||||
@property({ type: Boolean }) private _filterable = false;
|
||||
@property({ type: Boolean }) private _headerChecked = false;
|
||||
@property({ type: Boolean }) private _headerIndeterminate = false;
|
||||
@ -108,13 +108,19 @@ export class HaDataTable extends BaseElement {
|
||||
private _worker: any | undefined;
|
||||
|
||||
private _debounceSearch = debounce(
|
||||
(ev) => {
|
||||
this._filter = ev.detail.value;
|
||||
(value: string) => {
|
||||
this._filter = value;
|
||||
},
|
||||
200,
|
||||
false
|
||||
);
|
||||
|
||||
public clearSelection(): void {
|
||||
this._headerChecked = false;
|
||||
this._headerIndeterminate = false;
|
||||
this.mdcFoundation.handleHeaderRowCheckboxChange();
|
||||
}
|
||||
|
||||
protected firstUpdated() {
|
||||
super.firstUpdated();
|
||||
this._worker = sortFilterWorker();
|
||||
@ -146,6 +152,10 @@ export class HaDataTable extends BaseElement {
|
||||
this._sortColumns = clonedColumns;
|
||||
}
|
||||
|
||||
if (properties.has("filter")) {
|
||||
this._debounceSearch(this.filter);
|
||||
}
|
||||
|
||||
if (
|
||||
properties.has("data") ||
|
||||
properties.has("columns") ||
|
||||
@ -159,14 +169,18 @@ export class HaDataTable extends BaseElement {
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
${this._filterable
|
||||
? html`
|
||||
<search-input
|
||||
@value-changed=${this._handleSearchChange}
|
||||
></search-input>
|
||||
`
|
||||
: ""}
|
||||
<div class="mdc-data-table">
|
||||
<slot name="header">
|
||||
${this._filterable
|
||||
? html`
|
||||
<div class="table-header">
|
||||
<search-input
|
||||
@value-changed=${this._handleSearchChange}
|
||||
></search-input>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
</slot>
|
||||
<table class="mdc-data-table__table">
|
||||
<thead>
|
||||
<tr class="mdc-data-table__header-row">
|
||||
@ -178,7 +192,6 @@ export class HaDataTable extends BaseElement {
|
||||
scope="col"
|
||||
>
|
||||
<ha-checkbox
|
||||
id="header-checkbox"
|
||||
class="mdc-data-table__row-checkbox"
|
||||
@change=${this._handleHeaderRowCheckboxChange}
|
||||
.indeterminate=${this._headerIndeterminate}
|
||||
@ -372,9 +385,10 @@ export class HaDataTable extends BaseElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _handleHeaderRowCheckboxChange() {
|
||||
this._headerChecked = this._headerCheckbox.checked;
|
||||
this._headerIndeterminate = this._headerCheckbox.indeterminate;
|
||||
private _handleHeaderRowCheckboxChange(ev: Event) {
|
||||
const checkbox = ev.target as HaCheckbox;
|
||||
this._headerChecked = checkbox.checked;
|
||||
this._headerIndeterminate = checkbox.indeterminate;
|
||||
this.mdcFoundation.handleHeaderRowCheckboxChange();
|
||||
}
|
||||
|
||||
@ -387,20 +401,26 @@ export class HaDataTable extends BaseElement {
|
||||
}
|
||||
|
||||
private _handleRowClick(ev: Event) {
|
||||
const rowId = (ev.target as HTMLElement)
|
||||
.closest("tr")!
|
||||
.getAttribute("data-row-id")!;
|
||||
const target = ev.target as HTMLElement;
|
||||
if (target.tagName === "HA-CHECKBOX") {
|
||||
return;
|
||||
}
|
||||
const rowId = target.closest("tr")!.getAttribute("data-row-id")!;
|
||||
fireEvent(this, "row-click", { id: rowId }, { bubbles: false });
|
||||
}
|
||||
|
||||
private _setRowChecked(rowId: string, checked: boolean) {
|
||||
if (checked && !this._checkedRows.includes(rowId)) {
|
||||
this._checkedRows = [...this._checkedRows, rowId];
|
||||
} else if (!checked) {
|
||||
const index = this._checkedRows.indexOf(rowId);
|
||||
if (index !== -1) {
|
||||
this._checkedRows.splice(index, 1);
|
||||
if (checked) {
|
||||
if (this._checkedRows.includes(rowId)) {
|
||||
return;
|
||||
}
|
||||
this._checkedRows = [...this._checkedRows, rowId];
|
||||
} else {
|
||||
const index = this._checkedRows.indexOf(rowId);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
this._checkedRows.splice(index, 1);
|
||||
}
|
||||
fireEvent(this, "selection-changed", {
|
||||
id: rowId,
|
||||
@ -409,7 +429,7 @@ export class HaDataTable extends BaseElement {
|
||||
}
|
||||
|
||||
private _handleSearchChange(ev: CustomEvent): void {
|
||||
this._debounceSearch(ev);
|
||||
this._debounceSearch(ev.detail.value);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
@ -589,6 +609,9 @@ export class HaDataTable extends BaseElement {
|
||||
.mdc-data-table__header-cell:hover.not-sorted ha-icon {
|
||||
left: 0px;
|
||||
}
|
||||
.table-header {
|
||||
border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ import { showConfirmationDialog } from "../../../dialogs/confirmation/show-dialo
|
||||
class DialogEntityRegistryDetail extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() private _name!: string;
|
||||
@property() private _platform!: string;
|
||||
@property() private _entityId!: string;
|
||||
@property() private _disabledBy!: string | null;
|
||||
@property() private _error?: string;
|
||||
@ -45,7 +44,6 @@ class DialogEntityRegistryDetail extends LitElement {
|
||||
this._params = params;
|
||||
this._error = undefined;
|
||||
this._name = this._params.entry.name || "";
|
||||
this._platform = this._params.entry.platform;
|
||||
this._origEntityId = this._params.entry.entity_id;
|
||||
this._entityId = this._params.entry.entity_id;
|
||||
this._disabledBy = this._params.entry.disabled_by;
|
||||
@ -143,7 +141,8 @@ class DialogEntityRegistryDetail extends LitElement {
|
||||
<mwc-button
|
||||
class="warning"
|
||||
@click="${this._confirmDeleteEntry}"
|
||||
.disabled=${this._submitting}
|
||||
.disabled=${this._submitting ||
|
||||
!(stateObj && stateObj.attributes.restored)}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.editor.delete"
|
||||
@ -201,13 +200,8 @@ class DialogEntityRegistryDetail extends LitElement {
|
||||
|
||||
private _confirmDeleteEntry(): void {
|
||||
showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.editor.confirm_delete"
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.editor.confirm_delete2",
|
||||
"platform",
|
||||
this._platform
|
||||
"ui.panel.config.entity_registry.editor.confirm_delete"
|
||||
),
|
||||
confirm: () => this._deleteEntry(),
|
||||
});
|
||||
|
@ -5,19 +5,28 @@ import {
|
||||
css,
|
||||
CSSResult,
|
||||
property,
|
||||
query,
|
||||
} from "lit-element";
|
||||
import { styleMap } from "lit-html/directives/style-map";
|
||||
|
||||
import "@polymer/paper-checkbox/paper-checkbox";
|
||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||
import "@polymer/paper-item/paper-icon-item";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@polymer/paper-tooltip/paper-tooltip";
|
||||
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import {
|
||||
EntityRegistryEntry,
|
||||
computeEntityRegistryName,
|
||||
subscribeEntityRegistry,
|
||||
removeEntityRegistryEntry,
|
||||
updateEntityRegistryEntry,
|
||||
} from "../../../data/entity_registry";
|
||||
import "../../../layouts/hass-subpage";
|
||||
import "../../../layouts/hass-loading-screen";
|
||||
import "../../../components/data-table/ha-data-table";
|
||||
import "../../../components/ha-icon";
|
||||
import "../../../components/ha-switch";
|
||||
import { domainIcon } from "../../../common/entity/domain_icon";
|
||||
import { stateIcon } from "../../../common/entity/state_icon";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
@ -26,25 +35,33 @@ import {
|
||||
loadEntityRegistryDetailDialog,
|
||||
} from "./show-dialog-entity-registry-detail";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
// tslint:disable-next-line
|
||||
import { HaSwitch } from "../../../components/ha-switch";
|
||||
import memoize from "memoize-one";
|
||||
// tslint:disable-next-line
|
||||
import {
|
||||
DataTableColumnContainer,
|
||||
RowClickedEvent,
|
||||
SelectionChangedEvent,
|
||||
HaDataTable,
|
||||
DataTableColumnData,
|
||||
} from "../../../components/data-table/ha-data-table";
|
||||
import { showConfirmationDialog } from "../../../dialogs/confirmation/show-dialog-confirmation";
|
||||
|
||||
class HaConfigEntityRegistry extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
@property() public isWide?: boolean;
|
||||
@property() public isWide!: boolean;
|
||||
@property() public narrow!: boolean;
|
||||
@property() private _entities?: EntityRegistryEntry[];
|
||||
@property() private _showDisabled = false;
|
||||
@property() private _showUnavailable = true;
|
||||
@property() private _filter = "";
|
||||
@property() private _selectedEntities: string[] = [];
|
||||
@query("ha-data-table") private _dataTable!: HaDataTable;
|
||||
|
||||
private _unsubEntities?: UnsubscribeFunc;
|
||||
|
||||
private _columns = memoize(
|
||||
(_language): DataTableColumnContainer => {
|
||||
return {
|
||||
(narrow, _language): DataTableColumnContainer => {
|
||||
const columns: DataTableColumnContainer = {
|
||||
icon: {
|
||||
title: "",
|
||||
type: "icon",
|
||||
@ -60,58 +77,123 @@ class HaConfigEntityRegistry extends LitElement {
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
},
|
||||
entity_id: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.headers.entity_id"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
},
|
||||
platform: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.headers.integration"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
template: (platform) =>
|
||||
html`
|
||||
${this.hass.localize(`component.${platform}.config.title`) ||
|
||||
platform}
|
||||
`,
|
||||
},
|
||||
disabled_by: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.headers.enabled"
|
||||
),
|
||||
type: "icon",
|
||||
template: (disabledBy) => html`
|
||||
<ha-icon
|
||||
slot="item-icon"
|
||||
.icon=${disabledBy ? "hass:cancel" : "hass:check-circle"}
|
||||
></ha-icon>
|
||||
`,
|
||||
},
|
||||
};
|
||||
|
||||
const statusColumn: DataTableColumnData = {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.headers.status"
|
||||
),
|
||||
type: "icon",
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
template: (_status, entity: any) =>
|
||||
entity.unavailable || entity.disabled_by
|
||||
? html`
|
||||
<div
|
||||
tabindex="0"
|
||||
style="display:inline-block; position: relative;"
|
||||
>
|
||||
<ha-icon
|
||||
style=${styleMap({
|
||||
color: entity.unavailable ? "var(--google-red-500)" : "",
|
||||
})}
|
||||
.icon=${entity.unavailable
|
||||
? "hass:alert-circle"
|
||||
: "hass:cancel"}
|
||||
></ha-icon>
|
||||
<paper-tooltip position="left">
|
||||
${entity.unavailable
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.status.unavailable"
|
||||
)
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.status.disabled"
|
||||
)}
|
||||
</paper-tooltip>
|
||||
</div>
|
||||
`
|
||||
: "",
|
||||
};
|
||||
|
||||
if (narrow) {
|
||||
columns.name.template = (name, entity: any) => {
|
||||
return html`
|
||||
${name}<br />
|
||||
${entity.entity_id} |
|
||||
${this.hass.localize(`component.${entity.platform}.config.title`) ||
|
||||
entity.platform}
|
||||
`;
|
||||
};
|
||||
columns.status = statusColumn;
|
||||
return columns;
|
||||
}
|
||||
|
||||
columns.entity_id = {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.headers.entity_id"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
};
|
||||
columns.platform = {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.headers.integration"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
template: (platform) =>
|
||||
this.hass.localize(`component.${platform}.config.title`) || platform,
|
||||
};
|
||||
columns.status = statusColumn;
|
||||
|
||||
return columns;
|
||||
}
|
||||
);
|
||||
|
||||
private _filteredEntities = memoize(
|
||||
(entities: EntityRegistryEntry[], showDisabled: boolean) =>
|
||||
(showDisabled
|
||||
? entities
|
||||
: entities.filter((entity) => !Boolean(entity.disabled_by))
|
||||
).map((entry) => {
|
||||
(
|
||||
entities: EntityRegistryEntry[],
|
||||
showDisabled: boolean,
|
||||
showUnavailable: boolean
|
||||
) => {
|
||||
if (!showDisabled) {
|
||||
entities = entities.filter((entity) => !Boolean(entity.disabled_by));
|
||||
}
|
||||
|
||||
return entities.reduce((result, entry) => {
|
||||
const state = this.hass!.states[entry.entity_id];
|
||||
return {
|
||||
|
||||
const unavailable =
|
||||
state && (state.state === "unavailable" || state.attributes.restored); // if there is not state it is disabled
|
||||
|
||||
if (!showUnavailable && unavailable) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.push({
|
||||
...entry,
|
||||
icon: state
|
||||
? stateIcon(state)
|
||||
: domainIcon(computeDomain(entry.entity_id)),
|
||||
name:
|
||||
computeEntityRegistryName(this.hass!, entry) ||
|
||||
this.hass!.localize("state.default.unavailable"),
|
||||
};
|
||||
})
|
||||
this.hass.localize("state.default.unavailable"),
|
||||
unavailable,
|
||||
status: unavailable
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.status.unavailable"
|
||||
)
|
||||
: entry.disabled_by
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.status.disabled"
|
||||
)
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.status.ok"
|
||||
),
|
||||
});
|
||||
return result;
|
||||
}, [] as any);
|
||||
}
|
||||
);
|
||||
|
||||
public disconnectedCallback() {
|
||||
@ -133,17 +215,19 @@ class HaConfigEntityRegistry extends LitElement {
|
||||
"ui.panel.config.entity_registry.caption"
|
||||
)}"
|
||||
>
|
||||
<div class="content">
|
||||
<div class="intro">
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.header"
|
||||
)}
|
||||
</h2>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.introduction"
|
||||
)}
|
||||
<div class="content">
|
||||
<div class="intro">
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.header"
|
||||
)}
|
||||
</h2>
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.introduction"
|
||||
)}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.introduction2"
|
||||
@ -154,22 +238,123 @@ class HaConfigEntityRegistry extends LitElement {
|
||||
"ui.panel.config.entity_registry.picker.integrations_page"
|
||||
)}
|
||||
</a>
|
||||
<ha-switch
|
||||
?checked=${this._showDisabled}
|
||||
@change=${this._showDisabledChanged}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.show_disabled"
|
||||
)}
|
||||
</ha-switch>
|
||||
</div>
|
||||
</p>
|
||||
<ha-data-table
|
||||
.columns=${this._columns(this.hass.language)}
|
||||
.data=${this._filteredEntities(this._entities, this._showDisabled)}
|
||||
@row-click=${this._openEditEntry}
|
||||
id="entity_id"
|
||||
>
|
||||
</ha-data-table>
|
||||
<ha-data-table
|
||||
.columns=${this._columns(this.narrow, this.hass.language)}
|
||||
.data=${this._filteredEntities(
|
||||
this._entities,
|
||||
this._showDisabled,
|
||||
this._showUnavailable
|
||||
)}
|
||||
.filter=${this._filter}
|
||||
selectable
|
||||
@selection-changed=${this._handleSelectionChanged}
|
||||
@row-click=${this._openEditEntry}
|
||||
id="entity_id"
|
||||
>
|
||||
<div class="table-header" slot="header">
|
||||
${this._selectedEntities.length
|
||||
? html`
|
||||
<p class="selected-txt">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.selected",
|
||||
"number",
|
||||
this._selectedEntities.length
|
||||
)}
|
||||
</p>
|
||||
<div class="header-btns">
|
||||
${!this.narrow
|
||||
? html`
|
||||
<mwc-button @click=${this._enableSelected}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.enable_selected.button"
|
||||
)}</mwc-button
|
||||
>
|
||||
<mwc-button @click=${this._disableSelected}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.disable_selected.button"
|
||||
)}</mwc-button
|
||||
>
|
||||
<mwc-button @click=${this._removeSelected}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.remove_selected.button"
|
||||
)}</mwc-button
|
||||
>
|
||||
`
|
||||
: html`
|
||||
<paper-icon-button
|
||||
id="enable-btn"
|
||||
icon="hass:undo"
|
||||
@click=${this._enableSelected}
|
||||
></paper-icon-button>
|
||||
<paper-tooltip for="enable-btn">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.enable_selected.button"
|
||||
)}
|
||||
</paper-tooltip>
|
||||
<paper-icon-button
|
||||
id="disable-btn"
|
||||
icon="hass:cancel"
|
||||
@click=${this._disableSelected}
|
||||
></paper-icon-button>
|
||||
<paper-tooltip for="disable-btn">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.disable_selected.button"
|
||||
)}
|
||||
</paper-tooltip>
|
||||
<paper-icon-button
|
||||
id="remove-btn"
|
||||
icon="hass:delete"
|
||||
@click=${this._disableSelected}
|
||||
></paper-icon-button>
|
||||
<paper-tooltip for="remove-btn">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.remove_selected.button"
|
||||
)}
|
||||
</paper-tooltip>
|
||||
`}
|
||||
</div>
|
||||
`
|
||||
: html`
|
||||
<search-input
|
||||
@value-changed=${this._handleSearchChange}
|
||||
.filter=${this._filter}
|
||||
></search-input>
|
||||
<paper-menu-button no-animations horizontal-align="right">
|
||||
<paper-icon-button
|
||||
aria-label=${this.hass!.localize(
|
||||
"ui.panel.config.entity_registry.picker.filter.filter"
|
||||
)}
|
||||
title="${this.hass!.localize(
|
||||
"ui.panel.config.entity_registry.picker.filter.filter"
|
||||
)}"
|
||||
icon="hass:filter-variant"
|
||||
slot="dropdown-trigger"
|
||||
></paper-icon-button>
|
||||
<paper-listbox slot="dropdown-content">
|
||||
<paper-icon-item @click="${this._showDisabledChanged}">
|
||||
<paper-checkbox
|
||||
.checked=${this._showDisabled}
|
||||
slot="item-icon"
|
||||
></paper-checkbox>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.config.entity_registry.picker.filter.show_disabled"
|
||||
)}
|
||||
</paper-icon-item>
|
||||
<paper-icon-item @click="${this._showRestoredChanged}">
|
||||
<paper-checkbox
|
||||
.checked=${this._showUnavailable}
|
||||
slot="item-icon"
|
||||
></paper-checkbox>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.config.entity_registry.picker.filter.show_unavailable"
|
||||
)}
|
||||
</paper-icon-item>
|
||||
</paper-listbox>
|
||||
</paper-menu-button>
|
||||
`}
|
||||
</div>
|
||||
</ha-data-table>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
@ -192,8 +377,103 @@ class HaConfigEntityRegistry extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _showDisabledChanged(ev: Event) {
|
||||
this._showDisabled = (ev.target as HaSwitch).checked;
|
||||
private _showDisabledChanged() {
|
||||
this._showDisabled = !this._showDisabled;
|
||||
}
|
||||
|
||||
private _showRestoredChanged() {
|
||||
this._showUnavailable = !this._showUnavailable;
|
||||
}
|
||||
|
||||
private _handleSearchChange(ev: CustomEvent) {
|
||||
this._filter = ev.detail.value;
|
||||
}
|
||||
|
||||
private _handleSelectionChanged(ev: CustomEvent): void {
|
||||
const changedSelection = ev.detail as SelectionChangedEvent;
|
||||
const entity = changedSelection.id;
|
||||
if (changedSelection.selected) {
|
||||
this._selectedEntities = [...this._selectedEntities, entity];
|
||||
} else {
|
||||
this._selectedEntities = this._selectedEntities.filter(
|
||||
(entityId) => entityId !== entity
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _enableSelected() {
|
||||
showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.enable_selected.confirm_title",
|
||||
"number",
|
||||
this._selectedEntities.length
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.enable_selected.confirm_text"
|
||||
),
|
||||
confirmBtnText: this.hass.localize("ui.common.yes"),
|
||||
cancelBtnText: this.hass.localize("ui.common.no"),
|
||||
confirm: () => {
|
||||
this._selectedEntities.forEach((entity) =>
|
||||
updateEntityRegistryEntry(this.hass, entity, {
|
||||
disabled_by: null,
|
||||
})
|
||||
);
|
||||
this._clearSelection();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _disableSelected() {
|
||||
showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.disable_selected.confirm_title",
|
||||
"number",
|
||||
this._selectedEntities.length
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.disable_selected.confirm_text"
|
||||
),
|
||||
confirmBtnText: this.hass.localize("ui.common.yes"),
|
||||
cancelBtnText: this.hass.localize("ui.common.no"),
|
||||
confirm: () => {
|
||||
this._selectedEntities.forEach((entity) =>
|
||||
updateEntityRegistryEntry(this.hass, entity, {
|
||||
disabled_by: "user",
|
||||
})
|
||||
);
|
||||
this._clearSelection();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _removeSelected() {
|
||||
const removeableEntities = this._selectedEntities.filter((entity) => {
|
||||
const stateObj = this.hass.states[entity];
|
||||
return stateObj?.attributes.restored;
|
||||
});
|
||||
showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.remove_selected.confirm_title",
|
||||
"number",
|
||||
removeableEntities.length
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.entity_registry.picker.remove_selected.confirm_text"
|
||||
),
|
||||
confirmBtnText: this.hass.localize("ui.common.yes"),
|
||||
cancelBtnText: this.hass.localize("ui.common.no"),
|
||||
confirm: () => {
|
||||
removeableEntities.forEach((entity) =>
|
||||
removeEntityRegistryEntry(this.hass, entity)
|
||||
);
|
||||
this._clearSelection();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _clearSelection() {
|
||||
this._dataTable.clearSelection();
|
||||
}
|
||||
|
||||
private _openEditEntry(ev: CustomEvent): void {
|
||||
@ -237,18 +517,35 @@ class HaConfigEntityRegistry extends LitElement {
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
.intro {
|
||||
padding: 24px 16px 0;
|
||||
padding: 24px 16px;
|
||||
}
|
||||
.content {
|
||||
padding: 4px;
|
||||
}
|
||||
ha-data-table {
|
||||
margin-bottom: 24px;
|
||||
margin-top: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
ha-switch {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12);
|
||||
}
|
||||
search-input {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.selected-txt {
|
||||
font-weight: bold;
|
||||
margin-top: 38px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.header-btns > mwc-button,
|
||||
.header-btns > paper-icon-button {
|
||||
margin: 8px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -1257,14 +1257,38 @@
|
||||
"picker": {
|
||||
"header": "Entities",
|
||||
"introduction": "Home Assistant keeps a registry of every entity it has ever seen that can be uniquely identified. Each of these entities will have an entity ID assigned which will be reserved for just this entity.",
|
||||
"introduction2": "Use the entity registry to override the name, change the entity ID or remove the entry from Home Assistant. Note, removing the entity registry entry won't remove the entity. To do that, follow the link below and remove it from the integrations page.",
|
||||
"integrations_page": "Integrations page",
|
||||
"show_disabled": "Show disabled entities",
|
||||
"introduction2": "Use the entity registry to override the name, change the entity ID or remove the entry from Home Assistant.",
|
||||
"filter": {
|
||||
"filter": "Filter",
|
||||
"show_disabled": "Show disabled entities",
|
||||
"show_unavailable": "Show unavailable entities"
|
||||
},
|
||||
"status": {
|
||||
"unavailable": "Unavailable",
|
||||
"disabled": "Disabled",
|
||||
"ok": "Ok"
|
||||
},
|
||||
"headers": {
|
||||
"name": "Name",
|
||||
"entity_id": "Entity ID",
|
||||
"integration": "Integration",
|
||||
"enabled": "Enabled"
|
||||
"status": "Status"
|
||||
},
|
||||
"selected": "{number} selected",
|
||||
"enable_selected": {
|
||||
"button": "Enable selected",
|
||||
"confirm_title": "Do you want to enable {number} entities?",
|
||||
"confirm_text": "This will make them available in Home Assistant again if they are now disabled."
|
||||
},
|
||||
"disable_selected": {
|
||||
"button": "Disable selected",
|
||||
"confirm_title": "Do you want to disable {number} entities?",
|
||||
"confirm_text": "Disabled entities will not be added to Home Assistant."
|
||||
},
|
||||
"remove_selected": {
|
||||
"button": "Remove selected",
|
||||
"confirm_title": "Do you want to remove {number} entities?",
|
||||
"confirm_text": "Entities can only be removed when the integration is no longer providing the entities."
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
@ -1275,7 +1299,6 @@
|
||||
"enabled_description": "Disabled entities will not be added to Home Assistant.",
|
||||
"delete": "DELETE",
|
||||
"confirm_delete": "Are you sure you want to delete this entry?",
|
||||
"confirm_delete2": "Deleting an entry will not remove the entity from Home Assistant. To do this, you will need to remove the integration '{platform}' from Home Assistant.",
|
||||
"update": "UPDATE",
|
||||
"note": "Note: this might not work yet with all integrations."
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user