diff --git a/build-scripts/gulp/translations.js b/build-scripts/gulp/translations.js index cda82a6c01..014df9f018 100755 --- a/build-scripts/gulp/translations.js +++ b/build-scripts/gulp/translations.js @@ -36,6 +36,7 @@ const TRANSLATION_FRAGMENTS = [ "page-authorize", "page-demo", "page-onboarding", + "developer-tools", ]; const tasks = []; diff --git a/setup.py b/setup.py index f7b4d98d63..c400df5a24 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20190712.0", + version="20190715.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors", diff --git a/src/common/search/search-input.ts b/src/common/search/search-input.ts new file mode 100644 index 0000000000..deb36885b7 --- /dev/null +++ b/src/common/search/search-input.ts @@ -0,0 +1,83 @@ +import { TemplateResult, html } from "lit-html"; +import { + css, + CSSResult, + customElement, + LitElement, + property, +} from "lit-element"; +import { fireEvent } from "../dom/fire_event"; +import "@polymer/iron-icon/iron-icon"; +import "@polymer/paper-input/paper-input"; +import "@polymer/paper-icon-button/paper-icon-button"; +import "@material/mwc-button"; + +@customElement("search-input") +class SearchInput extends LitElement { + @property() private filter?: string; + + protected render(): TemplateResult | void { + return html` +
+ + + ${this.filter && + html` + + `} + +
+ `; + } + + private async _filterChanged(value: string) { + fireEvent(this, "value-changed", { value: String(value) }); + } + + private async _filterInputChanged(e) { + this._filterChanged(e.target.value); + } + + private async _clearSearch() { + this._filterChanged(""); + } + + static get styles(): CSSResult { + return css` + paper-input { + flex: 1 1 auto; + margin: 0 16px; + } + .search-container { + display: inline-flex; + width: 100%; + align-items: center; + } + .prefix { + margin: 8px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "search-input": SearchInput; + } +} diff --git a/src/components/ha-menu-button.ts b/src/components/ha-menu-button.ts index 15a5887adb..ed97a569a8 100644 --- a/src/components/ha-menu-button.ts +++ b/src/components/ha-menu-button.ts @@ -72,7 +72,7 @@ class HaMenuButton extends LitElement { // on older frontends too, that don't have an always visible menu button // in the sidebar. this._alwaysVisible = - (Number((window.parent as any).frontendVersion) || 0) >= 20190710; + (Number((window.parent as any).frontendVersion) || 0) < 20190710; } protected updated(changedProps) { diff --git a/src/dialogs/config-flow/step-flow-pick-handler.ts b/src/dialogs/config-flow/step-flow-pick-handler.ts index ef64b0798a..0fbe0ba597 100644 --- a/src/dialogs/config-flow/step-flow-pick-handler.ts +++ b/src/dialogs/config-flow/step-flow-pick-handler.ts @@ -1,10 +1,11 @@ import { - LitElement, - TemplateResult, - html, css, - customElement, CSSResult, + customElement, + html, + LitElement, + property, + TemplateResult, } from "lit-element"; import "@polymer/paper-spinner/paper-spinner-lite"; import "@polymer/paper-item/paper-item"; @@ -12,23 +13,62 @@ import "@polymer/paper-item/paper-item-body"; import { HomeAssistant } from "../../types"; import { createConfigFlow } from "../../data/config_entries"; import { fireEvent } from "../../common/dom/fire_event"; +import memoizeOne from "memoize-one"; +import * as Fuse from "fuse.js"; + import "../../components/ha-icon-next"; +import "../../common/search/search-input"; + +interface HandlerObj { + name: string; + slug: string; +} @customElement("step-flow-pick-handler") class StepFlowPickHandler extends LitElement { - public hass!: HomeAssistant; - public handlers!: string[]; + @property() public hass!: HomeAssistant; + @property() public handlers!: string[]; + @property() private filter?: string; + + private _getHandlers = memoizeOne((h: string[], filter?: string) => { + const handlers: HandlerObj[] = h.map((handler) => { + return { + name: this.hass.localize(`component.${handler}.config.title`), + slug: handler, + }; + }); + + if (filter) { + const options: Fuse.FuseOptions = { + keys: ["name", "slug"], + caseSensitive: false, + minMatchCharLength: 2, + threshold: 0.2, + }; + const fuse = new Fuse(handlers, options); + return fuse.search(filter); + } + return handlers.sort((a, b) => + a.name.toUpperCase() < b.name.toUpperCase() ? -1 : 1 + ); + }); protected render(): TemplateResult | void { + const handlers = this._getHandlers(this.handlers, this.filter); + return html`

${this.hass.localize("ui.panel.config.integrations.new")}

- ${this.handlers.map( - (handler) => + + ${handlers.map( + (handler: HandlerObj) => html` - ${this.hass.localize(`component.${handler}.config.title`)} + ${handler.name} @@ -38,15 +78,20 @@ class StepFlowPickHandler extends LitElement { `; } + private async _filterChanged(e) { + this.filter = e.detail.value; + } + private async _handlerPicked(ev) { fireEvent(this, "flow-update", { - stepPromise: createConfigFlow(this.hass, ev.currentTarget.handler), + stepPromise: createConfigFlow(this.hass, ev.currentTarget.handler.slug), }); } static get styles(): CSSResult { return css` h2 { + margin-bottom: 2px; padding-left: 16px; } div { diff --git a/src/panels/config/cloud/account/cloud-alexa-pref.ts b/src/panels/config/cloud/account/cloud-alexa-pref.ts index 9e140f0e0d..dcbeee76be 100644 --- a/src/panels/config/cloud/account/cloud-alexa-pref.ts +++ b/src/panels/config/cloud/account/cloud-alexa-pref.ts @@ -41,8 +41,12 @@ export class CloudAlexaPref extends LitElement { control all your Home Assistant devices via any Alexa-enabled device.