diff --git a/src/panels/config/automation/ha-automation-picker.ts b/src/panels/config/automation/ha-automation-picker.ts index 62900a2798..28cd56dfc5 100644 --- a/src/panels/config/automation/ha-automation-picker.ts +++ b/src/panels/config/automation/ha-automation-picker.ts @@ -378,25 +378,42 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) { ${this.hass.localize("ui.panel.config.category.editor.add")} `; - const labelItems = html` ${this._labels?.map((label) => { + const labelItems = html`${this._labels?.map((label) => { const color = label.color ? computeCssColor(label.color) : undefined; + const selected = this._selected.every((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); + const partial = + !selected && + this._selected.some((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); return html` + ${label.icon ? html`` : nothing} ${label.name} - `; - })} + `; + })} +
${this.hass.localize("ui.panel.config.labels.add_label")} -
-
`; + `; return html` [] = []; this._selected.forEach((entityId) => { promises.push( updateEntityRegistryEntry(this.hass, entityId, { - labels: this.hass.entities[entityId].labels.concat(label), + labels: + action === "add" + ? this.hass.entities[entityId].labels.concat(label) + : this.hass.entities[entityId].labels.filter( + (lbl) => lbl !== label + ), }) ); }); diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index e47b567e3e..ba9630e2fa 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -546,23 +546,40 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) { const labelItems = html`${this._labels?.map((label) => { const color = label.color ? computeCssColor(label.color) : undefined; + const selected = this._selected.every((deviceId) => + this.hass.devices[deviceId]?.labels.includes(label.label_id) + ); + const partial = + !selected && + this._selected.some((deviceId) => + this.hass.devices[deviceId]?.labels.includes(label.label_id) + ); return html` + ${label.icon ? html`` : nothing} ${label.name} - `; - })} + `; + })} +
${this.hass.localize("ui.panel.config.labels.add_label")} -
-
`; + `; return html` [] = []; this._selected.forEach((deviceId) => { promises.push( updateDeviceRegistryEntry(this.hass, deviceId, { - labels: this.hass.devices[deviceId].labels.concat(label), + labels: + action === "add" + ? this.hass.devices[deviceId].labels.concat(label) + : this.hass.devices[deviceId].labels.filter( + (lbl) => lbl !== label + ), }) ); }); diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index b4ae8573b9..ef9289b099 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -134,7 +134,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { { value: string[] | undefined; items: Set | undefined } > = {}; - @state() private _selectedEntities: string[] = []; + @state() private _selected: string[] = []; @state() private _expandedFilter?: string; @@ -518,10 +518,26 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { const labelItems = html` ${this._labels?.map((label) => { const color = label.color ? computeCssColor(label.color) : undefined; + const selected = this._selected.every((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); + const partial = + !selected && + this._selected.some((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); return html` + ${label.icon ? html`` @@ -529,12 +545,13 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { ${label.name} `; - })} + })} +
${this.hass.localize("ui.panel.config.labels.add_label")} -
-
`; + `; return html` ): void { - this._selectedEntities = ev.detail.value; + this._selected = ev.detail.value; } private async _enableSelected() { showConfirmationDialog(this, { title: this.hass.localize( "ui.panel.config.entities.picker.enable_selected.confirm_title", - { number: this._selectedEntities.length } + { number: this._selected.length } ), text: this.hass.localize( "ui.panel.config.entities.picker.enable_selected.confirm_text" @@ -921,7 +938,7 @@ ${ let require_restart = false; let reload_delay = 0; await Promise.all( - this._selectedEntities.map(async (entity) => { + this._selected.map(async (entity) => { const result = await updateEntityRegistryEntry(this.hass, entity, { disabled_by: null, }); @@ -958,7 +975,7 @@ ${ showConfirmationDialog(this, { title: this.hass.localize( "ui.panel.config.entities.picker.disable_selected.confirm_title", - { number: this._selectedEntities.length } + { number: this._selected.length } ), text: this.hass.localize( "ui.panel.config.entities.picker.disable_selected.confirm_text" @@ -966,7 +983,7 @@ ${ confirmText: this.hass.localize("ui.common.disable"), dismissText: this.hass.localize("ui.common.cancel"), confirm: () => { - this._selectedEntities.forEach((entity) => + this._selected.forEach((entity) => updateEntityRegistryEntry(this.hass, entity, { disabled_by: "user", }) @@ -980,7 +997,7 @@ ${ showConfirmationDialog(this, { title: this.hass.localize( "ui.panel.config.entities.picker.hide_selected.confirm_title", - { number: this._selectedEntities.length } + { number: this._selected.length } ), text: this.hass.localize( "ui.panel.config.entities.picker.hide_selected.confirm_text" @@ -988,7 +1005,7 @@ ${ confirmText: this.hass.localize("ui.common.hide"), dismissText: this.hass.localize("ui.common.cancel"), confirm: () => { - this._selectedEntities.forEach((entity) => + this._selected.forEach((entity) => updateEntityRegistryEntry(this.hass, entity, { hidden_by: "user", }) @@ -999,7 +1016,7 @@ ${ } private _unhideSelected() { - this._selectedEntities.forEach((entity) => + this._selected.forEach((entity) => updateEntityRegistryEntry(this.hass, entity, { hidden_by: null, }) @@ -1009,11 +1026,17 @@ ${ private async _handleBulkLabel(ev) { const label = ev.currentTarget.value; + const action = ev.currentTarget.action; const promises: Promise[] = []; - this._selectedEntities.forEach((entityId) => { + this._selected.forEach((entityId) => { promises.push( updateEntityRegistryEntry(this.hass, entityId, { - labels: this.hass.entities[entityId].labels.concat(label), + labels: + action === "add" + ? this.hass.entities[entityId].labels.concat(label) + : this.hass.entities[entityId].labels.filter( + (lbl) => lbl !== label + ), }) ); }); @@ -1021,21 +1044,19 @@ ${ } private _removeSelected() { - const removeableEntities = this._selectedEntities.filter((entity) => { + const removeableEntities = this._selected.filter((entity) => { const stateObj = this.hass.states[entity]; return stateObj?.attributes.restored; }); showConfirmationDialog(this, { title: this.hass.localize( `ui.panel.config.entities.picker.remove_selected.confirm_${ - removeableEntities.length !== this._selectedEntities.length - ? "partly_" - : "" + removeableEntities.length !== this._selected.length ? "partly_" : "" }title`, { number: removeableEntities.length } ), text: - removeableEntities.length === this._selectedEntities.length + removeableEntities.length === this._selected.length ? this.hass.localize( "ui.panel.config.entities.picker.remove_selected.confirm_text" ) @@ -1043,7 +1064,7 @@ ${ "ui.panel.config.entities.picker.remove_selected.confirm_partly_text", { removable: removeableEntities.length, - selected: this._selectedEntities.length, + selected: this._selected.length, } ), confirmText: this.hass.localize("ui.common.remove"), diff --git a/src/panels/config/helpers/ha-config-helpers.ts b/src/panels/config/helpers/ha-config-helpers.ts index 809f03a23e..a63b0c2a01 100644 --- a/src/panels/config/helpers/ha-config-helpers.ts +++ b/src/panels/config/helpers/ha-config-helpers.ts @@ -456,6 +456,7 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) { .value=${label.label_id} .action=${selected ? "remove" : "add"} @click=${this._handleBulkLabel} + keep-open > `; const labelItems = html` ${this._labels?.map((label) => { const color = label.color ? computeCssColor(label.color) : undefined; + const selected = this._selected.every((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); + const partial = + !selected && + this._selected.some((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); return html` + ${label.icon ? html`` @@ -385,12 +401,13 @@ class HaSceneDashboard extends SubscribeMixin(LitElement) { ${label.name} `; - })} + })} +
${this.hass.localize("ui.panel.config.labels.add_label")} -
-
`; + `; return html` [] = []; this._selected.forEach((entityId) => { promises.push( updateEntityRegistryEntry(this.hass, entityId, { - labels: this.hass.entities[entityId].labels.concat(label), + labels: + action === "add" + ? this.hass.entities[entityId].labels.concat(label) + : this.hass.entities[entityId].labels.filter( + (lbl) => lbl !== label + ), }) ); }); diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts index c4be1b4e00..4d0242e934 100644 --- a/src/panels/config/script/ha-script-picker.ts +++ b/src/panels/config/script/ha-script-picker.ts @@ -384,12 +384,28 @@ class HaScriptPicker extends SubscribeMixin(LitElement) { ${this.hass.localize("ui.panel.config.category.editor.add")} `; - const labelItems = html` ${this._labels?.map((label) => { + const labelItems = html`${this._labels?.map((label) => { const color = label.color ? computeCssColor(label.color) : undefined; + const selected = this._selected.every((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); + const partial = + !selected && + this._selected.some((entityId) => + this.hass.entities[entityId]?.labels.includes(label.label_id) + ); return html` + ${label.icon ? html`` @@ -397,12 +413,13 @@ class HaScriptPicker extends SubscribeMixin(LitElement) { ${label.name} `; - })} + })} +
${this.hass.localize("ui.panel.config.labels.add_label")} -
-
`; + `; return html` [] = []; this._selected.forEach((entityId) => { promises.push( updateEntityRegistryEntry(this.hass, entityId, { - labels: this.hass.entities[entityId].labels.concat(label), + labels: + action === "add" + ? this.hass.entities[entityId].labels.concat(label) + : this.hass.entities[entityId].labels.filter( + (lbl) => lbl !== label + ), }) ); });