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 { storage } from "../../../common/decorators/storage";
|
||||||
import type { HASSDomEvent } from "../../../common/dom/fire_event";
|
import type { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
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 { computeStateName } from "../../../common/entity/compute_state_name";
|
||||||
import {
|
import {
|
||||||
PROTOCOL_INTEGRATIONS,
|
PROTOCOL_INTEGRATIONS,
|
||||||
@ -73,12 +80,15 @@ import type {
|
|||||||
} from "../../../data/entity_registry";
|
} from "../../../data/entity_registry";
|
||||||
import {
|
import {
|
||||||
computeEntityRegistryName,
|
computeEntityRegistryName,
|
||||||
removeEntityRegistryEntry,
|
|
||||||
updateEntityRegistryEntry,
|
updateEntityRegistryEntry,
|
||||||
} from "../../../data/entity_registry";
|
} from "../../../data/entity_registry";
|
||||||
|
import type { IntegrationManifest } from "../../../data/integration";
|
||||||
|
import {
|
||||||
|
fetchIntegrationManifests,
|
||||||
|
domainToName,
|
||||||
|
} from "../../../data/integration";
|
||||||
import type { EntitySources } from "../../../data/entity_sources";
|
import type { EntitySources } from "../../../data/entity_sources";
|
||||||
import { fetchEntitySourcesWithCache } from "../../../data/entity_sources";
|
import { fetchEntitySourcesWithCache } from "../../../data/entity_sources";
|
||||||
import { domainToName } from "../../../data/integration";
|
|
||||||
import type { LabelRegistryEntry } from "../../../data/label_registry";
|
import type { LabelRegistryEntry } from "../../../data/label_registry";
|
||||||
import {
|
import {
|
||||||
createLabelRegistryEntry,
|
createLabelRegistryEntry,
|
||||||
@ -136,6 +146,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
@state() private _entries?: ConfigEntry[];
|
@state() private _entries?: ConfigEntry[];
|
||||||
|
|
||||||
|
@state() private _manifests?: IntegrationManifest[];
|
||||||
|
|
||||||
@state()
|
@state()
|
||||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||||
_entities!: EntityRegistryEntry[];
|
_entities!: EntityRegistryEntry[];
|
||||||
@ -1280,11 +1292,46 @@ ${rejected
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _removeSelected() {
|
private async _removeSelected() {
|
||||||
const removeableEntities = this._selected.filter((entity) => {
|
if (!this._entities || !this.hass) {
|
||||||
const stateObj = this.hass.states[entity];
|
return;
|
||||||
return stateObj?.attributes.restored;
|
}
|
||||||
|
|
||||||
|
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, {
|
showConfirmationDialog(this, {
|
||||||
title: this.hass.localize(
|
title: this.hass.localize(
|
||||||
`ui.panel.config.entities.picker.delete_selected.confirm_title`
|
`ui.panel.config.entities.picker.delete_selected.confirm_title`
|
||||||
@ -1305,8 +1352,15 @@ ${rejected
|
|||||||
dismissText: this.hass.localize("ui.common.cancel"),
|
dismissText: this.hass.localize("ui.common.cancel"),
|
||||||
destructive: true,
|
destructive: true,
|
||||||
confirm: () => {
|
confirm: () => {
|
||||||
removeableEntities.forEach((entity) =>
|
removeableEntities.forEach((entity_id) =>
|
||||||
removeEntityRegistryEntry(this.hass, entity)
|
deleteEntity(
|
||||||
|
this.hass,
|
||||||
|
entity_id,
|
||||||
|
this._manifests!,
|
||||||
|
this._entities,
|
||||||
|
this._entries!,
|
||||||
|
fetchedHelpers
|
||||||
|
)
|
||||||
);
|
);
|
||||||
this._clearSelection();
|
this._clearSelection();
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user