Merge pull request #3184 from home-assistant/dev

20190509.0
This commit is contained in:
Paulus Schoutsen 2019-05-09 15:48:22 -07:00 committed by GitHub
commit bbdaa4b7c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 338 additions and 37366 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
version="20190508.0",
version="20190509.0",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors",

View File

@ -1,4 +1,11 @@
import { LitElement, html, property, PropertyValues } from "lit-element";
import {
LitElement,
html,
property,
PropertyValues,
CSSResult,
css,
} from "lit-element";
import "@material/mwc-button";
import "../components/ha-form";
import "../components/ha-markdown";
@ -20,19 +27,6 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
protected render() {
return html`
<style>
:host {
/* So we can set min-height to avoid jumping during loading */
display: block;
}
.action {
margin: 24px 0 8px;
text-align: center;
}
.error {
color: red;
}
</style>
<form>
${this._renderForm()}
</form>
@ -168,7 +162,7 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
return;
}
this._updateStep(data);
await this._updateStep(data);
} else {
this._state = "error";
this._errorMessage = data.message;
@ -199,7 +193,7 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
document.location.assign(url);
}
private _updateStep(step: ConfigFlowStep) {
private async _updateStep(step: ConfigFlowStep) {
let stepData: any = null;
if (
this._step &&
@ -215,6 +209,15 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
if (stepData != null) {
this._stepData = stepData;
}
await this.updateComplete;
// 100ms to give all the form elements time to initialize.
setTimeout(() => {
const form = this.shadowRoot!.querySelector("ha-form");
if (form) {
(form as any).focus();
}
}, 100);
}
private _computeStepDescription(step: ConfigFlowStepForm) {
@ -282,7 +285,7 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
this._redirect(newStep.result);
return;
}
this._updateStep(newStep);
await this._updateStep(newStep);
} catch (err) {
// tslint:disable-next-line: no-console
console.error("Error submitting step", err);
@ -292,5 +295,21 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
this.style.setProperty("min-height", "");
}
}
static get styles(): CSSResult {
return css`
:host {
/* So we can set min-height to avoid jumping during loading */
display: block;
}
.action {
margin: 24px 0 8px;
text-align: center;
}
.error {
color: red;
}
`;
}
}
customElements.define("ha-auth-flow", HaAuthFlow);

View File

@ -48,12 +48,12 @@ class HaCameraStream extends LitElement {
}
return html`
${this._shouldRenderMJPEG
${__DEMO__ || this._shouldRenderMJPEG
? html`
<img
@load=${this._elementResized}
.src=${__DEMO__
? "/demo/webcamp.jpg"
? `/api/camera_proxy_stream/${this.stateObj.entity_id}`
: computeMJPEGStreamUrl(this.stateObj)}
.alt=${computeStateName(this.stateObj)}
/>

View File

@ -189,6 +189,18 @@ class HaForm extends EventsMixin(PolymerElement) {
};
}
focus() {
const input = this.shadowRoot.querySelector(
"ha-form, paper-input, ha-paper-slider, paper-checkbox, paper-dropdown-menu"
);
if (!input) {
return;
}
input.focus();
}
_isArray(val) {
return Array.isArray(val);
}

View File

@ -3,6 +3,15 @@ import { createCollection } from "home-assistant-js-websocket";
import { debounce } from "../common/util/debounce";
import { LocalizeFunc } from "../common/translations/localize";
export interface DataEntryFlowProgressedEvent {
type: "data_entry_flow_progressed";
data: {
handler: string;
flow_id: string;
refresh: boolean;
};
}
export interface ConfigEntry {
entry_id: string;
domain: string;
@ -38,6 +47,15 @@ export interface ConfigFlowStepForm {
description_placeholders: { [key: string]: string };
}
export interface ConfigFlowStepExternal {
type: "external";
flow_id: string;
handler: string;
step_id: string;
url: string;
description_placeholders: { [key: string]: string };
}
export interface ConfigFlowStepCreateEntry {
type: "create_entry";
version: number;
@ -60,6 +78,7 @@ export interface ConfigFlowStepAbort {
export type ConfigFlowStep =
| ConfigFlowStepForm
| ConfigFlowStepExternal
| ConfigFlowStepCreateEntry
| ConfigFlowStepAbort;

View File

@ -34,6 +34,7 @@ import { HaConfigFlowParams } from "./show-dialog-config-flow";
import "./step-flow-pick-handler";
import "./step-flow-loading";
import "./step-flow-form";
import "./step-flow-external";
import "./step-flow-abort";
import "./step-flow-create-entry";
import {
@ -155,6 +156,13 @@ class ConfigFlowDialog extends LitElement {
.hass=${this.hass}
></step-flow-form>
`
: this._step.type === "external"
? html`
<step-flow-external
.step=${this._step}
.hass=${this.hass}
></step-flow-external>
`
: this._step.type === "abort"
? html`
<step-flow-abort
@ -251,7 +259,7 @@ class ConfigFlowDialog extends LitElement {
return;
}
const flowFinished = Boolean(
this._step && ["success", "abort"].includes(this._step.type)
this._step && ["create_entry", "abort"].includes(this._step.type)
);
// If we created this flow, delete it now.

View File

@ -0,0 +1,106 @@
import {
LitElement,
TemplateResult,
html,
customElement,
property,
CSSResultArray,
css,
} from "lit-element";
import "@material/mwc-button";
import {
ConfigFlowStepExternal,
DataEntryFlowProgressedEvent,
fetchConfigFlow,
} from "../../data/config_entries";
import { HomeAssistant } from "../../types";
import { localizeKey } from "../../common/translations/localize";
import { fireEvent } from "../../common/dom/fire_event";
import { configFlowContentStyles } from "./styles";
@customElement("step-flow-external")
class StepFlowExternal extends LitElement {
@property()
public hass!: HomeAssistant;
@property()
private step!: ConfigFlowStepExternal;
protected render(): TemplateResult | void {
const localize = this.hass.localize;
const step = this.step;
const description = localizeKey(
localize,
`component.${step.handler}.config.${step.step_id}.description`,
step.description_placeholders
);
return html`
<h2>
${localize(
`component.${step.handler}.config.step.${step.step_id}.title`
)}
</h2>
<div class="content">
<p>
${localize(
"ui.panel.config.integrations.config_flow.external_step.description"
)}
</p>
${description
? html`
<ha-markdown .content=${description} allow-svg></ha-markdown>
`
: ""}
<div class="open-button">
<a href=${this.step.url} target="_blank">
<mwc-button raised>
${localize(
"ui.panel.config.integrations.config_flow.external_step.open_site"
)}
</mwc-button>
</a>
</div>
</div>
`;
}
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
this.hass.connection.subscribeEvents<DataEntryFlowProgressedEvent>(
async (ev) => {
if (ev.data.flow_id !== this.step.flow_id) {
return;
}
const step = await fetchConfigFlow(this.hass, this.step.flow_id);
fireEvent(this, "flow-update", { step });
},
"data_entry_flow_progressed"
);
window.open(this.step.url);
}
static get styles(): CSSResultArray {
return [
configFlowContentStyles,
css`
.open-button {
text-align: center;
padding: 24px 0;
}
.open-button a {
text-decoration: none;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"step-flow-external": StepFlowExternal;
}
}

View File

@ -22,7 +22,9 @@ let es5Loaded: Promise<unknown> | undefined;
window.loadES5Adapter = () => {
if (!es5Loaded) {
es5Loaded = Promise.all([
loadJS(`${__STATIC_PATH__}custom-elements-es5-adapter.js`).catch(),
loadJS(
`${__STATIC_PATH__}/polyfills/custom-elements-es5-adapter.js`
).catch(),
import(/* webpackChunkName: "compat" */ "./compatibility"),
]);
}
@ -47,7 +49,9 @@ function initialize(panel: CustomPanelInfo, properties: {}) {
let start: Promise<unknown> = Promise.resolve();
if (!webComponentsSupported) {
start = start.then(() => loadJS("/static/webcomponents-bundle.js"));
start = start.then(() =>
loadJS(`${__STATIC_PATH__}/polyfills/webcomponents-bundle.js`)
);
}
if (__BUILD__ === "es5") {

View File

@ -18,8 +18,8 @@ export default class WaitAction extends Component {
onTemplateChange(ev) {
this.props.onChange(
this.props.index,
Object.assign({}, this.props.trigger, {
[ev.target.name]: ev.target.value,
Object.assign({}, this.props.action, {
[ev.target.getAttribute("name")]: ev.target.value,
})
);
}

View File

@ -53,6 +53,9 @@ const addEntities = (entities: Set<string>, obj) => {
if (obj.cards) {
obj.cards.forEach((card) => addEntities(entities, card));
}
if (obj.elements) {
obj.elements.forEach((card) => addEntities(entities, card));
}
if (obj.badges) {
obj.badges.forEach((badge) => addEntityId(entities, badge));
}

View File

@ -850,6 +850,12 @@
"device_unavailable": "device unavailable",
"entity_unavailable": "entity unavailable",
"no_area": "No Area"
},
"config_flow": {
"external_step": {
"description": "This step requires you to visit an external website to be completed.",
"open_site": "Open website"
}
}
},
"users": {

View File

@ -855,6 +855,11 @@
"required_fields": "Omple tots els camps obligatoris",
"password_not_match": "Les contrasenyes no coincideixen"
}
},
"integration": {
"intro": "Els dispositius i serveis es representen a Home Assistant com a integracions. Pots configurar-los ara o més tard des de la pàgina de configuració.",
"more_integrations": "Més",
"finish": "Finalitza"
}
},
"lovelace": {

View File

@ -603,6 +603,12 @@
"device_unavailable": "device unavailable",
"entity_unavailable": "entity unavailable",
"no_area": "No Area"
},
"config_flow": {
"external_step": {
"description": "This step requires you to visit an external website to be completed.",
"open_site": "Open website"
}
}
},
"zha": {

View File

@ -855,6 +855,11 @@
"required_fields": "Complete todos los campos requeridos",
"password_not_match": "Las contraseñas no coinciden"
}
},
"integration": {
"intro": "Los dispositivos y servicios están representados en Home Assistant como integraciones. Puede configurarlos ahora, o hacerlo más tarde desde la pantalla de configuración.",
"more_integrations": "Más",
"finish": "Terminar"
}
},
"lovelace": {
@ -868,6 +873,14 @@
"title": "Bienvenido a casa",
"no_devices": "Esta página te permite controlar tus dispositivos, aunque parece que aún no has configurado ninguno. Dirígete a la página de integraciones para empezar.",
"go_to_integrations_page": "Ir a la página de integraciones."
},
"picture-elements": {
"hold": "Mantener:",
"tap": "Toque:",
"navigate_to": "Navegar a {location}",
"toggle": "Alternar {name}",
"call_service": "Ejecutar servicio {name}",
"more_info": "Mostrar más información: {name}"
}
},
"editor": {
@ -925,7 +938,8 @@
},
"sidebar": {
"log_out": "Cerrar sesión",
"developer_tools": "Herramientas para desarrolladores"
"developer_tools": "Herramientas para desarrolladores",
"external_app_configuration": "Configuración de la aplicación"
},
"common": {
"loading": "Cargando",

View File

@ -581,7 +581,8 @@
"cloud": {
"caption": "Cloud Home Assistant",
"description_login": "Connecté en tant que {email}",
"description_not_login": "Pas connecté"
"description_not_login": "Pas connecté",
"description_features": "Contrôle hors de la maison, intégration avec Alexa et Google Assistant."
},
"integrations": {
"caption": "Intégrations",
@ -854,6 +855,11 @@
"required_fields": "Remplissez tous les champs requis",
"password_not_match": "Les mots de passe ne correspondent pas"
}
},
"integration": {
"intro": "Les appareils et les services sont représentés dans Home Assistant sous forme dintégrations. Vous pouvez les configurer maintenant ou le faire plus tard à partir de l'écran de configuration.",
"more_integrations": "Plus",
"finish": "Terminer"
}
},
"lovelace": {