${this.hass.localize(
@@ -1082,6 +1089,10 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
private async _handleBulkCategory(ev) {
const category = ev.currentTarget.value;
+ this._bulkAddCategory(category);
+ }
+
+ private async _bulkAddCategory(category: string) {
const promises: Promise
[] = [];
this._selected.forEach((entityId) => {
promises.push(
@@ -1096,6 +1107,10 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
private async _handleBulkLabel(ev) {
const label = ev.currentTarget.value;
const action = ev.currentTarget.action;
+ this._bulkLabel(label, action);
+ }
+
+ private async _bulkLabel(label: string, action: "add" | "remove") {
const promises: Promise[] = [];
this._selected.forEach((entityId) => {
promises.push(
@@ -1128,17 +1143,28 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
await Promise.all(promises);
}
- private _createCategory() {
+ private async _bulkCreateCategory() {
showCategoryRegistryDetailDialog(this, {
scope: "automation",
- createEntry: (values) =>
- createCategoryRegistryEntry(this.hass, "automation", values),
+ createEntry: async (values) => {
+ const category = await createCategoryRegistryEntry(
+ this.hass,
+ "automation",
+ values
+ );
+ this._bulkAddCategory(category.category_id);
+ return category;
+ },
});
}
- private _createLabel() {
+ private _bulkCreateLabel() {
showLabelDetailDialog(this, {
- createEntry: (values) => createLabelRegistryEntry(this.hass, values),
+ createEntry: async (values) => {
+ const label = await createLabelRegistryEntry(this.hass, values);
+ this._bulkLabel(label.label_id, "add");
+ return label;
+ },
});
}
@@ -1146,6 +1172,9 @@ class HaAutomationPicker extends SubscribeMixin(LitElement) {
return [
haStyle,
css`
+ :host {
+ display: block;
+ }
hass-tabs-subpage-data-table {
--data-table-row-height: 60px;
}
diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts
index ba9630e2fa7e..f9f2fd16e6e6 100644
--- a/src/panels/config/devices/ha-config-devices-dashboard.ts
+++ b/src/panels/config/devices/ha-config-devices-dashboard.ts
@@ -575,7 +575,7 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
`;
})}
-
+
${this.hass.localize("ui.panel.config.labels.add_label")}
[] = [];
this._selected.forEach((deviceId) => {
promises.push(
@@ -817,9 +821,13 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
await Promise.all(promises);
}
- private _createLabel() {
+ private _bulkCreateLabel() {
showLabelDetailDialog(this, {
- createEntry: (values) => createLabelRegistryEntry(this.hass, values),
+ createEntry: async (values) => {
+ const label = await createLabelRegistryEntry(this.hass, values);
+ this._bulkLabel(label.label_id, "add");
+ return label;
+ },
});
}
diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts
index 910448ac3a4a..5a7f5461aa06 100644
--- a/src/panels/config/entities/ha-config-entities.ts
+++ b/src/panels/config/entities/ha-config-entities.ts
@@ -88,6 +88,10 @@ import { configSections } from "../ha-panel-config";
import "../integrations/ha-integration-overflow-menu";
import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
+import {
+ EntitySources,
+ fetchEntitySourcesWithCache,
+} from "../../../data/entity_sources";
export interface StateEntity
extends Omit {
@@ -141,6 +145,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
@state()
_labels!: LabelRegistryEntry[];
+ @state() private _entitySources?: EntitySources;
+
@query("hass-tabs-subpage-data-table", true)
private _dataTable!: HaTabsSubpageDataTable;
@@ -405,10 +411,12 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
const entryIds = entries
.filter((entry) => filter.value!.includes(entry.domain))
.map((entry) => entry.entry_id);
+
filteredEntities = filteredEntities.filter(
(entity) =>
- entity.config_entry_id &&
- entryIds.includes(entity.config_entry_id)
+ filter.value?.includes(entity.platform) ||
+ (entity.config_entry_id &&
+ entryIds.includes(entity.config_entry_id))
);
filter.value!.forEach((domain) => filteredDomains.add(domain));
} else if (key === "ha-filter-labels" && filter.value?.length) {
@@ -547,7 +555,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
`;
})}
-
+
${this.hass.localize("ui.panel.config.labels.add_label")}
{
+ this._entitySources = sources;
+ });
}
private _setFiltersFromUrl() {
@@ -865,14 +876,18 @@ ${
this._filters = {};
}
- public willUpdate(changedProps: PropertyValues): void {
+ public willUpdate(changedProps: PropertyValues): void {
super.willUpdate(changedProps);
const oldHass = changedProps.get("hass");
let changed = false;
if (!this.hass || !this._entities) {
return;
}
- if (changedProps.has("hass") || changedProps.has("_entities")) {
+ if (
+ changedProps.has("hass") ||
+ changedProps.has("_entities") ||
+ changedProps.has("_entitySources")
+ ) {
const stateEntities: StateEntity[] = [];
const regEntityIds = new Set(
this._entities.map((entity) => entity.entity_id)
@@ -883,6 +898,7 @@ ${
}
if (
!oldHass ||
+ changedProps.has("_entitySources") ||
this.hass.states[entityId] !== oldHass.states[entityId]
) {
changed = true;
@@ -890,7 +906,8 @@ ${
stateEntities.push({
name: computeStateName(this.hass.states[entityId]),
entity_id: entityId,
- platform: computeDomain(entityId),
+ platform:
+ this._entitySources?.[entityId]?.domain || computeDomain(entityId),
disabled_by: null,
hidden_by: null,
area_id: null,
@@ -1027,6 +1044,10 @@ ${
private async _handleBulkLabel(ev) {
const label = ev.currentTarget.value;
const action = ev.currentTarget.action;
+ await this._bulkLabel(label, action);
+ }
+
+ private async _bulkLabel(label: string, action: "add" | "remove") {
const promises: Promise[] = [];
this._selected.forEach((entityId) => {
const entityReg =
@@ -1047,6 +1068,16 @@ ${
await Promise.all(promises);
}
+ private _bulkCreateLabel() {
+ showLabelDetailDialog(this, {
+ createEntry: async (values) => {
+ const label = await createLabelRegistryEntry(this.hass, values);
+ this._bulkLabel(label.label_id, "add");
+ return label;
+ },
+ });
+ }
+
private _removeSelected() {
const removeableEntities = this._selected.filter((entity) => {
const stateObj = this.hass.states[entity];
@@ -1123,12 +1154,6 @@ ${
});
}
- private _createLabel() {
- showLabelDetailDialog(this, {
- createEntry: (values) => createLabelRegistryEntry(this.hass, values),
- });
- }
-
static get styles(): CSSResultGroup {
return [
haStyle,
diff --git a/src/panels/config/helpers/ha-config-helpers.ts b/src/panels/config/helpers/ha-config-helpers.ts
index a63b0c2a01e2..b32fa2075034 100644
--- a/src/panels/config/helpers/ha-config-helpers.ts
+++ b/src/panels/config/helpers/ha-config-helpers.ts
@@ -1,4 +1,5 @@
import { consume } from "@lit-labs/context";
+import { ResizeController } from "@lit-labs/observers/resize-controller";
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
import {
mdiAlertCircle,
@@ -83,12 +84,12 @@ import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant, Route } from "../../../types";
import { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
+import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
import { configSections } from "../ha-panel-config";
import "../integrations/ha-integration-overflow-menu";
+import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
import { isHelperDomain } from "./const";
import { showHelperDetailDialog } from "./show-dialog-helper-detail";
-import { showCategoryRegistryDetailDialog } from "../category/show-dialog-category-registry-detail";
-import { showLabelDetailDialog } from "../labels/show-dialog-label-detail";
type HelperItem = {
id: string;
@@ -163,6 +164,10 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
@state() private _filteredStateItems?: string[] | null;
+ private _sizeController = new ResizeController(this, {
+ callback: (entries) => entries[0]?.contentRect.width,
+ });
+
public hassSubscribe() {
return [
subscribeConfigEntries(
@@ -375,6 +380,7 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
type: configEntry.domain,
configEntry,
entity: undefined,
+ selectable: false,
}));
return [...states, ...entries]
@@ -437,7 +443,7 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {