mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-26 22:37:21 +00:00
Add friendly name to quick bar list and filter (#7306)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
0d741b6275
commit
63f60019d1
@ -7,7 +7,16 @@
|
|||||||
*
|
*
|
||||||
* return true if word contains sequence. Otherwise false.
|
* 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 === "") {
|
if (filter === "") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -22,7 +31,7 @@ export const fuzzySequentialMatch = (filter: string, word: string) => {
|
|||||||
const newWord = word.substring(pos + 1);
|
const newWord = word.substring(pos + 1);
|
||||||
const newFilter = filter.substring(1);
|
const newFilter = filter.substring(1);
|
||||||
|
|
||||||
return fuzzySequentialMatch(newFilter, newWord);
|
return _fuzzySequentialMatch(newFilter, newWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -36,6 +36,8 @@ export class QuickBar extends LitElement {
|
|||||||
|
|
||||||
@internalProperty() private _commandItems: CommandItem[] = [];
|
@internalProperty() private _commandItems: CommandItem[] = [];
|
||||||
|
|
||||||
|
@internalProperty() private _entities: HassEntity[] = [];
|
||||||
|
|
||||||
@internalProperty() private _itemFilter = "";
|
@internalProperty() private _itemFilter = "";
|
||||||
|
|
||||||
@internalProperty() private _opened = false;
|
@internalProperty() private _opened = false;
|
||||||
@ -46,6 +48,9 @@ export class QuickBar extends LitElement {
|
|||||||
this._commandMode = params.commandMode || false;
|
this._commandMode = params.commandMode || false;
|
||||||
this._opened = true;
|
this._opened = true;
|
||||||
this._commandItems = this._generateCommandItems();
|
this._commandItems = this._generateCommandItems();
|
||||||
|
this._entities = Object.keys(this.hass.states).map<HassEntity>(
|
||||||
|
(entity_id) => this.hass.states[entity_id]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog() {
|
public closeDialog() {
|
||||||
@ -101,19 +106,31 @@ export class QuickBar extends LitElement {
|
|||||||
});
|
});
|
||||||
|
|
||||||
protected renderEntityList = memoizeOne((filter) => {
|
protected renderEntityList = memoizeOne((filter) => {
|
||||||
const entities = this._filterEntityItems(
|
const entities = this._filterEntityItems(filter);
|
||||||
Object.keys(this.hass.states),
|
|
||||||
filter
|
|
||||||
);
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<mwc-list activatable @selected=${this._entityMoreInfo}>
|
<mwc-list activatable @selected=${this._entityMoreInfo}>
|
||||||
${entities.map((entityId) => {
|
${entities.map((entity) => {
|
||||||
const domain = computeDomain(entityId);
|
const domain = computeDomain(entity.entity_id);
|
||||||
return html`
|
return html`
|
||||||
<mwc-list-item graphic="icon" .entityId=${entityId}>
|
<mwc-list-item
|
||||||
|
twoline
|
||||||
|
.entityId=${entity.entity_id}
|
||||||
|
graphic="avatar"
|
||||||
|
>
|
||||||
<ha-icon .icon=${domainIcon(domain)} slot="graphic"></ha-icon>
|
<ha-icon .icon=${domainIcon(domain)} slot="graphic"></ha-icon>
|
||||||
${entityId}
|
${entity.attributes?.friendly_name
|
||||||
|
? html`
|
||||||
|
<span>
|
||||||
|
${entity.attributes?.friendly_name}
|
||||||
|
</span>
|
||||||
|
<span slot="secondary">${entity.entity_id}</span>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<span>
|
||||||
|
${entity.entity_id}
|
||||||
|
</span>
|
||||||
|
`}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
`;
|
`;
|
||||||
})}
|
})}
|
||||||
@ -155,25 +172,28 @@ export class QuickBar extends LitElement {
|
|||||||
): CommandItem[] {
|
): CommandItem[] {
|
||||||
return items
|
return items
|
||||||
.filter(({ text }) =>
|
.filter(({ text }) =>
|
||||||
fuzzySequentialMatch(filter.toLowerCase(), text.toLowerCase())
|
fuzzySequentialMatch(filter.toLowerCase(), [text.toLowerCase()])
|
||||||
)
|
)
|
||||||
.sort((itemA, itemB) => compare(itemA.text, itemB.text));
|
.sort((itemA, itemB) => compare(itemA.text, itemB.text));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filterEntityItems(
|
private _filterEntityItems(filter: string): HassEntity[] {
|
||||||
entityIds: HassEntity["entity_id"][],
|
return this._entities
|
||||||
filter: string
|
.filter(({ entity_id, attributes: { friendly_name } }) => {
|
||||||
): HassEntity["entity_id"][] {
|
const values = [entity_id];
|
||||||
return entityIds
|
if (friendly_name) {
|
||||||
.filter((entityId) =>
|
values.push(friendly_name);
|
||||||
fuzzySequentialMatch(filter.toLowerCase(), entityId)
|
}
|
||||||
|
return fuzzySequentialMatch(filter.toLowerCase(), values);}
|
||||||
)
|
)
|
||||||
.sort();
|
.sort((entityA, entityB) =>
|
||||||
|
compare(entityA.entity_id, entityB.entity_id)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _processItemAndCloseDialog(ev: SingleSelectedEvent) {
|
private async _processItemAndCloseDialog(ev: SingleSelectedEvent) {
|
||||||
const index = ev.detail.index;
|
const _index = ev.detail.index;
|
||||||
const item = (ev.target as any).items[index].item;
|
const item = (ev.target as any).items[_index].item;
|
||||||
|
|
||||||
await this.hass.callService(item.domain, item.service, item.serviceData);
|
await this.hass.callService(item.domain, item.service, item.serviceData);
|
||||||
|
|
||||||
@ -181,10 +201,11 @@ export class QuickBar extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _entityMoreInfo(ev: SingleSelectedEvent) {
|
private _entityMoreInfo(ev: SingleSelectedEvent) {
|
||||||
const index = ev.detail.index;
|
const _index = ev.detail.index;
|
||||||
const entityId = (ev.target as any).items[index].entityId;
|
const entityId = (ev.target as any).items[_index].entityId;
|
||||||
|
|
||||||
fireEvent(this, "hass-more-info", { entityId });
|
fireEvent(this, "hass-more-info", { entityId });
|
||||||
|
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { assert } from "chai";
|
|||||||
import { fuzzySequentialMatch } from "../../../src/common/string/sequence_matching";
|
import { fuzzySequentialMatch } from "../../../src/common/string/sequence_matching";
|
||||||
|
|
||||||
describe("fuzzySequentialMatch", () => {
|
describe("fuzzySequentialMatch", () => {
|
||||||
const entityId = "automation.ticker";
|
const entity = { entity_id: "automation.ticker", friendly_name: "Stocks" };
|
||||||
|
|
||||||
const shouldMatchEntity = [
|
const shouldMatchEntity = [
|
||||||
"",
|
"",
|
||||||
@ -23,6 +23,9 @@ describe("fuzzySequentialMatch", () => {
|
|||||||
"uoaintce",
|
"uoaintce",
|
||||||
"au.tce",
|
"au.tce",
|
||||||
"tomaontkr",
|
"tomaontkr",
|
||||||
|
"s",
|
||||||
|
"stocks",
|
||||||
|
"sks",
|
||||||
];
|
];
|
||||||
|
|
||||||
const shouldNotMatchEntity = [
|
const shouldNotMatchEntity = [
|
||||||
@ -32,19 +35,27 @@ describe("fuzzySequentialMatch", () => {
|
|||||||
"automation. ticke",
|
"automation. ticke",
|
||||||
"1",
|
"1",
|
||||||
"noitamotua",
|
"noitamotua",
|
||||||
|
"autostocks",
|
||||||
|
"stox",
|
||||||
];
|
];
|
||||||
|
|
||||||
describe(`Entity '${entityId}'`, () => {
|
describe(`Entity '${entity.entity_id}'`, () => {
|
||||||
for (const goodFilter of shouldMatchEntity) {
|
for (const goodFilter of shouldMatchEntity) {
|
||||||
it(`matches with '${goodFilter}'`, () => {
|
it(`matches with '${goodFilter}'`, () => {
|
||||||
const res = fuzzySequentialMatch(goodFilter, entityId);
|
const res = fuzzySequentialMatch(goodFilter, [
|
||||||
|
entity.entity_id,
|
||||||
|
entity.friendly_name.toLowerCase(),
|
||||||
|
]);
|
||||||
assert.equal(res, true);
|
assert.equal(res, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const badFilter of shouldNotMatchEntity) {
|
for (const badFilter of shouldNotMatchEntity) {
|
||||||
it(`fails to match with '${badFilter}'`, () => {
|
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);
|
assert.equal(res, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user