From d9f1b06199e29db460f00fa282ecedf84c37c578 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 26 Jun 2024 20:37:07 +0200 Subject: [PATCH 1/4] Fix undefined value in search (#21175) --- hassio/src/components/hassio-filter-addons.ts | 3 ++- src/common/string/strip-diacritics.ts | 2 +- .../add-automation-element-dialog.ts | 5 ++-- .../integrations/dialog-add-integration.ts | 3 ++- .../ha-config-integrations-dashboard.ts | 25 ++++++++++--------- .../editor/card-editor/hui-card-picker.ts | 3 ++- src/util/fuse.ts | 12 +++++++++ 7 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 src/util/fuse.ts diff --git a/hassio/src/components/hassio-filter-addons.ts b/hassio/src/components/hassio-filter-addons.ts index cb72ab3a52b8..1970aa54951f 100644 --- a/hassio/src/components/hassio-filter-addons.ts +++ b/hassio/src/components/hassio-filter-addons.ts @@ -2,6 +2,7 @@ import type { IFuseOptions } from "fuse.js"; import Fuse from "fuse.js"; import { stripDiacritics } from "../../../src/common/string/strip-diacritics"; import { StoreAddon } from "../../../src/data/supervisor/store"; +import { getStripDiacriticsFn } from "../../../src/util/fuse"; export function filterAndSort(addons: StoreAddon[], filter: string) { const options: IFuseOptions = { @@ -9,7 +10,7 @@ export function filterAndSort(addons: StoreAddon[], filter: string) { isCaseSensitive: false, minMatchCharLength: Math.min(filter.length, 2), threshold: 0.2, - getFn: (obj, path) => stripDiacritics(Fuse.config.getFn(obj, path)), + getFn: getStripDiacriticsFn, }; const fuse = new Fuse(addons, options); return fuse.search(stripDiacritics(filter)).map((result) => result.item); diff --git a/src/common/string/strip-diacritics.ts b/src/common/string/strip-diacritics.ts index a82ddf2c4521..6a704d86e385 100644 --- a/src/common/string/strip-diacritics.ts +++ b/src/common/string/strip-diacritics.ts @@ -1,2 +1,2 @@ -export const stripDiacritics = (str) => +export const stripDiacritics = (str: string) => str.normalize("NFD").replace(/[\u0300-\u036F]/g, ""); diff --git a/src/panels/config/automation/add-automation-element-dialog.ts b/src/panels/config/automation/add-automation-element-dialog.ts index 6f75232f52cd..a18822216b75 100644 --- a/src/panels/config/automation/add-automation-element-dialog.ts +++ b/src/panels/config/automation/add-automation-element-dialog.ts @@ -18,6 +18,7 @@ import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; import { computeDomain } from "../../../common/entity/compute_domain"; import { stringCompare } from "../../../common/string/compare"; +import { stripDiacritics } from "../../../common/string/strip-diacritics"; import { LocalizeFunc } from "../../../common/translations/localize"; import { deepEqual } from "../../../common/util/deep-equal"; import "../../../components/ha-dialog"; @@ -50,11 +51,11 @@ import { TRIGGER_GROUPS, TRIGGER_ICONS } from "../../../data/trigger"; import { HassDialog } from "../../../dialogs/make-dialog-manager"; import { haStyle, haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; +import { getStripDiacriticsFn } from "../../../util/fuse"; import { AddAutomationElementDialogParams, PASTE_VALUE, } from "./show-add-automation-element-dialog"; -import { stripDiacritics } from "../../../common/string/strip-diacritics"; const TYPES = { trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS }, @@ -209,7 +210,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog { isCaseSensitive: false, minMatchCharLength: Math.min(filter.length, 2), threshold: 0.2, - getFn: (obj, path) => stripDiacritics(Fuse.config.getFn(obj, path)), + getFn: getStripDiacriticsFn, }; const fuse = new Fuse(items, options); return fuse.search(stripDiacritics(filter)).map((result) => result.item); diff --git a/src/panels/config/integrations/dialog-add-integration.ts b/src/panels/config/integrations/dialog-add-integration.ts index 004ac0c6112d..e94008727d4e 100644 --- a/src/panels/config/integrations/dialog-add-integration.ts +++ b/src/panels/config/integrations/dialog-add-integration.ts @@ -56,6 +56,7 @@ import { } from "./show-add-integration-dialog"; import { getConfigEntries } from "../../../data/config_entries"; import { stripDiacritics } from "../../../common/string/strip-diacritics"; +import { getStripDiacriticsFn } from "../../../util/fuse"; export interface IntegrationListItem { name: string; @@ -256,7 +257,7 @@ class AddIntegrationDialog extends LitElement { isCaseSensitive: false, minMatchCharLength: Math.min(filter.length, 2), threshold: 0.2, - getFn: (obj, path) => stripDiacritics(Fuse.config.getFn(obj, path)), + getFn: getStripDiacriticsFn, }; const helpers = Object.entries(h).map(([domain, integration]) => ({ domain, diff --git a/src/panels/config/integrations/ha-config-integrations-dashboard.ts b/src/panels/config/integrations/ha-config-integrations-dashboard.ts index 48987048d8f3..8c1dacbf3e9c 100644 --- a/src/panels/config/integrations/ha-config-integrations-dashboard.ts +++ b/src/panels/config/integrations/ha-config-integrations-dashboard.ts @@ -1,25 +1,27 @@ import { ActionDetail } from "@material/mwc-list"; import { mdiFilterVariant, mdiPlus } from "@mdi/js"; -import Fuse from "fuse.js"; import type { IFuseOptions } from "fuse.js"; +import Fuse from "fuse.js"; import type { UnsubscribeFunc } from "home-assistant-js-websocket"; import { - css, CSSResultGroup, - html, LitElement, - nothing, PropertyValues, + css, + html, + nothing, } from "lit"; import { customElement, property, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import memoizeOne from "memoize-one"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { - protocolIntegrationPicked, PROTOCOL_INTEGRATIONS, + protocolIntegrationPicked, } from "../../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../../common/navigate"; +import { caseInsensitiveStringCompare } from "../../../common/string/compare"; +import { stripDiacritics } from "../../../common/string/strip-diacritics"; import { extractSearchParam } from "../../../common/url/search-params"; import { nextRender } from "../../../common/util/render-status"; import "../../../components/ha-button-menu"; @@ -29,6 +31,7 @@ import "../../../components/ha-fab"; import "../../../components/ha-icon-button"; import "../../../components/ha-svg-icon"; import "../../../components/search-input"; +import "../../../components/search-input-outlined"; import { ConfigEntry, getConfigEntries } from "../../../data/config_entries"; import { getConfigFlowInProgressCollection } from "../../../data/config_flow"; import { fetchDiagnosticHandlers } from "../../../data/diagnostics"; @@ -37,11 +40,11 @@ import { subscribeEntityRegistry, } from "../../../data/entity_registry"; import { + IntegrationLogInfo, + IntegrationManifest, domainToName, fetchIntegrationManifest, fetchIntegrationManifests, - IntegrationLogInfo, - IntegrationManifest, subscribeLogInfo, } from "../../../data/integration"; import { @@ -59,19 +62,17 @@ import "../../../layouts/hass-tabs-subpage"; import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, Route } from "../../../types"; +import { getStripDiacriticsFn } from "../../../util/fuse"; import { configSections } from "../ha-panel-config"; import { isHelperDomain } from "../helpers/const"; import "./ha-config-flow-card"; import { DataEntryFlowProgressExtended } from "./ha-config-integrations"; +import "./ha-disabled-config-entry-card"; import "./ha-ignored-config-entry-card"; import "./ha-integration-card"; import type { HaIntegrationCard } from "./ha-integration-card"; import "./ha-integration-overflow-menu"; import { showAddIntegrationDialog } from "./show-add-integration-dialog"; -import "./ha-disabled-config-entry-card"; -import { caseInsensitiveStringCompare } from "../../../common/string/compare"; -import "../../../components/search-input-outlined"; -import { stripDiacritics } from "../../../common/string/strip-diacritics"; export interface ConfigEntryExtended extends ConfigEntry { localized_domain_name?: string; @@ -209,7 +210,7 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) { isCaseSensitive: false, minMatchCharLength: Math.min(filter.length, 2), threshold: 0.2, - getFn: (obj, path) => stripDiacritics(Fuse.config.getFn(obj, path)), + getFn: getStripDiacriticsFn, }; const fuse = new Fuse(configEntriesInProgress, options); filteredEntries = fuse diff --git a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts index 65d8d94bdd2d..3537955479a5 100644 --- a/src/panels/lovelace/editor/card-editor/hui-card-picker.ts +++ b/src/panels/lovelace/editor/card-editor/hui-card-picker.ts @@ -29,6 +29,7 @@ import { getCustomCardEntry, } from "../../../../data/lovelace_custom_cards"; import type { HomeAssistant } from "../../../../types"; +import { getStripDiacriticsFn } from "../../../../util/fuse"; import { calcUnusedEntities, computeUsedEntities, @@ -87,7 +88,7 @@ export class HuiCardPicker extends LitElement { isCaseSensitive: false, minMatchCharLength: Math.min(filter.length, 2), threshold: 0.2, - getFn: (obj, path) => stripDiacritics(Fuse.config.getFn(obj, path)), + getFn: getStripDiacriticsFn, }; const fuse = new Fuse(cards, options); cards = fuse.search(stripDiacritics(filter)).map((result) => result.item); diff --git a/src/util/fuse.ts b/src/util/fuse.ts new file mode 100644 index 000000000000..56157d700182 --- /dev/null +++ b/src/util/fuse.ts @@ -0,0 +1,12 @@ +import Fuse from "fuse.js"; +import { stripDiacritics } from "../common/string/strip-diacritics"; + +type GetFn = typeof Fuse.config.getFn; + +export const getStripDiacriticsFn: GetFn = (obj, path) => { + const value = Fuse.config.getFn(obj, path); + if (Array.isArray(value)) { + return value.map((v) => stripDiacritics(v ?? "")); + } + return stripDiacritics((value as string | undefined) ?? ""); +}; From b08b67179e7d524e49726b74a394bb9c1da3426e Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 26 Jun 2024 23:05:47 +0200 Subject: [PATCH 2/4] Fix hass object in nested hui-card (#21178) --- src/panels/lovelace/cards/hui-card.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/panels/lovelace/cards/hui-card.ts b/src/panels/lovelace/cards/hui-card.ts index e8091f2b871f..a892d4764dcf 100644 --- a/src/panels/lovelace/cards/hui-card.ts +++ b/src/panels/lovelace/cards/hui-card.ts @@ -105,6 +105,8 @@ export class HuiCard extends ReactiveElement { "ll-upgrade", (ev: Event) => { ev.stopPropagation(); + element.hass = this.hass; + element.preview = this.preview; fireEvent(this, "card-updated"); }, { once: true } From 231c923776a12b98d165a183a1faebe8d805cc53 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 26 Jun 2024 23:08:56 +0200 Subject: [PATCH 3/4] Bumped version to 20240626.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e2c30d045b4f..2a2ab98c3203 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240626.0" +version = "20240626.1" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From ccad1afcf0766d9109342ebc252135783455e54b Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 26 Jun 2024 23:18:57 +0200 Subject: [PATCH 4/4] Bumped version to 20240626.2 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2a2ab98c3203..28a3be951139 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20240626.1" +version = "20240626.2" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md"