Rework ZHA group adds and removes (#5602)

This commit is contained in:
David F. Mulcahey 2020-05-12 15:42:29 -04:00 committed by GitHub
parent 1b2841eef9
commit 577a21fc5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 276 additions and 194 deletions

View File

@ -3,6 +3,7 @@ import { HomeAssistant } from "../types";
export interface ZHAEntityReference extends HassEntity { export interface ZHAEntityReference extends HassEntity {
name: string; name: string;
original_name?: string;
} }
export interface ZHADevice { export interface ZHADevice {
@ -26,6 +27,12 @@ export interface ZHADevice {
signature: any; signature: any;
} }
export interface ZHADeviceEndpoint {
device: ZHADevice;
endpoint_id: number;
entities: ZHAEntityReference[];
}
export interface Attribute { export interface Attribute {
name: string; name: string;
id: number; id: number;
@ -56,7 +63,12 @@ export interface ReadAttributeServiceData {
export interface ZHAGroup { export interface ZHAGroup {
name: string; name: string;
group_id: number; group_id: number;
members: ZHADevice[]; members: ZHADeviceEndpoint[];
}
export interface ZHAGroupMember {
ieee: string;
endpoint_id: string;
} }
export const reconfigureNode = ( export const reconfigureNode = (
@ -213,7 +225,7 @@ export const fetchGroup = (
export const fetchGroupableDevices = ( export const fetchGroupableDevices = (
hass: HomeAssistant hass: HomeAssistant
): Promise<ZHADevice[]> => ): Promise<ZHADeviceEndpoint[]> =>
hass.callWS({ hass.callWS({
type: "zha/devices/groupable", type: "zha/devices/groupable",
}); });
@ -221,7 +233,7 @@ export const fetchGroupableDevices = (
export const addMembersToGroup = ( export const addMembersToGroup = (
hass: HomeAssistant, hass: HomeAssistant,
groupId: number, groupId: number,
membersToAdd: string[] membersToAdd: ZHAGroupMember[]
): Promise<ZHAGroup> => ): Promise<ZHAGroup> =>
hass.callWS({ hass.callWS({
type: "zha/group/members/add", type: "zha/group/members/add",
@ -232,7 +244,7 @@ export const addMembersToGroup = (
export const removeMembersFromGroup = ( export const removeMembersFromGroup = (
hass: HomeAssistant, hass: HomeAssistant,
groupId: number, groupId: number,
membersToRemove: string[] membersToRemove: ZHAGroupMember[]
): Promise<ZHAGroup> => ): Promise<ZHAGroup> =>
hass.callWS({ hass.callWS({
type: "zha/group/members/remove", type: "zha/group/members/remove",
@ -243,7 +255,7 @@ export const removeMembersFromGroup = (
export const addGroup = ( export const addGroup = (
hass: HomeAssistant, hass: HomeAssistant,
groupName: string, groupName: string,
membersToAdd?: string[] membersToAdd?: ZHAGroupMember[]
): Promise<ZHAGroup> => ): Promise<ZHAGroup> =>
hass.callWS({ hass.callWS({
type: "zha/group/add", type: "zha/group/add",

View File

@ -18,31 +18,31 @@ import type { SelectionChangedEvent } from "../../../components/data-table/ha-da
import { import {
addGroup, addGroup,
fetchGroupableDevices, fetchGroupableDevices,
ZHADevice,
ZHAGroup, ZHAGroup,
ZHADeviceEndpoint,
} from "../../../data/zha"; } from "../../../data/zha";
import "../../../layouts/hass-error-screen"; import "../../../layouts/hass-error-screen";
import "../../../layouts/hass-subpage"; import "../../../layouts/hass-subpage";
import type { PolymerChangedEvent } from "../../../polymer-types"; import type { PolymerChangedEvent } from "../../../polymer-types";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "../ha-config-section"; import "../ha-config-section";
import "./zha-devices-data-table"; import "./zha-device-endpoint-data-table";
import type { ZHADevicesDataTable } from "./zha-devices-data-table"; import type { ZHADeviceEndpointDataTable } from "./zha-device-endpoint-data-table";
@customElement("zha-add-group-page") @customElement("zha-add-group-page")
export class ZHAAddGroupPage extends LitElement { export class ZHAAddGroupPage extends LitElement {
@property() public hass!: HomeAssistant; @property({ type: Object }) public hass!: HomeAssistant;
@property() public narrow!: boolean; @property({ type: Boolean }) public narrow!: boolean;
@property() public devices: ZHADevice[] = []; @property({ type: Array }) public deviceEndpoints: ZHADeviceEndpoint[] = [];
@property() private _processingAdd = false; @property() private _processingAdd = false;
@property() private _groupName = ""; @property() private _groupName = "";
@query("zha-devices-data-table") @query("zha-device-endpoint-data-table")
private _zhaDevicesDataTable!: ZHADevicesDataTable; private _zhaDevicesDataTable!: ZHADeviceEndpointDataTable;
private _firstUpdatedCalled = false; private _firstUpdatedCalled = false;
@ -87,14 +87,14 @@ export class ZHAAddGroupPage extends LitElement {
${this.hass.localize("ui.panel.config.zha.groups.add_members")} ${this.hass.localize("ui.panel.config.zha.groups.add_members")}
</div> </div>
<zha-devices-data-table <zha-device-endpoint-data-table
.hass=${this.hass} .hass=${this.hass}
.devices=${this.devices} .deviceEndpoints=${this.deviceEndpoints}
.narrow=${this.narrow} .narrow=${this.narrow}
selectable selectable
@selection-changed=${this._handleAddSelectionChanged} @selection-changed=${this._handleAddSelectionChanged}
> >
</zha-devices-data-table> </zha-device-endpoint-data-table>
<div class="paper-dialog-buttons"> <div class="paper-dialog-buttons">
<mwc-button <mwc-button
@ -121,7 +121,7 @@ export class ZHAAddGroupPage extends LitElement {
} }
private async _fetchData() { private async _fetchData() {
this.devices = await fetchGroupableDevices(this.hass!); this.deviceEndpoints = await fetchGroupableDevices(this.hass!);
} }
private _handleAddSelectionChanged( private _handleAddSelectionChanged(
@ -132,11 +132,11 @@ export class ZHAAddGroupPage extends LitElement {
private async _createGroup(): Promise<void> { private async _createGroup(): Promise<void> {
this._processingAdd = true; this._processingAdd = true;
const group: ZHAGroup = await addGroup( const members = this._selectedDevicesToAdd.map((member) => {
this.hass, const memberParts = member.split("_");
this._groupName, return { ieee: memberParts[0], endpoint_id: memberParts[1] };
this._selectedDevicesToAdd });
); const group: ZHAGroup = await addGroup(this.hass, this._groupName, members);
this._selectedDevicesToAdd = []; this._selectedDevicesToAdd = [];
this._processingAdd = false; this._processingAdd = false;
this._groupName = ""; this._groupName = "";

View File

@ -16,6 +16,7 @@ import "../../../components/data-table/ha-data-table";
import type { import type {
DataTableColumnContainer, DataTableColumnContainer,
RowClickedEvent, RowClickedEvent,
DataTableRowData,
} from "../../../components/data-table/ha-data-table"; } from "../../../components/data-table/ha-data-table";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon-next"; import "../../../components/ha-icon-next";
@ -27,19 +28,19 @@ import type { HomeAssistant, Route } from "../../../types";
import "../ha-config-section"; import "../ha-config-section";
import { formatAsPaddedHex, sortZHADevices } from "./functions"; import { formatAsPaddedHex, sortZHADevices } from "./functions";
export interface DeviceRowData extends ZHADevice { export interface DeviceRowData extends DataTableRowData {
device?: DeviceRowData; device?: DeviceRowData;
} }
@customElement("zha-config-dashboard") @customElement("zha-config-dashboard")
class ZHAConfigDashboard extends LitElement { class ZHAConfigDashboard extends LitElement {
@property() public hass!: HomeAssistant; @property({ type: Object }) public hass!: HomeAssistant;
@property() public route!: Route; @property({ type: Object }) public route!: Route;
@property() public narrow!: boolean; @property({ type: Boolean }) public narrow!: boolean;
@property() public isWide!: boolean; @property({ type: Boolean }) public isWide!: boolean;
@property() private _devices: ZHADevice[] = []; @property() private _devices: ZHADevice[] = [];
@ -91,7 +92,7 @@ class ZHAConfigDashboard extends LitElement {
title: "IEEE", title: "IEEE",
sortable: true, sortable: true,
filterable: true, filterable: true,
width: "25%", width: "30%",
}, },
} }
); );

View File

@ -0,0 +1,182 @@
import {
customElement,
html,
LitElement,
property,
query,
TemplateResult,
css,
CSSResult,
} from "lit-element";
import memoizeOne from "memoize-one";
import "../../../components/data-table/ha-data-table";
import type {
DataTableColumnContainer,
HaDataTable,
DataTableRowData,
} from "../../../components/data-table/ha-data-table";
import "../../../components/entity/ha-state-icon";
import type { ZHADeviceEndpoint, ZHAEntityReference } from "../../../data/zha";
import { showZHADeviceInfoDialog } from "../../../dialogs/zha-device-info-dialog/show-dialog-zha-device-info";
import type { HomeAssistant } from "../../../types";
export interface DeviceEndpointRowData extends DataTableRowData {
id: string;
name: string;
model: string;
manufacturer: string;
endpoint_id: number;
entities: ZHAEntityReference[];
}
@customElement("zha-device-endpoint-data-table")
export class ZHADeviceEndpointDataTable extends LitElement {
@property({ type: Object }) public hass!: HomeAssistant;
@property({ type: Boolean }) public narrow = false;
@property({ type: Boolean }) public selectable = false;
@property({ type: Array }) public deviceEndpoints: ZHADeviceEndpoint[] = [];
@query("ha-data-table") private _dataTable!: HaDataTable;
private _deviceEndpoints = memoizeOne(
(deviceEndpoints: ZHADeviceEndpoint[]) => {
const outputDevices: DeviceEndpointRowData[] = [];
deviceEndpoints.forEach((deviceEndpoint) => {
outputDevices.push({
name:
deviceEndpoint.device.user_given_name || deviceEndpoint.device.name,
model: deviceEndpoint.device.model,
manufacturer: deviceEndpoint.device.manufacturer,
id: deviceEndpoint.device.ieee + "_" + deviceEndpoint.endpoint_id,
ieee: deviceEndpoint.device.ieee,
endpoint_id: deviceEndpoint.endpoint_id,
entities: deviceEndpoint.entities,
});
});
return outputDevices;
}
);
private _columns = memoizeOne(
(narrow: boolean): DataTableColumnContainer =>
narrow
? {
name: {
title: "Devices",
sortable: true,
filterable: true,
direction: "asc",
grows: true,
template: (name) => html`
<div
class="mdc-data-table__cell table-cell-text"
@click=${this._handleClicked}
style="cursor: pointer;"
>
${name}
</div>
`,
},
endpoint_id: {
title: "Endpoint",
sortable: true,
filterable: true,
},
}
: {
name: {
title: "Name",
sortable: true,
filterable: true,
direction: "asc",
grows: true,
template: (name) => html`
<div
class="mdc-data-table__cell table-cell-text"
@click=${this._handleClicked}
style="cursor: pointer;"
>
${name}
</div>
`,
},
endpoint_id: {
title: "Endpoint",
sortable: true,
filterable: true,
},
entities: {
title: "Associated Entities",
sortable: false,
filterable: false,
width: "50%",
template: (entities) => html`
${entities.length
? entities.length > 3
? html`${entities.slice(0, 2).map(
(entity) =>
html`<div
style="overflow: hidden; text-overflow: ellipsis;"
>
${entity.name || entity.original_name}
</div>`
)}
<div>And ${entities.length - 2} more...</div>`
: entities.map(
(entity) =>
html`<div
style="overflow: hidden; text-overflow: ellipsis;"
>
${entity.name || entity.original_name}
</div>`
)
: "This endpoint has no associated entities"}
`,
},
}
);
public clearSelection() {
this._dataTable.clearSelection();
}
protected render(): TemplateResult {
return html`
<ha-data-table
.columns=${this._columns(this.narrow)}
.data=${this._deviceEndpoints(this.deviceEndpoints)}
.selectable=${this.selectable}
auto-height
></ha-data-table>
`;
}
private async _handleClicked(ev: CustomEvent) {
const rowId = ((ev.target as HTMLElement).closest(
".mdc-data-table__row"
) as any).rowId;
const ieee = rowId.substring(0, rowId.indexOf("_"));
showZHADeviceInfoDialog(this, { ieee });
}
static get styles(): CSSResult[] {
return [
css`
.table-cell-text {
word-break: break-word;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"zha-device-endpoint-data-table": ZHADeviceEndpointDataTable;
}
}

View File

@ -1,124 +0,0 @@
import {
customElement,
html,
LitElement,
property,
query,
TemplateResult,
} from "lit-element";
import memoizeOne from "memoize-one";
import "../../../components/data-table/ha-data-table";
import type {
DataTableColumnContainer,
HaDataTable,
} from "../../../components/data-table/ha-data-table";
import "../../../components/entity/ha-state-icon";
import type { ZHADevice } from "../../../data/zha";
import { showZHADeviceInfoDialog } from "../../../dialogs/zha-device-info-dialog/show-dialog-zha-device-info";
import type { HomeAssistant } from "../../../types";
export interface DeviceRowData extends ZHADevice {
device?: DeviceRowData;
}
@customElement("zha-devices-data-table")
export class ZHADevicesDataTable extends LitElement {
@property() public hass!: HomeAssistant;
@property() public narrow = false;
@property({ type: Boolean }) public selectable = false;
@property() public devices: ZHADevice[] = [];
@query("ha-data-table") private _dataTable!: HaDataTable;
private _devices = memoizeOne((devices: ZHADevice[]) => {
let outputDevices: DeviceRowData[] = devices;
outputDevices = outputDevices.map((device) => {
return {
...device,
name: device.user_given_name || device.name,
model: device.model,
manufacturer: device.manufacturer,
id: device.ieee,
};
});
return outputDevices;
});
private _columns = memoizeOne(
(narrow: boolean): DataTableColumnContainer =>
narrow
? {
name: {
title: "Devices",
sortable: true,
filterable: true,
direction: "asc",
grows: true,
template: (name) => html`
<div @click=${this._handleClicked} style="cursor: pointer;">
${name}
</div>
`,
},
}
: {
name: {
title: "Name",
sortable: true,
filterable: true,
direction: "asc",
grows: true,
template: (name) => html`
<div @click=${this._handleClicked} style="cursor: pointer;">
${name}
</div>
`,
},
manufacturer: {
title: "Manufacturer",
sortable: true,
filterable: true,
width: "20%",
},
model: {
title: "Model",
sortable: true,
filterable: true,
width: "20%",
},
}
);
public clearSelection() {
this._dataTable.clearSelection();
}
protected render(): TemplateResult {
return html`
<ha-data-table
.columns=${this._columns(this.narrow)}
.data=${this._devices(this.devices)}
.selectable=${this.selectable}
auto-height
></ha-data-table>
`;
}
private async _handleClicked(ev: CustomEvent) {
const ieee = ((ev.target as HTMLElement).closest(
".mdc-data-table__row"
) as any).rowId;
showZHADeviceInfoDialog(this, { ieee });
}
}
declare global {
interface HTMLElementTagNameMap {
"zha-devices-data-table": ZHADevicesDataTable;
}
}

View File

@ -9,8 +9,8 @@ import {
LitElement, LitElement,
property, property,
PropertyValues, PropertyValues,
query,
} from "lit-element"; } from "lit-element";
import memoizeOne from "memoize-one";
import { HASSDomEvent } from "../../../common/dom/fire_event"; import { HASSDomEvent } from "../../../common/dom/fire_event";
import { navigate } from "../../../common/navigate"; import { navigate } from "../../../common/navigate";
import { SelectionChangedEvent } from "../../../components/data-table/ha-data-table"; import { SelectionChangedEvent } from "../../../components/data-table/ha-data-table";
@ -20,8 +20,8 @@ import {
fetchGroupableDevices, fetchGroupableDevices,
removeGroups, removeGroups,
removeMembersFromGroup, removeMembersFromGroup,
ZHADevice,
ZHAGroup, ZHAGroup,
ZHADeviceEndpoint,
} from "../../../data/zha"; } from "../../../data/zha";
import "../../../layouts/hass-error-screen"; import "../../../layouts/hass-error-screen";
import "../../../layouts/hass-subpage"; import "../../../layouts/hass-subpage";
@ -29,37 +29,40 @@ import { HomeAssistant } from "../../../types";
import "../ha-config-section"; import "../ha-config-section";
import { formatAsPaddedHex } from "./functions"; import { formatAsPaddedHex } from "./functions";
import "./zha-device-card"; import "./zha-device-card";
import "./zha-devices-data-table"; import "./zha-device-endpoint-data-table";
import type { ZHADeviceEndpointDataTable } from "./zha-device-endpoint-data-table";
@customElement("zha-group-page") @customElement("zha-group-page")
export class ZHAGroupPage extends LitElement { export class ZHAGroupPage extends LitElement {
@property() public hass!: HomeAssistant; @property({ type: Object }) public hass!: HomeAssistant;
@property() public group?: ZHAGroup; @property({ type: Object }) public group?: ZHAGroup;
@property() public groupId!: number; @property({ type: Number }) public groupId!: number;
@property() public narrow!: boolean; @property({ type: Boolean }) public narrow!: boolean;
@property() public isWide!: boolean; @property({ type: Boolean }) public isWide!: boolean;
@property() public devices: ZHADevice[] = []; @property({ type: Array }) public deviceEndpoints: ZHADeviceEndpoint[] = [];
@property() private _processingAdd = false; @property() private _processingAdd = false;
@property() private _processingRemove = false; @property() private _processingRemove = false;
@property() private _filteredDevices: ZHADevice[] = []; @property() private _filteredDeviceEndpoints: ZHADeviceEndpoint[] = [];
@property() private _selectedDevicesToAdd: string[] = []; @property() private _selectedDevicesToAdd: string[] = [];
@property() private _selectedDevicesToRemove: string[] = []; @property() private _selectedDevicesToRemove: string[] = [];
private _firstUpdatedCalled = false; @query("#addMembers")
private _zhaAddMembersDataTable!: ZHADeviceEndpointDataTable;
private _members = memoizeOne( @query("#removeMembers")
(group: ZHAGroup): ZHADevice[] => group.members private _zhaRemoveMembersDataTable!: ZHADeviceEndpointDataTable;
);
private _firstUpdatedCalled = false;
public connectedCallback(): void { public connectedCallback(): void {
super.connectedCallback(); super.connectedCallback();
@ -74,8 +77,8 @@ export class ZHAGroupPage extends LitElement {
this._processingRemove = false; this._processingRemove = false;
this._selectedDevicesToRemove = []; this._selectedDevicesToRemove = [];
this._selectedDevicesToAdd = []; this._selectedDevicesToAdd = [];
this.devices = []; this.deviceEndpoints = [];
this._filteredDevices = []; this._filteredDeviceEndpoints = [];
} }
protected firstUpdated(changedProperties: PropertyValues): void { protected firstUpdated(changedProperties: PropertyValues): void {
@ -97,8 +100,6 @@ export class ZHAGroupPage extends LitElement {
`; `;
} }
const members = this._members(this.group);
return html` return html`
<hass-subpage .header=${this.group.name}> <hass-subpage .header=${this.group.name}>
<ha-icon-button <ha-icon-button
@ -122,13 +123,13 @@ export class ZHAGroupPage extends LitElement {
${this.hass.localize("ui.panel.config.zha.groups.members")} ${this.hass.localize("ui.panel.config.zha.groups.members")}
</div> </div>
${members.length ${this.group.members.length
? members.map( ? this.group.members.map(
(member) => html` (member) => html`
<zha-device-card <zha-device-card
class="card" class="card"
.hass=${this.hass} .hass=${this.hass}
.device=${member} .device=${member.device}
.narrow=${this.narrow} .narrow=${this.narrow}
.showActions=${false} .showActions=${false}
.showEditableInfo=${false} .showEditableInfo=${false}
@ -140,7 +141,7 @@ export class ZHAGroupPage extends LitElement {
This group has no members This group has no members
</p> </p>
`} `}
${members.length ${this.group.members.length
? html` ? html`
<div class="header"> <div class="header">
${this.hass.localize( ${this.hass.localize(
@ -148,14 +149,15 @@ export class ZHAGroupPage extends LitElement {
)} )}
</div> </div>
<zha-devices-data-table <zha-device-endpoint-data-table
id="removeMembers"
.hass=${this.hass} .hass=${this.hass}
.devices=${members} .deviceEndpoints=${this.group.members}
.narrow=${this.narrow} .narrow=${this.narrow}
selectable selectable
@selection-changed=${this._handleRemoveSelectionChanged} @selection-changed=${this._handleRemoveSelectionChanged}
> >
</zha-devices-data-table> </zha-device-endpoint-data-table>
<div class="paper-dialog-buttons"> <div class="paper-dialog-buttons">
<mwc-button <mwc-button
@ -182,14 +184,15 @@ export class ZHAGroupPage extends LitElement {
${this.hass.localize("ui.panel.config.zha.groups.add_members")} ${this.hass.localize("ui.panel.config.zha.groups.add_members")}
</div> </div>
<zha-devices-data-table <zha-device-endpoint-data-table
id="addMembers"
.hass=${this.hass} .hass=${this.hass}
.devices=${this._filteredDevices} .deviceEndpoints=${this._filteredDeviceEndpoints}
.narrow=${this.narrow} .narrow=${this.narrow}
selectable selectable
@selection-changed=${this._handleAddSelectionChanged} @selection-changed=${this._handleAddSelectionChanged}
> >
</zha-devices-data-table> </zha-device-endpoint-data-table>
<div class="paper-dialog-buttons"> <div class="paper-dialog-buttons">
<mwc-button <mwc-button
@ -218,16 +221,22 @@ export class ZHAGroupPage extends LitElement {
if (this.groupId !== null && this.groupId !== undefined) { if (this.groupId !== null && this.groupId !== undefined) {
this.group = await fetchGroup(this.hass!, this.groupId); this.group = await fetchGroup(this.hass!, this.groupId);
} }
this.devices = await fetchGroupableDevices(this.hass!); this.deviceEndpoints = await fetchGroupableDevices(this.hass!);
// filter the groupable devices so we only show devices that aren't already in the group // filter the groupable devices so we only show devices that aren't already in the group
this._filterDevices(); this._filterDevices();
} }
private _filterDevices() { private _filterDevices() {
// filter the groupable devices so we only show devices that aren't already in the group // filter the groupable devices so we only show devices that aren't already in the group
this._filteredDevices = this.devices.filter((device) => { this._filteredDeviceEndpoints = this.deviceEndpoints.filter(
return !this.group!.members.some((member) => member.ieee === device.ieee); (deviceEndpoint) => {
}); return !this.group!.members.some(
(member) =>
member.device.ieee === deviceEndpoint.device.ieee &&
member.endpoint_id === deviceEndpoint.endpoint_id
);
}
);
} }
private _handleAddSelectionChanged( private _handleAddSelectionChanged(
@ -244,25 +253,27 @@ export class ZHAGroupPage extends LitElement {
private async _addMembersToGroup(): Promise<void> { private async _addMembersToGroup(): Promise<void> {
this._processingAdd = true; this._processingAdd = true;
this.group = await addMembersToGroup( const members = this._selectedDevicesToAdd.map((member) => {
this.hass, const memberParts = member.split("_");
this.groupId, return { ieee: memberParts[0], endpoint_id: memberParts[1] };
this._selectedDevicesToAdd });
); this.group = await addMembersToGroup(this.hass, this.groupId, members);
this._filterDevices(); this._filterDevices();
this._selectedDevicesToAdd = []; this._selectedDevicesToAdd = [];
this._zhaAddMembersDataTable.clearSelection();
this._processingAdd = false; this._processingAdd = false;
} }
private async _removeMembersFromGroup(): Promise<void> { private async _removeMembersFromGroup(): Promise<void> {
this._processingRemove = true; this._processingRemove = true;
this.group = await removeMembersFromGroup( const members = this._selectedDevicesToRemove.map((member) => {
this.hass, const memberParts = member.split("_");
this.groupId, return { ieee: memberParts[0], endpoint_id: memberParts[1] };
this._selectedDevicesToRemove });
); this.group = await removeMembersFromGroup(this.hass, this.groupId, members);
this._filterDevices(); this._filterDevices();
this._selectedDevicesToRemove = []; this._selectedDevicesToRemove = [];
this._zhaRemoveMembersDataTable.clearSelection();
this._processingRemove = false; this._processingRemove = false;
} }