Reorder config entries in device pages (#17105)

This commit is contained in:
Paul Bottein 2023-06-30 17:15:49 +02:00 committed by GitHub
parent d6f8941098
commit 23ac7501b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 173 additions and 102 deletions

View File

@ -1,6 +1,6 @@
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { HomeAssistant } from "../types";
import { IntegrationType } from "./integration";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import type { HomeAssistant } from "../types";
import type { IntegrationManifest, IntegrationType } from "./integration";
export interface ConfigEntry {
entry_id: string;
@ -143,3 +143,23 @@ export const enableConfigEntry = (hass: HomeAssistant, configEntryId: string) =>
entry_id: configEntryId,
disabled_by: null,
});
export const sortConfigEntries = (
configEntries: ConfigEntry[],
manifestLookup: { [domain: string]: IntegrationManifest }
): ConfigEntry[] => {
const sortedConfigEntries = [...configEntries];
const getScore = (entry: ConfigEntry) => {
const manifest = manifestLookup[entry.domain] as
| IntegrationManifest
| undefined;
const isHelper = manifest?.integration_type === "helper";
return isHelper ? -1 : 1;
};
const configEntriesCompare = (a: ConfigEntry, b: ConfigEntry) =>
getScore(b) - getScore(a);
return sortedConfigEntries.sort(configEntriesCompare);
};

View File

@ -41,6 +41,7 @@ import {
ConfigEntry,
disableConfigEntry,
DisableConfigEntryResult,
sortConfigEntries,
} from "../../../data/config_entries";
import {
computeDeviceName,
@ -60,7 +61,7 @@ import {
findBatteryEntity,
updateEntityRegistryEntry,
} from "../../../data/entity_registry";
import { domainToName } from "../../../data/integration";
import { IntegrationManifest, domainToName } from "../../../data/integration";
import { SceneEntities, showSceneEditor } from "../../../data/scene";
import { findRelated, RelatedResult } from "../../../data/search";
import {
@ -115,6 +116,8 @@ export class HaConfigDevicePage extends LitElement {
@property({ attribute: false }) public areas!: AreaRegistryEntry[];
@property({ attribute: false }) public manifests!: IntegrationManifest[];
@property() public deviceId!: string;
@property({ type: Boolean, reflect: true }) public narrow!: boolean;
@ -145,14 +148,24 @@ export class HaConfigDevicePage extends LitElement {
);
private _integrations = memoizeOne(
(device: DeviceRegistryEntry, entries: ConfigEntry[]): ConfigEntry[] => {
(
device: DeviceRegistryEntry,
entries: ConfigEntry[],
manifests: IntegrationManifest[]
): ConfigEntry[] => {
const entryLookup: { [entryId: string]: ConfigEntry } = {};
for (const entry of entries) {
entryLookup[entry.entry_id] = entry;
}
return device.config_entries
.map((entry) => entryLookup[entry])
.filter(Boolean);
const manifestLookup: { [domain: string]: IntegrationManifest } = {};
for (const manifest of manifests) {
manifestLookup[manifest.domain] = manifest;
}
const deviceEntries = device.config_entries
.filter((entId) => entId in entryLookup)
.map((entry) => entryLookup[entry]);
return sortConfigEntries(deviceEntries, manifestLookup);
}
);
@ -292,7 +305,11 @@ export class HaConfigDevicePage extends LitElement {
}
const deviceName = computeDeviceName(device, this.hass);
const integrations = this._integrations(device, this.entries);
const integrations = this._integrations(
device,
this.entries,
this.manifests
);
const entities = this._entities(this.deviceId, this.entities);
const entitiesByCategory = this._entitiesByCategory(entities);
const batteryEntity = this._batteryEntity(entities);
@ -920,7 +937,7 @@ export class HaConfigDevicePage extends LitElement {
}
let links = await Promise.all(
this._integrations(device, this.entries).map(
this._integrations(device, this.entries, this.manifests).map(
async (entry): Promise<boolean | { link: string; domain: string }> => {
if (entry.state !== "loaded") {
return false;
@ -983,7 +1000,8 @@ export class HaConfigDevicePage extends LitElement {
}
const buttons: DeviceAction[] = [];
this._integrations(device, this.entries).forEach((entry) => {
this._integrations(device, this.entries, this.manifests).forEach(
(entry) => {
if (entry.state !== "loaded" || !entry.supports_remove_device) {
return;
}
@ -991,7 +1009,8 @@ export class HaConfigDevicePage extends LitElement {
action: async () => {
const confirmed = await showConfirmationDialog(this, {
text:
this._integrations(device, this.entries).length > 1
this._integrations(device, this.entries, this.manifests)
.length > 1
? this.hass.localize(
`ui.panel.config.devices.confirm_delete_integration`,
{
@ -1001,7 +1020,9 @@ export class HaConfigDevicePage extends LitElement {
),
}
)
: this.hass.localize(`ui.panel.config.devices.confirm_delete`),
: this.hass.localize(
`ui.panel.config.devices.confirm_delete`
),
});
if (!confirmed) {
@ -1017,7 +1038,7 @@ export class HaConfigDevicePage extends LitElement {
classes: "warning",
icon: mdiDelete,
label:
this._integrations(device, this.entries).length > 1
this._integrations(device, this.entries, this.manifests).length > 1
? this.hass.localize(
`ui.panel.config.devices.delete_device_integration`,
{
@ -1026,7 +1047,8 @@ export class HaConfigDevicePage extends LitElement {
)
: this.hass.localize(`ui.panel.config.devices.delete_device`),
});
});
}
);
if (buttons.length > 0) {
this._deleteButtons = buttons;
@ -1061,9 +1083,11 @@ export class HaConfigDevicePage extends LitElement {
});
}
const domains = this._integrations(device, this.entries).map(
(int) => int.domain
);
const domains = this._integrations(
device,
this.entries,
this.manifests
).map((int) => int.domain);
if (domains.includes("mqtt")) {
const mqtt = await import(
@ -1103,9 +1127,11 @@ export class HaConfigDevicePage extends LitElement {
const deviceAlerts: DeviceAlert[] = [];
const domains = this._integrations(device, this.entries).map(
(int) => int.domain
);
const domains = this._integrations(
device,
this.entries,
this.manifests
).map((int) => int.domain);
if (domains.includes("zwave_js")) {
const zwave = await import(

View File

@ -25,7 +25,7 @@ import "../../../components/ha-check-list-item";
import "../../../components/ha-fab";
import "../../../components/ha-icon-button";
import { AreaRegistryEntry } from "../../../data/area_registry";
import { ConfigEntry } from "../../../data/config_entries";
import { ConfigEntry, sortConfigEntries } from "../../../data/config_entries";
import {
computeDeviceName,
DeviceEntityLookup,
@ -36,7 +36,7 @@ import {
findBatteryChargingEntity,
findBatteryEntity,
} from "../../../data/entity_registry";
import { domainToName } from "../../../data/integration";
import { IntegrationManifest, domainToName } from "../../../data/integration";
import "../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant, Route } from "../../../types";
@ -68,6 +68,8 @@ export class HaConfigDeviceDashboard extends LitElement {
@property() public areas!: AreaRegistryEntry[];
@property() public manifests!: IntegrationManifest[];
@property() public route!: Route;
@state() private _searchParms = new URLSearchParams(window.location.search);
@ -149,6 +151,7 @@ export class HaConfigDeviceDashboard extends LitElement {
entries: ConfigEntry[],
entities: EntityRegistryEntry[],
areas: AreaRegistryEntry[],
manifests: IntegrationManifest[],
filters: URLSearchParams,
showDisabled: boolean,
localize: LocalizeFunc
@ -186,6 +189,11 @@ export class HaConfigDeviceDashboard extends LitElement {
areaLookup[area.area_id] = area;
}
const manifestLookup: { [domain: string]: IntegrationManifest } = {};
for (const manifest of manifests) {
manifestLookup[manifest.domain] = manifest;
}
let filterConfigEntry: ConfigEntry | undefined;
const filteredDomains = new Set<string>();
@ -217,7 +225,14 @@ export class HaConfigDeviceDashboard extends LitElement {
outputDevices = outputDevices.filter((device) => !device.disabled_by);
}
outputDevices = outputDevices.map((device) => ({
outputDevices = outputDevices.map((device) => {
const deviceEntries = sortConfigEntries(
device.config_entries
.filter((entId) => entId in entryLookup)
.map((entId) => entryLookup[entId]),
manifestLookup
);
return {
...device,
name: computeDeviceName(
device,
@ -234,21 +249,17 @@ export class HaConfigDeviceDashboard extends LitElement {
device.area_id && areaLookup[device.area_id]
? areaLookup[device.area_id].name
: "—",
integration: device.config_entries.length
? device.config_entries
.filter((entId) => entId in entryLookup)
integration: deviceEntries.length
? deviceEntries
.map(
(entId) =>
localize(`component.${entryLookup[entId].domain}.title`) ||
entryLookup[entId].domain
(entry) =>
localize(`component.${entry.domain}.title`) || entry.domain
)
.join(", ")
: this.hass.localize(
"ui.panel.config.devices.data_table.no_integration"
),
domains: device.config_entries
.filter((entId) => entId in entryLookup)
.map((entId) => entryLookup[entId].domain),
domains: deviceEntries.map((entry) => entry.domain),
battery_entity: [
this._batteryEntity(device.id, deviceEntityLookup),
this._batteryChargingEntity(device.id, deviceEntityLookup),
@ -257,7 +268,8 @@ export class HaConfigDeviceDashboard extends LitElement {
this.hass.states[
this._batteryEntity(device.id, deviceEntityLookup) || ""
]?.state,
}));
};
});
this._numHiddenDevices = startLength - outputDevices.length;
return {
@ -429,6 +441,7 @@ export class HaConfigDeviceDashboard extends LitElement {
this.entries,
this.entities,
this.areas,
this.manifests,
this._searchParms,
this._showDisabled,
this.hass.localize
@ -565,6 +578,7 @@ export class HaConfigDeviceDashboard extends LitElement {
this.entries,
this.entities,
this.areas,
this.manifests,
this._searchParms,
this._showDisabled,
this.hass.localize

View File

@ -14,6 +14,10 @@ import {
EntityRegistryEntry,
subscribeEntityRegistry,
} from "../../../data/entity_registry";
import {
IntegrationManifest,
fetchIntegrationManifests,
} from "../../../data/integration";
import {
HassRouterPage,
RouterOptions,
@ -47,6 +51,8 @@ class HaConfigDevices extends HassRouterPage {
@state() private _configEntries: ConfigEntry[] = [];
@state() private _manifests: IntegrationManifest[] = [];
@state()
private _entityRegistryEntries: EntityRegistryEntry[] = [];
@ -99,6 +105,7 @@ class HaConfigDevices extends HassRouterPage {
pageEl.entities = this._entityRegistryEntries;
pageEl.entries = this._configEntries;
pageEl.manifests = this._manifests;
pageEl.devices = this._deviceRegistryEntries;
pageEl.areas = this._areas;
pageEl.narrow = this.narrow;
@ -111,6 +118,10 @@ class HaConfigDevices extends HassRouterPage {
getConfigEntries(this.hass).then((configEntries) => {
this._configEntries = configEntries;
});
fetchIntegrationManifests(this.hass).then((manifests) => {
this._manifests = manifests;
});
if (this._unsubs) {
return;
}