mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 19:26:36 +00:00
Allow entities table to delete helpers (#22248)
* Allow deleting helpers in entities table * Fix calling the right delete on restored legacy helpers
This commit is contained in:
parent
db03e271f5
commit
28703b39da
91
src/common/entity/delete_entity.ts
Normal file
91
src/common/entity/delete_entity.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import type { IntegrationManifest } from "../../data/integration";
|
||||
import { computeDomain } from "./compute_domain";
|
||||
import { HELPERS_CRUD } from "../../data/helpers_crud";
|
||||
import type { Helper } from "../../panels/config/helpers/const";
|
||||
import { isHelperDomain } from "../../panels/config/helpers/const";
|
||||
import { isComponentLoaded } from "../config/is_component_loaded";
|
||||
import type { EntityRegistryEntry } from "../../data/entity_registry";
|
||||
import { removeEntityRegistryEntry } from "../../data/entity_registry";
|
||||
import type { ConfigEntry } from "../../data/config_entries";
|
||||
import { deleteConfigEntry } from "../../data/config_entries";
|
||||
|
||||
export const isDeletableEntity = (
|
||||
hass: HomeAssistant,
|
||||
entity_id: string,
|
||||
manifests: IntegrationManifest[],
|
||||
entityRegistry: EntityRegistryEntry[],
|
||||
configEntries: ConfigEntry[],
|
||||
fetchedHelpers: Helper[]
|
||||
): boolean => {
|
||||
const restored = !!hass.states[entity_id]?.attributes.restored;
|
||||
if (restored) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const domain = computeDomain(entity_id);
|
||||
const entityRegEntry = entityRegistry.find((e) => e.entity_id === entity_id);
|
||||
if (isHelperDomain(domain)) {
|
||||
return !!(
|
||||
isComponentLoaded(hass, domain) &&
|
||||
entityRegEntry &&
|
||||
fetchedHelpers.some((e) => e.id === entityRegEntry.unique_id)
|
||||
);
|
||||
}
|
||||
|
||||
const configEntryId = entityRegEntry?.config_entry_id;
|
||||
if (!configEntryId) {
|
||||
return false;
|
||||
}
|
||||
const configEntry = configEntries.find((e) => e.entry_id === configEntryId);
|
||||
return (
|
||||
manifests.find((m) => m.domain === configEntry?.domain)
|
||||
?.integration_type === "helper"
|
||||
);
|
||||
};
|
||||
|
||||
export const deleteEntity = (
|
||||
hass: HomeAssistant,
|
||||
entity_id: string,
|
||||
manifests: IntegrationManifest[],
|
||||
entityRegistry: EntityRegistryEntry[],
|
||||
configEntries: ConfigEntry[],
|
||||
fetchedHelpers: Helper[]
|
||||
) => {
|
||||
// This function assumes the entity_id already was validated by isDeletableEntity and does not repeat all those checks.
|
||||
const domain = computeDomain(entity_id);
|
||||
const entityRegEntry = entityRegistry.find((e) => e.entity_id === entity_id);
|
||||
if (isHelperDomain(domain)) {
|
||||
if (isComponentLoaded(hass, domain)) {
|
||||
if (
|
||||
entityRegEntry &&
|
||||
fetchedHelpers.some((e) => e.id === entityRegEntry.unique_id)
|
||||
) {
|
||||
HELPERS_CRUD[domain].delete(hass, entityRegEntry.unique_id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const stateObj = hass.states[entity_id];
|
||||
if (!stateObj?.attributes.restored) {
|
||||
return;
|
||||
}
|
||||
removeEntityRegistryEntry(hass, entity_id);
|
||||
return;
|
||||
}
|
||||
|
||||
const configEntryId = entityRegEntry?.config_entry_id;
|
||||
const configEntry = configEntryId
|
||||
? configEntries.find((e) => e.entry_id === configEntryId)
|
||||
: undefined;
|
||||
const isHelperEntryType = configEntry
|
||||
? manifests.find((m) => m.domain === configEntry.domain)
|
||||
?.integration_type === "helper"
|
||||
: false;
|
||||
|
||||
if (isHelperEntryType) {
|
||||
deleteConfigEntry(hass, configEntryId!);
|
||||
return;
|
||||
}
|
||||
|
||||
removeEntityRegistryEntry(hass, entity_id);
|
||||
};
|
@ -27,6 +27,13 @@ import { formatShortDateTime } from "../../../common/datetime/format_date_time";
|
||||
import { storage } from "../../../common/decorators/storage";
|
||||
import type { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import {
|
||||
isDeletableEntity,
|
||||
deleteEntity,
|
||||
} from "../../../common/entity/delete_entity";
|
||||
import type { Helper } from "../helpers/const";
|
||||
import { isHelperDomain } from "../helpers/const";
|
||||
import { HELPERS_CRUD } from "../../../data/helpers_crud";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import {
|
||||
PROTOCOL_INTEGRATIONS,
|
||||
@ -73,12 +80,15 @@ import type {
|
||||
} from "../../../data/entity_registry";
|
||||
import {
|
||||
computeEntityRegistryName,
|
||||
removeEntityRegistryEntry,
|
||||
updateEntityRegistryEntry,
|
||||
} from "../../../data/entity_registry";
|
||||
import type { IntegrationManifest } from "../../../data/integration";
|
||||
import {
|
||||
fetchIntegrationManifests,
|
||||
domainToName,
|
||||
} from "../../../data/integration";
|
||||
import type { EntitySources } from "../../../data/entity_sources";
|
||||
import { fetchEntitySourcesWithCache } from "../../../data/entity_sources";
|
||||
import { domainToName } from "../../../data/integration";
|
||||
import type { LabelRegistryEntry } from "../../../data/label_registry";
|
||||
import {
|
||||
createLabelRegistryEntry,
|
||||
@ -136,6 +146,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
|
||||
@state() private _entries?: ConfigEntry[];
|
||||
|
||||
@state() private _manifests?: IntegrationManifest[];
|
||||
|
||||
@state()
|
||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||
_entities!: EntityRegistryEntry[];
|
||||
@ -1280,11 +1292,46 @@ ${rejected
|
||||
});
|
||||
}
|
||||
|
||||
private _removeSelected() {
|
||||
const removeableEntities = this._selected.filter((entity) => {
|
||||
const stateObj = this.hass.states[entity];
|
||||
return stateObj?.attributes.restored;
|
||||
private async _removeSelected() {
|
||||
if (!this._entities || !this.hass) {
|
||||
return;
|
||||
}
|
||||
|
||||
const manifestsProm = this._manifests
|
||||
? undefined
|
||||
: fetchIntegrationManifests(this.hass);
|
||||
const helperDomains = [
|
||||
...new Set(this._selected.map((s) => computeDomain(s))),
|
||||
].filter((d) => isHelperDomain(d));
|
||||
|
||||
const configEntriesProm = this._entries
|
||||
? undefined
|
||||
: this._loadConfigEntries();
|
||||
const domainProms = helperDomains.map((d) =>
|
||||
HELPERS_CRUD[d].fetch(this.hass)
|
||||
);
|
||||
const helpersResult = await Promise.all(domainProms);
|
||||
let fetchedHelpers: Helper[] = [];
|
||||
helpersResult.forEach((r) => {
|
||||
fetchedHelpers = fetchedHelpers.concat(r);
|
||||
});
|
||||
if (manifestsProm) {
|
||||
this._manifests = await manifestsProm;
|
||||
}
|
||||
if (configEntriesProm) {
|
||||
await configEntriesProm;
|
||||
}
|
||||
|
||||
const removeableEntities = this._selected.filter((entity_id) =>
|
||||
isDeletableEntity(
|
||||
this.hass,
|
||||
entity_id,
|
||||
this._manifests!,
|
||||
this._entities,
|
||||
this._entries!,
|
||||
fetchedHelpers
|
||||
)
|
||||
);
|
||||
showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
`ui.panel.config.entities.picker.delete_selected.confirm_title`
|
||||
@ -1305,8 +1352,15 @@ ${rejected
|
||||
dismissText: this.hass.localize("ui.common.cancel"),
|
||||
destructive: true,
|
||||
confirm: () => {
|
||||
removeableEntities.forEach((entity) =>
|
||||
removeEntityRegistryEntry(this.hass, entity)
|
||||
removeableEntities.forEach((entity_id) =>
|
||||
deleteEntity(
|
||||
this.hass,
|
||||
entity_id,
|
||||
this._manifests!,
|
||||
this._entities,
|
||||
this._entries!,
|
||||
fetchedHelpers
|
||||
)
|
||||
);
|
||||
this._clearSelection();
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user