mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 17:56:46 +00:00
commit
2586590bd9
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="home-assistant-frontend",
|
name="home-assistant-frontend",
|
||||||
version="20190315.1",
|
version="20190316.0",
|
||||||
description="The Home Assistant frontend",
|
description="The Home Assistant frontend",
|
||||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||||
author="The Home Assistant Authors",
|
author="The Home Assistant Authors",
|
||||||
|
@ -58,15 +58,13 @@ class MoreInfoCamera extends UpdatingElement {
|
|||||||
videoEl.muted = true;
|
videoEl.muted = true;
|
||||||
|
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
let Hls: HLSModule | undefined;
|
const Hls = ((await import(/* webpackChunkName: "hls.js" */ "hls.js")) as any)
|
||||||
|
.default as HLSModule;
|
||||||
let hlsSupported =
|
let hlsSupported = Hls.isSupported();
|
||||||
videoEl.canPlayType("application/vnd.apple.mpegurl") !== "";
|
|
||||||
|
|
||||||
if (!hlsSupported) {
|
if (!hlsSupported) {
|
||||||
Hls = ((await import(/* webpackChunkName: "hls.js" */ "hls.js")) as any)
|
hlsSupported =
|
||||||
.default as HLSModule;
|
videoEl.canPlayType("application/vnd.apple.mpegurl") !== "";
|
||||||
hlsSupported = Hls.isSupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hlsSupported) {
|
if (hlsSupported) {
|
||||||
@ -76,7 +74,7 @@ class MoreInfoCamera extends UpdatingElement {
|
|||||||
this.stateObj.entity_id
|
this.stateObj.entity_id
|
||||||
);
|
);
|
||||||
|
|
||||||
if (Hls) {
|
if (Hls.isSupported()) {
|
||||||
this._renderHLSPolyfill(videoEl, Hls, url);
|
this._renderHLSPolyfill(videoEl, Hls, url);
|
||||||
} else {
|
} else {
|
||||||
this._renderHLSNative(videoEl, url);
|
this._renderHLSNative(videoEl, url);
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
css,
|
css,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { removeInitSkeleton } from "../util/init-skeleton";
|
||||||
|
|
||||||
class HaInitPage extends LitElement {
|
class HaInitPage extends LitElement {
|
||||||
public error?: boolean;
|
public error?: boolean;
|
||||||
@ -35,6 +36,10 @@ class HaInitPage extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected firstUpdated() {
|
||||||
|
removeInitSkeleton();
|
||||||
|
}
|
||||||
|
|
||||||
private _retry() {
|
private _retry() {
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,9 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
super.update(changedProps);
|
super.update(changedProps);
|
||||||
|
|
||||||
if (!changedProps.has("route")) {
|
if (!changedProps.has("route")) {
|
||||||
if (this.lastChild) {
|
// Do not update if we have a currentLoadProm, because that means
|
||||||
|
// that there is still an old panel shown and we're moving to a new one.
|
||||||
|
if (this.lastChild && !this._currentLoadProm) {
|
||||||
this.updatePageEl(this.lastChild, changedProps);
|
this.updatePageEl(this.lastChild, changedProps);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -214,11 +216,11 @@ export class HassRouterPage extends UpdatingElement {
|
|||||||
const dividerPos = route.path.indexOf("/", 1);
|
const dividerPos = route.path.indexOf("/", 1);
|
||||||
return dividerPos === -1
|
return dividerPos === -1
|
||||||
? {
|
? {
|
||||||
prefix: route.path,
|
prefix: route.prefix + route.path,
|
||||||
path: "",
|
path: "",
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
prefix: route.path.substr(0, dividerPos),
|
prefix: route.prefix + route.path.substr(0, dividerPos),
|
||||||
path: route.path.substr(dividerPos),
|
path: route.path.substr(dividerPos),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
RouterOptions,
|
RouterOptions,
|
||||||
RouteOptions,
|
RouteOptions,
|
||||||
} from "./hass-router-page";
|
} from "./hass-router-page";
|
||||||
|
import { removeInitSkeleton } from "../util/init-skeleton";
|
||||||
|
|
||||||
const CACHE_COMPONENTS = ["lovelace", "states"];
|
const CACHE_COMPONENTS = ["lovelace", "states"];
|
||||||
const COMPONENTS = {
|
const COMPONENTS = {
|
||||||
@ -113,11 +114,7 @@ class PartialPanelResolver extends HassRouterPage {
|
|||||||
this.routerOptions = getRoutes(this.hass!.panels);
|
this.routerOptions = getRoutes(this.hass!.panels);
|
||||||
await this.rebuild();
|
await this.rebuild();
|
||||||
await this.pageRendered;
|
await this.pageRendered;
|
||||||
|
removeInitSkeleton();
|
||||||
const initEl = document.getElementById("ha-init-skeleton");
|
|
||||||
if (initEl) {
|
|
||||||
initEl.parentElement!.removeChild(initEl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ class DialogAreaDetail extends LitElement {
|
|||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
const entry = this._params.entry;
|
||||||
const nameInvalid = this._name.trim() === "";
|
const nameInvalid = this._name.trim() === "";
|
||||||
return html`
|
return html`
|
||||||
<paper-dialog
|
<paper-dialog
|
||||||
@ -52,8 +53,8 @@ class DialogAreaDetail extends LitElement {
|
|||||||
@opened-changed="${this._openedChanged}"
|
@opened-changed="${this._openedChanged}"
|
||||||
>
|
>
|
||||||
<h2>
|
<h2>
|
||||||
${this._params.entry
|
${entry
|
||||||
? this._params.entry.name
|
? entry.name
|
||||||
: this.hass.localize(
|
: this.hass.localize(
|
||||||
"ui.panel.config.area_registry.editor.default_name"
|
"ui.panel.config.area_registry.editor.default_name"
|
||||||
)}
|
)}
|
||||||
@ -65,17 +66,23 @@ class DialogAreaDetail extends LitElement {
|
|||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
<div class="form">
|
<div class="form">
|
||||||
|
${entry
|
||||||
|
? html`
|
||||||
|
<div>Area ID: ${entry.area_id}</div>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
|
||||||
<paper-input
|
<paper-input
|
||||||
.value=${this._name}
|
.value=${this._name}
|
||||||
@value-changed=${this._nameChanged}
|
@value-changed=${this._nameChanged}
|
||||||
.label=${this.hass.localize("ui.dialogs.more_info_settings.name")}
|
label="Name"
|
||||||
error-message="Name is required"
|
error-message="Name is required"
|
||||||
.invalid=${nameInvalid}
|
.invalid=${nameInvalid}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
</div>
|
</div>
|
||||||
</paper-dialog-scrollable>
|
</paper-dialog-scrollable>
|
||||||
<div class="paper-dialog-buttons">
|
<div class="paper-dialog-buttons">
|
||||||
${this._params.entry
|
${entry
|
||||||
? html`
|
? html`
|
||||||
<mwc-button
|
<mwc-button
|
||||||
class="warning"
|
class="warning"
|
||||||
@ -92,7 +99,7 @@ class DialogAreaDetail extends LitElement {
|
|||||||
@click="${this._updateEntry}"
|
@click="${this._updateEntry}"
|
||||||
.disabled=${nameInvalid || this._submitting}
|
.disabled=${nameInvalid || this._submitting}
|
||||||
>
|
>
|
||||||
${this._params.entry
|
${entry
|
||||||
? this.hass.localize(
|
? this.hass.localize(
|
||||||
"ui.panel.config.area_registry.editor.update"
|
"ui.panel.config.area_registry.editor.update"
|
||||||
)
|
)
|
||||||
|
@ -18,13 +18,13 @@ class HaConfigAutomation extends PolymerElement {
|
|||||||
</style>
|
</style>
|
||||||
<app-route
|
<app-route
|
||||||
route="[[route]]"
|
route="[[route]]"
|
||||||
pattern="/automation/edit/:automation"
|
pattern="/edit/:automation"
|
||||||
data="{{_routeData}}"
|
data="{{_routeData}}"
|
||||||
active="{{_edittingAutomation}}"
|
active="{{_edittingAutomation}}"
|
||||||
></app-route>
|
></app-route>
|
||||||
<app-route
|
<app-route
|
||||||
route="[[route]]"
|
route="[[route]]"
|
||||||
pattern="/automation/new"
|
pattern="/new"
|
||||||
active="{{_creatingNew}}"
|
active="{{_creatingNew}}"
|
||||||
></app-route>
|
></app-route>
|
||||||
|
|
||||||
|
@ -11,12 +11,8 @@ import "./ha-config-cloud-login";
|
|||||||
import "./ha-config-cloud-register";
|
import "./ha-config-cloud-register";
|
||||||
import NavigateMixin from "../../../mixins/navigate-mixin";
|
import NavigateMixin from "../../../mixins/navigate-mixin";
|
||||||
|
|
||||||
const LOGGED_IN_URLS = ["/cloud/account"];
|
const LOGGED_IN_URLS = ["/account"];
|
||||||
const NOT_LOGGED_IN_URLS = [
|
const NOT_LOGGED_IN_URLS = ["/login", "/register", "/forgot-password"];
|
||||||
"/cloud/login",
|
|
||||||
"/cloud/register",
|
|
||||||
"/cloud/forgot-password",
|
|
||||||
];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin NavigateMixin
|
* @appliesMixin NavigateMixin
|
||||||
@ -26,7 +22,7 @@ class HaConfigCloud extends NavigateMixin(PolymerElement) {
|
|||||||
return html`
|
return html`
|
||||||
<app-route
|
<app-route
|
||||||
route="[[route]]"
|
route="[[route]]"
|
||||||
pattern="/cloud/:page"
|
pattern="/:page"
|
||||||
data="{{_routeData}}"
|
data="{{_routeData}}"
|
||||||
tail="{{_routeTail}}"
|
tail="{{_routeTail}}"
|
||||||
></app-route>
|
></app-route>
|
||||||
@ -121,8 +117,6 @@ class HaConfigCloud extends NavigateMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_checkRoute(route) {
|
_checkRoute(route) {
|
||||||
if (!route || route.path.substr(0, 6) !== "/cloud") return;
|
|
||||||
|
|
||||||
this._debouncer = Debouncer.debounce(
|
this._debouncer = Debouncer.debounce(
|
||||||
this._debouncer,
|
this._debouncer,
|
||||||
timeOut.after(0),
|
timeOut.after(0),
|
||||||
|
@ -121,7 +121,7 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected updatePageEl(el) {
|
protected updatePageEl(el) {
|
||||||
el.route = this.route;
|
el.route = this.routeTail;
|
||||||
el.hass = this.hass;
|
el.hass = this.hass;
|
||||||
el.isWide = this.hass.dockedSidebar ? this._wideSidebar : this._wide;
|
el.isWide = this.hass.dockedSidebar ? this._wideSidebar : this._wide;
|
||||||
el.cloudStatus = this._cloudStatus;
|
el.cloudStatus = this._cloudStatus;
|
||||||
|
@ -15,7 +15,7 @@ class HaConfigIntegrations extends NavigateMixin(PolymerElement) {
|
|||||||
return html`
|
return html`
|
||||||
<app-route
|
<app-route
|
||||||
route="[[route]]"
|
route="[[route]]"
|
||||||
pattern="/integrations/:page"
|
pattern="/:page"
|
||||||
data="{{_routeData}}"
|
data="{{_routeData}}"
|
||||||
tail="{{_routeTail}}"
|
tail="{{_routeTail}}"
|
||||||
></app-route>
|
></app-route>
|
||||||
@ -90,12 +90,12 @@ class HaConfigIntegrations extends NavigateMixin(PolymerElement) {
|
|||||||
|
|
||||||
ready() {
|
ready() {
|
||||||
super.ready();
|
super.ready();
|
||||||
this._loadData();
|
|
||||||
this.addEventListener("hass-reload-entries", () => this._loadData());
|
this.addEventListener("hass-reload-entries", () => this._loadData());
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
|
this._loadData();
|
||||||
|
|
||||||
this.hass.connection
|
this.hass.connection
|
||||||
.subscribeEvents(() => {
|
.subscribeEvents(() => {
|
||||||
|
@ -19,13 +19,13 @@ class HaConfigScript extends PolymerElement {
|
|||||||
</style>
|
</style>
|
||||||
<app-route
|
<app-route
|
||||||
route="[[route]]"
|
route="[[route]]"
|
||||||
pattern="/script/edit/:script"
|
pattern="/edit/:script"
|
||||||
data="{{_routeData}}"
|
data="{{_routeData}}"
|
||||||
active="{{_edittingScript}}"
|
active="{{_edittingScript}}"
|
||||||
></app-route>
|
></app-route>
|
||||||
<app-route
|
<app-route
|
||||||
route="[[route]]"
|
route="[[route]]"
|
||||||
pattern="/script/new"
|
pattern="/new"
|
||||||
active="{{_creatingNew}}"
|
active="{{_creatingNew}}"
|
||||||
></app-route>
|
></app-route>
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class HaConfigUsers extends NavigateMixin(PolymerElement) {
|
|||||||
return html`
|
return html`
|
||||||
<app-route
|
<app-route
|
||||||
route="[[route]]"
|
route="[[route]]"
|
||||||
pattern="/users/:user"
|
pattern="/:user"
|
||||||
data="{{_routeData}}"
|
data="{{_routeData}}"
|
||||||
></app-route>
|
></app-route>
|
||||||
|
|
||||||
@ -72,8 +72,6 @@ class HaConfigUsers extends NavigateMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_checkRoute(route) {
|
_checkRoute(route) {
|
||||||
if (!route || route.path.substr(0, 6) !== "/users") return;
|
|
||||||
|
|
||||||
// prevent list getting under toolbar
|
// prevent list getting under toolbar
|
||||||
fireEvent(this, "iron-resize");
|
fireEvent(this, "iron-resize");
|
||||||
|
|
||||||
@ -81,8 +79,8 @@ class HaConfigUsers extends NavigateMixin(PolymerElement) {
|
|||||||
this._debouncer,
|
this._debouncer,
|
||||||
timeOut.after(0),
|
timeOut.after(0),
|
||||||
() => {
|
() => {
|
||||||
if (route.path === "/users") {
|
if (route.path === "") {
|
||||||
this.navigate("/config/users/picker", true);
|
this.navigate(`${route.prefix}/picker`, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -38,7 +38,7 @@ class HaPanelCustom extends NavigateMixin(EventsMixin(PolymerElement)) {
|
|||||||
delete window.customPanel;
|
delete window.customPanel;
|
||||||
this._setProperties = null;
|
this._setProperties = null;
|
||||||
while (this.lastChild) {
|
while (this.lastChild) {
|
||||||
this.remove(this.lastChild);
|
this.removeChild(this.lastChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = panel.config._panel_custom;
|
const config = panel.config._panel_custom;
|
||||||
@ -95,7 +95,7 @@ It will have access to all data in Home Assistant.
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<iframe></iframe>
|
<iframe></iframe>
|
||||||
`;
|
`.trim();
|
||||||
const iframeDoc = this.querySelector("iframe").contentWindow.document;
|
const iframeDoc = this.querySelector("iframe").contentWindow.document;
|
||||||
iframeDoc.open();
|
iframeDoc.open();
|
||||||
iframeDoc.write(`<script src='${window.customPanelJS}'></script>`);
|
iframeDoc.write(`<script src='${window.customPanelJS}'></script>`);
|
||||||
|
6
src/util/init-skeleton.ts
Normal file
6
src/util/init-skeleton.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export const removeInitSkeleton = () => {
|
||||||
|
const initEl = document.getElementById("ha-init-skeleton");
|
||||||
|
if (initEl) {
|
||||||
|
initEl.parentElement!.removeChild(initEl);
|
||||||
|
}
|
||||||
|
};
|
@ -1084,7 +1084,7 @@
|
|||||||
"sun": {
|
"sun": {
|
||||||
"elevation": "Височина",
|
"elevation": "Височина",
|
||||||
"rising": "Изгрев",
|
"rising": "Изгрев",
|
||||||
"setting": "Настройка"
|
"setting": "Залез"
|
||||||
},
|
},
|
||||||
"updater": {
|
"updater": {
|
||||||
"title": "Инструкции за актуализиране"
|
"title": "Инструкции за актуализиране"
|
||||||
|
@ -384,7 +384,7 @@
|
|||||||
"alias": "Назва",
|
"alias": "Назва",
|
||||||
"triggers": {
|
"triggers": {
|
||||||
"header": "Тригери",
|
"header": "Тригери",
|
||||||
"introduction": "Тригери - це те, що починає обробляти правило автоматизації. Можна вказати декілька тригерів для одного і того ж правила. Після запуску тригера, Home Assistant перевірить умови, якщо такі є, і викликає дію. \n\n [Докладніше про тригери.] (Https:\/\/home-assistant.io\/docs\/automation\/trigger\/)",
|
"introduction": "Тригери - це те, що починає обробляти правило автоматизації. Можна вказати декілька тригерів для одного і того ж правила. Після запуску тригера, Home Assistant перевірить умови, якщо такі є, і викликає дію. \n\n [Докладніше про тригери.] (https:\/\/home-assistant.io\/docs\/automation\/trigger\/)",
|
||||||
"add": "Додати тригер",
|
"add": "Додати тригер",
|
||||||
"duplicate": "Дублювати",
|
"duplicate": "Дублювати",
|
||||||
"delete": "Видалити",
|
"delete": "Видалити",
|
||||||
@ -466,7 +466,7 @@
|
|||||||
},
|
},
|
||||||
"conditions": {
|
"conditions": {
|
||||||
"header": "Умови",
|
"header": "Умови",
|
||||||
"introduction": "Умови є необов'язковою частиною правила автоматизації і можуть використовуватися для запобігання дії, що відбувається під час запуску. Умови виглядають дуже схоже на тригери, але вони різні. Тригер буде дивитися на події, що відбуваються в системі, в той час як умова тільки дивиться на те, як система виглядає зараз. Тригер може спостерігати, що перемикач включений. Умова може бачити тільки, якщо перемикач ввімкнено або вимкнено. \n\n [Докладніше про умови.] (Https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)",
|
"introduction": "Умови є необов'язковою частиною правила автоматизації і можуть використовуватися для запобігання дії, що відбувається під час запуску. Умови виглядають дуже схоже на тригери, але вони різні. Тригер буде дивитися на події, що відбуваються в системі, в той час як умова тільки дивиться на те, як система виглядає зараз. Тригер може спостерігати, що перемикач включений. Умова може бачити тільки, якщо перемикач ввімкнено або вимкнено. \n\n [Докладніше про умови.] (https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)",
|
||||||
"add": "Додати умову",
|
"add": "Додати умову",
|
||||||
"duplicate": "Дублювати",
|
"duplicate": "Дублювати",
|
||||||
"delete": "Видалити",
|
"delete": "Видалити",
|
||||||
@ -504,7 +504,7 @@
|
|||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"header": "Дії",
|
"header": "Дії",
|
||||||
"introduction": "Що Home Assistant буде робити, коли автоматизація спрацьовує. \n\n [Докладніше про дії.] (Https:\/\/home-assistant.io\/docs\/automation\/action\/)",
|
"introduction": "Що Home Assistant буде робити, коли автоматизація спрацьовує. \n\n [Докладніше про дії.] (https:\/\/home-assistant.io\/docs\/automation\/action\/)",
|
||||||
"add": "Додати дію",
|
"add": "Додати дію",
|
||||||
"duplicate": "Дублювати",
|
"duplicate": "Дублювати",
|
||||||
"delete": "Видалити",
|
"delete": "Видалити",
|
||||||
@ -513,7 +513,7 @@
|
|||||||
"type_select": "Тип дії",
|
"type_select": "Тип дії",
|
||||||
"type": {
|
"type": {
|
||||||
"service": {
|
"service": {
|
||||||
"label": "Викликати послугу",
|
"label": "Викликати сервіс",
|
||||||
"service_data": "Дані послуги "
|
"service_data": "Дані послуги "
|
||||||
},
|
},
|
||||||
"delay": {
|
"delay": {
|
||||||
@ -807,7 +807,8 @@
|
|||||||
},
|
},
|
||||||
"create_account": "Створити обліковий запис",
|
"create_account": "Створити обліковий запис",
|
||||||
"error": {
|
"error": {
|
||||||
"required_fields": "Заповніть усі необхідні поля"
|
"required_fields": "Заповніть усі необхідні поля",
|
||||||
|
"password_not_match": "Паролі не збігаються"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1129,5 +1130,9 @@
|
|||||||
"auto": "Авто"
|
"auto": "Авто"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"groups": {
|
||||||
|
"system-admin": "Адміністратори",
|
||||||
|
"system-users": "Користувачі"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user