From 63f60019d1faa5c999068a51e3bf385449ed04e2 Mon Sep 17 00:00:00 2001 From: Donnie Date: Tue, 13 Oct 2020 15:26:12 -0700 Subject: [PATCH] Add friendly name to quick bar list and filter (#7306) Co-authored-by: Bram Kragten --- src/common/string/sequence_matching.ts | 13 +++- src/dialogs/quick-bar/ha-quick-bar.ts | 63 ++++++++++++------- .../common/string/sequence_matching.test.ts | 19 ++++-- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/common/string/sequence_matching.ts b/src/common/string/sequence_matching.ts index 3898ec667f..402b35baee 100644 --- a/src/common/string/sequence_matching.ts +++ b/src/common/string/sequence_matching.ts @@ -7,7 +7,16 @@ * * return true if word contains sequence. Otherwise false. */ -export const fuzzySequentialMatch = (filter: string, word: string) => { +export const fuzzySequentialMatch = (filter: string, words: string[]) => { + for (const word of words) { + if (_fuzzySequentialMatch(filter, word)) { + return true; + } + } + return false; +}; + +const _fuzzySequentialMatch = (filter: string, word: string) => { if (filter === "") { return true; } @@ -22,7 +31,7 @@ export const fuzzySequentialMatch = (filter: string, word: string) => { const newWord = word.substring(pos + 1); const newFilter = filter.substring(1); - return fuzzySequentialMatch(newFilter, newWord); + return _fuzzySequentialMatch(newFilter, newWord); } return true; diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 08c1984c8c..1f04fe90fe 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -36,6 +36,8 @@ export class QuickBar extends LitElement { @internalProperty() private _commandItems: CommandItem[] = []; + @internalProperty() private _entities: HassEntity[] = []; + @internalProperty() private _itemFilter = ""; @internalProperty() private _opened = false; @@ -46,6 +48,9 @@ export class QuickBar extends LitElement { this._commandMode = params.commandMode || false; this._opened = true; this._commandItems = this._generateCommandItems(); + this._entities = Object.keys(this.hass.states).map( + (entity_id) => this.hass.states[entity_id] + ); } public closeDialog() { @@ -101,19 +106,31 @@ export class QuickBar extends LitElement { }); protected renderEntityList = memoizeOne((filter) => { - const entities = this._filterEntityItems( - Object.keys(this.hass.states), - filter - ); + const entities = this._filterEntityItems(filter); return html` - ${entities.map((entityId) => { - const domain = computeDomain(entityId); + ${entities.map((entity) => { + const domain = computeDomain(entity.entity_id); return html` - + - ${entityId} + ${entity.attributes?.friendly_name + ? html` + + ${entity.attributes?.friendly_name} + + ${entity.entity_id} + ` + : html` + + ${entity.entity_id} + + `} `; })} @@ -155,25 +172,28 @@ export class QuickBar extends LitElement { ): CommandItem[] { return items .filter(({ text }) => - fuzzySequentialMatch(filter.toLowerCase(), text.toLowerCase()) + fuzzySequentialMatch(filter.toLowerCase(), [text.toLowerCase()]) ) .sort((itemA, itemB) => compare(itemA.text, itemB.text)); } - private _filterEntityItems( - entityIds: HassEntity["entity_id"][], - filter: string - ): HassEntity["entity_id"][] { - return entityIds - .filter((entityId) => - fuzzySequentialMatch(filter.toLowerCase(), entityId) + private _filterEntityItems(filter: string): HassEntity[] { + return this._entities + .filter(({ entity_id, attributes: { friendly_name } }) => { + const values = [entity_id]; + if (friendly_name) { + values.push(friendly_name); + } + return fuzzySequentialMatch(filter.toLowerCase(), values);} ) - .sort(); + .sort((entityA, entityB) => + compare(entityA.entity_id, entityB.entity_id) + ); } private async _processItemAndCloseDialog(ev: SingleSelectedEvent) { - const index = ev.detail.index; - const item = (ev.target as any).items[index].item; + const _index = ev.detail.index; + const item = (ev.target as any).items[_index].item; await this.hass.callService(item.domain, item.service, item.serviceData); @@ -181,10 +201,11 @@ export class QuickBar extends LitElement { } private _entityMoreInfo(ev: SingleSelectedEvent) { - const index = ev.detail.index; - const entityId = (ev.target as any).items[index].entityId; + const _index = ev.detail.index; + const entityId = (ev.target as any).items[_index].entityId; fireEvent(this, "hass-more-info", { entityId }); + this.closeDialog(); } diff --git a/test-mocha/common/string/sequence_matching.test.ts b/test-mocha/common/string/sequence_matching.test.ts index df1ef14e91..babc35696a 100644 --- a/test-mocha/common/string/sequence_matching.test.ts +++ b/test-mocha/common/string/sequence_matching.test.ts @@ -3,7 +3,7 @@ import { assert } from "chai"; import { fuzzySequentialMatch } from "../../../src/common/string/sequence_matching"; describe("fuzzySequentialMatch", () => { - const entityId = "automation.ticker"; + const entity = { entity_id: "automation.ticker", friendly_name: "Stocks" }; const shouldMatchEntity = [ "", @@ -23,6 +23,9 @@ describe("fuzzySequentialMatch", () => { "uoaintce", "au.tce", "tomaontkr", + "s", + "stocks", + "sks", ]; const shouldNotMatchEntity = [ @@ -32,19 +35,27 @@ describe("fuzzySequentialMatch", () => { "automation. ticke", "1", "noitamotua", + "autostocks", + "stox", ]; - describe(`Entity '${entityId}'`, () => { + describe(`Entity '${entity.entity_id}'`, () => { for (const goodFilter of shouldMatchEntity) { it(`matches with '${goodFilter}'`, () => { - const res = fuzzySequentialMatch(goodFilter, entityId); + const res = fuzzySequentialMatch(goodFilter, [ + entity.entity_id, + entity.friendly_name.toLowerCase(), + ]); assert.equal(res, true); }); } for (const badFilter of shouldNotMatchEntity) { it(`fails to match with '${badFilter}'`, () => { - const res = fuzzySequentialMatch(badFilter, entityId); + const res = fuzzySequentialMatch(badFilter, [ + entity.entity_id, + entity.friendly_name, + ]); assert.equal(res, false); }); }