mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-14 12:56:37 +00:00
Add search to add helper dialog (#23728)
* Add search to add helper dialog * Add missing scrollbar style * Fix string * Remove virtualizer & add alias
This commit is contained in:
parent
e6cc920781
commit
1043db29be
@ -1,13 +1,12 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item-base";
|
|
||||||
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
|
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
|
||||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||||
import { dynamicElement } from "../../../common/dom/dynamic-element-directive";
|
import { dynamicElement } from "../../../common/dom/dynamic-element-directive";
|
||||||
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
|
|
||||||
import "../../../components/ha-circular-progress";
|
import "../../../components/ha-circular-progress";
|
||||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||||
import "../../../components/ha-list-item";
|
import "../../../components/ha-list-item";
|
||||||
@ -26,13 +25,14 @@ import {
|
|||||||
import { createSchedule } from "../../../data/schedule";
|
import { createSchedule } from "../../../data/schedule";
|
||||||
import { createTimer } from "../../../data/timer";
|
import { createTimer } from "../../../data/timer";
|
||||||
import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow";
|
import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow";
|
||||||
import { haStyleDialog } from "../../../resources/styles";
|
import { haStyleDialog, haStyleScrollbar } from "../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { brandsUrl } from "../../../util/brands-url";
|
import { brandsUrl } from "../../../util/brands-url";
|
||||||
import type { Helper, HelperDomain } from "./const";
|
import type { Helper, HelperDomain } from "./const";
|
||||||
import { isHelperDomain } from "./const";
|
import { isHelperDomain } from "./const";
|
||||||
import type { ShowDialogHelperDetailParams } from "./show-dialog-helper-detail";
|
import type { ShowDialogHelperDetailParams } from "./show-dialog-helper-detail";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { stringCompare } from "../../../common/string/compare";
|
||||||
|
|
||||||
type HelperCreators = Record<
|
type HelperCreators = Record<
|
||||||
HelperDomain,
|
HelperDomain,
|
||||||
@ -46,6 +46,7 @@ type HelperCreators = Record<
|
|||||||
params: any
|
params: any
|
||||||
) => Promise<Helper>;
|
) => Promise<Helper>;
|
||||||
import: () => Promise<unknown>;
|
import: () => Promise<unknown>;
|
||||||
|
alias?: string[];
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@ -53,6 +54,7 @@ const HELPERS: HelperCreators = {
|
|||||||
input_boolean: {
|
input_boolean: {
|
||||||
create: createInputBoolean,
|
create: createInputBoolean,
|
||||||
import: () => import("./forms/ha-input_boolean-form"),
|
import: () => import("./forms/ha-input_boolean-form"),
|
||||||
|
alias: ["switch", "toggle"],
|
||||||
},
|
},
|
||||||
input_button: {
|
input_button: {
|
||||||
create: createInputButton,
|
create: createInputButton,
|
||||||
@ -73,6 +75,7 @@ const HELPERS: HelperCreators = {
|
|||||||
input_select: {
|
input_select: {
|
||||||
create: createInputSelect,
|
create: createInputSelect,
|
||||||
import: () => import("./forms/ha-input_select-form"),
|
import: () => import("./forms/ha-input_select-form"),
|
||||||
|
alias: ["select", "dropdown"],
|
||||||
},
|
},
|
||||||
counter: {
|
counter: {
|
||||||
create: createCounter,
|
create: createCounter,
|
||||||
@ -81,6 +84,7 @@ const HELPERS: HelperCreators = {
|
|||||||
timer: {
|
timer: {
|
||||||
create: createTimer,
|
create: createTimer,
|
||||||
import: () => import("./forms/ha-timer-form"),
|
import: () => import("./forms/ha-timer-form"),
|
||||||
|
alias: ["countdown"],
|
||||||
},
|
},
|
||||||
schedule: {
|
schedule: {
|
||||||
create: createSchedule,
|
create: createSchedule,
|
||||||
@ -108,6 +112,8 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
|
|
||||||
@state() private _loading = false;
|
@state() private _loading = false;
|
||||||
|
|
||||||
|
@state() private _filter?: string;
|
||||||
|
|
||||||
private _params?: ShowDialogHelperDetailParams;
|
private _params?: ShowDialogHelperDetailParams;
|
||||||
|
|
||||||
public async showDialog(params: ShowDialogHelperDetailParams): Promise<void> {
|
public async showDialog(params: ShowDialogHelperDetailParams): Promise<void> {
|
||||||
@ -172,24 +178,24 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
indeterminate
|
indeterminate
|
||||||
></ha-circular-progress>`;
|
></ha-circular-progress>`;
|
||||||
} else {
|
} else {
|
||||||
const items: [string, string][] = [];
|
const items = this._filterHelpers(
|
||||||
|
HELPERS,
|
||||||
for (const helper of Object.keys(HELPERS) as (keyof typeof HELPERS)[]) {
|
this._helperFlows,
|
||||||
items.push([
|
this._filter
|
||||||
helper,
|
);
|
||||||
this.hass.localize(`ui.panel.config.helpers.types.${helper}`) ||
|
|
||||||
helper,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const domain of this._helperFlows) {
|
|
||||||
items.push([domain, domainToName(this.hass.localize, domain)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
items.sort((a, b) => a[1].localeCompare(b[1]));
|
|
||||||
|
|
||||||
content = html`
|
content = html`
|
||||||
|
<search-input
|
||||||
|
.hass=${this.hass}
|
||||||
|
dialogInitialFocus="true"
|
||||||
|
.filter=${this._filter}
|
||||||
|
@value-changed=${this._filterChanged}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.integrations.search_helper"
|
||||||
|
)}
|
||||||
|
></search-input>
|
||||||
<mwc-list
|
<mwc-list
|
||||||
|
class="ha-scrollbar"
|
||||||
innerRole="listbox"
|
innerRole="listbox"
|
||||||
itemRoles="option"
|
itemRoles="option"
|
||||||
innerAriaLabel=${this.hass.localize(
|
innerAriaLabel=${this.hass.localize(
|
||||||
@ -274,6 +280,52 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _filterHelpers = memoizeOne(
|
||||||
|
(
|
||||||
|
predefinedHelpers: HelperCreators,
|
||||||
|
flowHelpers?: string[],
|
||||||
|
filter?: string
|
||||||
|
) => {
|
||||||
|
const items: [string, string][] = [];
|
||||||
|
|
||||||
|
for (const helper of Object.keys(
|
||||||
|
predefinedHelpers
|
||||||
|
) as (keyof typeof predefinedHelpers)[]) {
|
||||||
|
items.push([
|
||||||
|
helper,
|
||||||
|
this.hass.localize(`ui.panel.config.helpers.types.${helper}`) ||
|
||||||
|
helper,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flowHelpers) {
|
||||||
|
for (const domain of flowHelpers) {
|
||||||
|
items.push([domain, domainToName(this.hass.localize, domain)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items
|
||||||
|
.filter(([domain, label]) => {
|
||||||
|
if (filter) {
|
||||||
|
const lowerFilter = filter.toLowerCase();
|
||||||
|
return (
|
||||||
|
label.toLowerCase().includes(lowerFilter) ||
|
||||||
|
domain.toLowerCase().includes(lowerFilter) ||
|
||||||
|
(predefinedHelpers[domain as HelperDomain]?.alias || []).some(
|
||||||
|
(alias) => alias.toLowerCase().includes(lowerFilter)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.sort((a, b) => stringCompare(a[1], b[1], this.hass.locale.language));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
private async _filterChanged(e) {
|
||||||
|
this._filter = e.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
this._item = ev.detail.value;
|
this._item = ev.detail.value;
|
||||||
}
|
}
|
||||||
@ -303,13 +355,8 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _domainPicked(
|
private async _domainPicked(ev): Promise<void> {
|
||||||
ev: CustomEvent<RequestSelectedDetail>
|
const domain = ev.target.closest("ha-list-item").domain;
|
||||||
): Promise<void> {
|
|
||||||
if (!shouldHandleRequestSelectedEvent(ev)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const domain = (ev.currentTarget! as any).domain;
|
|
||||||
|
|
||||||
if (domain in HELPERS) {
|
if (domain in HELPERS) {
|
||||||
this._loading = true;
|
this._loading = true;
|
||||||
@ -343,6 +390,7 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
|
haStyleScrollbar,
|
||||||
haStyleDialog,
|
haStyleDialog,
|
||||||
css`
|
css`
|
||||||
ha-dialog.button-left {
|
ha-dialog.button-left {
|
||||||
@ -364,6 +412,18 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
.form {
|
.form {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
}
|
}
|
||||||
|
search-input {
|
||||||
|
display: block;
|
||||||
|
margin: 16px 16px 0;
|
||||||
|
}
|
||||||
|
mwc-list {
|
||||||
|
height: calc(60vh - 184px);
|
||||||
|
}
|
||||||
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
|
mwc-list {
|
||||||
|
height: calc(100vh - 184px);
|
||||||
|
}
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -4936,6 +4936,7 @@
|
|||||||
"rename_input_label": "Entry name",
|
"rename_input_label": "Entry name",
|
||||||
"search": "Search integrations",
|
"search": "Search integrations",
|
||||||
"search_brand": "Search for a brand name",
|
"search_brand": "Search for a brand name",
|
||||||
|
"search_helper": "Search for a helper",
|
||||||
"add_zwave_js_device": "Add Z-Wave device",
|
"add_zwave_js_device": "Add Z-Wave device",
|
||||||
"add_zha_device": "Add Zigbee device",
|
"add_zha_device": "Add Zigbee device",
|
||||||
"add_matter_device": "Add Matter device",
|
"add_matter_device": "Add Matter device",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user