Add developer tools panel (#3313)

This commit is contained in:
Paulus Schoutsen 2019-06-28 08:34:29 -07:00 committed by GitHub
parent 618d25ce48
commit 58e6be12af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 710 additions and 675 deletions

View File

@ -22,6 +22,7 @@ const BUILT_IN_PANEL_ICONS = [
"mailbox", // Mailbox
"tooltip-account", // Map
"cart", // Shopping List
"hammer", // developer-tools
];
// Given an icon name, load the SVG file

View File

@ -14,7 +14,6 @@ import "@polymer/paper-listbox/paper-listbox";
import "./ha-icon";
import "../components/user/ha-user-badge";
import isComponentLoaded from "../common/config/is_component_loaded";
import { HomeAssistant, PanelInfo } from "../types";
import { fireEvent } from "../common/dom/fire_event";
import { DEFAULT_PANEL } from "../common/const";
@ -23,29 +22,24 @@ import {
ExternalConfig,
} from "../external_app/external_config";
const SHOW_AFTER_SPACER = ["config", "developer-tools"];
const computeUrl = (urlPath) => `/${urlPath}`;
const computePanels = (hass: HomeAssistant) => {
const panels = hass.panels;
if (!panels) {
return [];
}
const sortValue = {
const SORT_VALUE = {
map: 1,
logbook: 2,
history: 3,
};
const result: PanelInfo[] = Object.values(panels).filter(
(panel) => panel.title
);
"developer-tools": 9,
configuration: 10,
};
result.sort((a, b) => {
const aBuiltIn = a.component_name in sortValue;
const bBuiltIn = b.component_name in sortValue;
const panelSorter = (a, b) => {
const aBuiltIn = a.component_name in SORT_VALUE;
const bBuiltIn = b.component_name in SORT_VALUE;
if (aBuiltIn && bBuiltIn) {
return sortValue[a.component_name] - sortValue[b.component_name];
return SORT_VALUE[a.component_name] - SORT_VALUE[b.component_name];
}
if (aBuiltIn) {
return -1;
@ -61,9 +55,31 @@ const computePanels = (hass: HomeAssistant) => {
return 1;
}
return 0;
};
const computePanels = (hass: HomeAssistant): [PanelInfo[], PanelInfo[]] => {
const panels = hass.panels;
if (!panels) {
return [[], []];
}
const beforeSpacer: PanelInfo[] = [];
const afterSpacer: PanelInfo[] = [];
Object.values(panels).forEach((panel) => {
if (!panel.title) {
return;
}
(SHOW_AFTER_SPACER.includes(panel.component_name)
? afterSpacer
: beforeSpacer
).push(panel);
});
return result;
beforeSpacer.sort(panelSorter);
afterSpacer.sort(panelSorter);
return [beforeSpacer, afterSpacer];
};
const renderPanel = (hass, panel) => html`
@ -100,12 +116,7 @@ class HaSidebar extends LitElement {
return html``;
}
const panels = computePanels(hass);
const configPanelIdx = panels.findIndex(
(panel) => panel.component_name === "config"
);
const configPanel =
configPanelIdx === -1 ? undefined : panels.splice(configPanelIdx, 1)[0];
const [beforeSpacer, afterSpacer] = computePanels(hass);
return html`
${this.expanded
@ -137,69 +148,11 @@ class HaSidebar extends LitElement {
</paper-icon-item>
</a>
${panels.map((panel) => renderPanel(hass, panel))}
${beforeSpacer.map((panel) => renderPanel(hass, panel))}
<div class="spacer" disabled></div>
${this.expanded && hass.user && hass.user.is_admin
? html`
<div class="divider" disabled></div>
<div class="subheader" disabled>
${hass.localize("ui.sidebar.developer_tools")}
</div>
<div class="dev-tools" disabled>
<a href="/dev-service" tabindex="-1">
<paper-icon-button
icon="hass:remote"
alt="${hass.localize("panel.dev-services")}"
title="${hass.localize("panel.dev-services")}"
></paper-icon-button>
</a>
<a href="/dev-state" tabindex="-1">
<paper-icon-button
icon="hass:code-tags"
alt="${hass.localize("panel.dev-states")}"
title="${hass.localize("panel.dev-states")}"
></paper-icon-button>
</a>
<a href="/dev-event" tabindex="-1">
<paper-icon-button
icon="hass:radio-tower"
alt="${hass.localize("panel.dev-events")}"
title="${hass.localize("panel.dev-events")}"
></paper-icon-button>
</a>
<a href="/dev-template" tabindex="-1">
<paper-icon-button
icon="hass:file-xml"
alt="${hass.localize("panel.dev-templates")}"
title="${hass.localize("panel.dev-templates")}"
></paper-icon-button>
</a>
${isComponentLoaded(hass, "mqtt")
? html`
<a href="/dev-mqtt" tabindex="-1">
<paper-icon-button
icon="hass:altimeter"
alt="${hass.localize("panel.dev-mqtt")}"
title="${hass.localize("panel.dev-mqtt")}"
></paper-icon-button>
</a>
`
: html``}
<a href="/dev-info" tabindex="-1">
<paper-icon-button
icon="hass:information-outline"
alt="${hass.localize("panel.dev-info")}"
title="${hass.localize("panel.dev-info")}"
></paper-icon-button>
</a>
</div>
<div class="divider" disabled></div>
`
: ""}
${afterSpacer.map((panel) => renderPanel(hass, panel))}
${this._externalConfig && this._externalConfig.hasSettingsScreen
? html`
<a
@ -223,7 +176,6 @@ class HaSidebar extends LitElement {
</a>
`
: ""}
${configPanel ? renderPanel(hass, configPanel) : ""}
${hass.user
? html`
<a
@ -280,7 +232,6 @@ class HaSidebar extends LitElement {
return (
hass.panels !== oldHass.panels ||
hass.panelUrl !== oldHass.panelUrl ||
hass.config.components !== oldHass.config.components ||
hass.user !== oldHass.user ||
hass.localize !== oldHass.localize
);
@ -458,12 +409,6 @@ class HaSidebar extends LitElement {
pointer-events: none;
}
.divider {
height: 1px;
background-color: var(--divider-color);
margin: 4px 0;
}
.subheader {
color: var(--sidebar-text-color);
font-weight: 500;

View File

@ -9,7 +9,7 @@ import {
} from "./hass-router-page";
import { removeInitSkeleton } from "../util/init-skeleton";
const CACHE_COMPONENTS = ["lovelace", "states"];
const CACHE_COMPONENTS = ["lovelace", "states", "developer-tools"];
const COMPONENTS = {
calendar: () =>
import(/* webpackChunkName: "panel-calendar" */ "../panels/calendar/ha-panel-calendar"),
@ -17,18 +17,8 @@ const COMPONENTS = {
import(/* webpackChunkName: "panel-config" */ "../panels/config/ha-panel-config"),
custom: () =>
import(/* webpackChunkName: "panel-custom" */ "../panels/custom/ha-panel-custom"),
"dev-event": () =>
import(/* webpackChunkName: "panel-dev-event" */ "../panels/dev-event/ha-panel-dev-event"),
"dev-info": () =>
import(/* webpackChunkName: "panel-dev-info" */ "../panels/dev-info/ha-panel-dev-info"),
"dev-mqtt": () =>
import(/* webpackChunkName: "panel-dev-mqtt" */ "../panels/dev-mqtt/ha-panel-dev-mqtt"),
"dev-service": () =>
import(/* webpackChunkName: "panel-dev-service" */ "../panels/dev-service/ha-panel-dev-service"),
"dev-state": () =>
import(/* webpackChunkName: "panel-dev-state" */ "../panels/dev-state/ha-panel-dev-state"),
"dev-template": () =>
import(/* webpackChunkName: "panel-dev-template" */ "../panels/dev-template/ha-panel-dev-template"),
"developer-tools": () =>
import(/* webpackChunkName: "panel-developer-tools" */ "../panels/developer-tools/ha-panel-developer-tools"),
lovelace: () =>
import(/* webpackChunkName: "panel-lovelace" */ "../panels/lovelace/ha-panel-lovelace"),
states: () =>
@ -52,14 +42,17 @@ const COMPONENTS = {
};
const getRoutes = (panels: Panels): RouterOptions => {
const routes: { [route: string]: RouteOptions } = {};
const routes: RouterOptions["routes"] = {};
Object.values(panels).forEach((panel) => {
routes[panel.url_path] = {
load: COMPONENTS[panel.component_name],
const data: RouteOptions = {
tag: `ha-panel-${panel.component_name}`,
cache: CACHE_COMPONENTS.includes(panel.component_name),
};
if (panel.component_name in COMPONENTS) {
data.load = COMPONENTS[panel.component_name];
}
routes[panel.url_path] = data;
});
return {

View File

@ -1,221 +0,0 @@
import {
LitElement,
html,
PropertyDeclarations,
CSSResult,
css,
TemplateResult,
} from "lit-element";
import "@polymer/app-layout/app-header-layout/app-header-layout";
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "../../components/ha-menu-button";
import { HomeAssistant } from "../../types";
import { haStyle } from "../../resources/styles";
import "./system-log-card";
import "./error-log-card";
import "./system-health-card";
const JS_VERSION = __BUILD__;
const OPT_IN_PANEL = "states";
class HaPanelDevInfo extends LitElement {
public hass?: HomeAssistant;
static get properties(): PropertyDeclarations {
return {
hass: {},
};
}
protected render(): TemplateResult | void {
const hass = this.hass;
if (!hass) {
return html``;
}
const customUiList: Array<{ name: string; url: string; version: string }> =
(window as any).CUSTOM_UI_LIST || [];
const nonDefaultLink =
localStorage.defaultPage === OPT_IN_PANEL && OPT_IN_PANEL === "states"
? "/lovelace"
: "/states";
const nonDefaultLinkText =
localStorage.defaultPage === OPT_IN_PANEL && OPT_IN_PANEL === "states"
? "Go to the Lovelace UI"
: "Go to the states UI";
const defaultPageText = `${
localStorage.defaultPage === OPT_IN_PANEL ? "Remove" : "Set"
} ${OPT_IN_PANEL} as default page on this device`;
return html`
<app-header-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<ha-menu-button></ha-menu-button>
<div main-title>About</div>
</app-toolbar>
</app-header>
<div class="content">
<div class="about">
<p class="version">
<a href="https://www.home-assistant.io" target="_blank">
<img
src="/static/icons/favicon-192x192.png"
height="192"
alt="Home Assistant logo"
/>
</a>
<br />
Home Assistant<br />
${hass.config.version}
</p>
<p>
Path to configuration.yaml: ${hass.config.config_dir}
</p>
<p class="develop">
<a
href="https://www.home-assistant.io/developers/credits/"
target="_blank"
>
Developed by a bunch of awesome people.
</a>
</p>
<p>
Published under the Apache 2.0 license<br />
Source:
<a
href="https://github.com/home-assistant/home-assistant"
target="_blank"
>server</a
>
&mdash;
<a
href="https://github.com/home-assistant/home-assistant-polymer"
target="_blank"
>frontend-ui</a
>
</p>
<p>
Built using
<a href="https://www.python.org">Python 3</a>,
<a href="https://www.polymer-project.org" target="_blank"
>Polymer</a
>, Icons by
<a href="https://www.google.com/design/icons/" target="_blank"
>Google</a
>
and
<a href="https://MaterialDesignIcons.com" target="_blank"
>MaterialDesignIcons.com</a
>.
</p>
<p>
Frontend JavaScript version: ${JS_VERSION}
${customUiList.length > 0
? html`
<div>
Custom UIs:
${customUiList.map(
(item) => html`
<div>
<a href="${item.url}" target="_blank">
${item.name}</a
>: ${item.version}
</div>
`
)}
</div>
`
: ""}
</p>
<p>
<a href="${nonDefaultLink}">${nonDefaultLinkText}</a><br />
<mwc-button @click="${this._toggleDefaultPage}" raised>
${defaultPageText}
</mwc-button>
</p>
</div>
<system-health-card .hass=${this.hass}></system-health-card>
<system-log-card .hass=${this.hass}></system-log-card>
<error-log-card .hass=${this.hass}></error-log-card>
</div>
</app-header-layout>
`;
}
protected firstUpdated(changedProps): void {
super.firstUpdated(changedProps);
// Legacy custom UI can be slow to register, give them time.
const customUI = ((window as any).CUSTOM_UI_LIST || []).length;
setTimeout(() => {
if (((window as any).CUSTOM_UI_LIST || []).length !== customUI.length) {
this.requestUpdate();
}
}, 1000);
}
protected _toggleDefaultPage(): void {
if (localStorage.defaultPage === OPT_IN_PANEL) {
delete localStorage.defaultPage;
} else {
localStorage.defaultPage = OPT_IN_PANEL;
}
this.requestUpdate();
}
static get styles(): CSSResult[] {
return [
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
}
.content {
padding: 16px 0px 16px 0;
direction: ltr;
}
.about {
text-align: center;
line-height: 2em;
}
.version {
@apply --paper-font-headline;
}
.develop {
@apply --paper-font-subhead;
}
.about a {
color: var(--dark-primary-color);
}
system-health-card {
display: block;
max-width: 600px;
margin: 0 auto;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-panel-dev-info": HaPanelDevInfo;
}
}
customElements.define("ha-panel-dev-info", HaPanelDevInfo);

View File

@ -0,0 +1,68 @@
import { HassRouterPage, RouterOptions } from "../../layouts/hass-router-page";
import { customElement, property } from "lit-element";
import { PolymerElement } from "@polymer/polymer";
import { HomeAssistant } from "../../types";
@customElement("developer-tools-router")
class DeveloperToolsRouter extends HassRouterPage {
@property() public hass!: HomeAssistant;
@property() public narrow!: boolean;
protected routerOptions: RouterOptions = {
// defaultPage: "info",
beforeRender: (page) => {
if (!page || page === "not_found") {
// If we can, we are going to restore the last visited page.
return this._currentPage ? this._currentPage : "info";
}
return undefined;
},
cacheAll: true,
showLoading: true,
routes: {
event: {
tag: "developer-tools-event",
load: () => import("./event/developer-tools-event"),
},
info: {
tag: "developer-tools-info",
load: () => import("./info/developer-tools-info"),
},
mqtt: {
tag: "developer-tools-mqtt",
load: () => import("./mqtt/developer-tools-mqtt"),
},
service: {
tag: "developer-tools-service",
load: () => import("./service/developer-tools-service"),
},
state: {
tag: "developer-tools-state",
load: () => import("./state/developer-tools-state"),
},
template: {
tag: "developer-tools-template",
load: () => import("./template/developer-tools-template"),
},
},
};
protected updatePageEl(el) {
if ("setProperties" in el) {
// As long as we have Polymer pages
(el as PolymerElement).setProperties({
hass: this.hass,
narrow: this.narrow,
});
} else {
el.hass = this.hass;
el.narrow = this.narrow;
}
}
}
declare global {
interface HTMLElementTagNameMap {
"developer-tools-router": DeveloperToolsRouter;
}
}

View File

@ -1,6 +1,3 @@
import "@polymer/app-layout/app-header-layout/app-header-layout";
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
import "@material/mwc-button";
import "@polymer/paper-input/paper-input";
@ -8,11 +5,10 @@ import "@polymer/paper-input/paper-textarea";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../components/ha-menu-button";
import "../../resources/ha-style";
import "../../../resources/ha-style";
import "./events-list";
import "./event-subscribe-card";
import { EventsMixin } from "../../mixins/events-mixin";
import { EventsMixin } from "../../../mixins/events-mixin";
/*
* @appliesMixin EventsMixin
@ -26,12 +22,10 @@ class HaPanelDevEvent extends EventsMixin(PolymerElement) {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
}
.content {
@apply --paper-font-body1;
padding: 16px;
direction: ltr;
display: block;
}
.ha-form {
@ -49,15 +43,6 @@ class HaPanelDevEvent extends EventsMixin(PolymerElement) {
}
</style>
<app-header-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<ha-menu-button></ha-menu-button>
<div main-title>Events</div>
</app-toolbar>
</app-header>
<div class="content">
<div class$="[[computeFormClasses(narrow)]]">
<div class="flex">
<p>Fire an event on the event bus.</p>
@ -86,8 +71,6 @@ class HaPanelDevEvent extends EventsMixin(PolymerElement) {
</div>
</div>
<event-subscribe-card hass="[[hass]]"></event-subscribe-card>
</div>
</app-header-layout>
`;
}
@ -139,4 +122,4 @@ class HaPanelDevEvent extends EventsMixin(PolymerElement) {
}
}
customElements.define("ha-panel-dev-event", HaPanelDevEvent);
customElements.define("developer-tools-event", HaPanelDevEvent);

View File

@ -10,10 +10,10 @@ import {
import "@material/mwc-button";
import "@polymer/paper-input/paper-input";
import { HassEvent } from "home-assistant-js-websocket";
import { HomeAssistant } from "../../types";
import { PolymerChangedEvent } from "../../polymer-types";
import "../../components/ha-card";
import format_time from "../../common/datetime/format_time";
import { HomeAssistant } from "../../../types";
import { PolymerChangedEvent } from "../../../polymer-types";
import "../../../components/ha-card";
import format_time from "../../../common/datetime/format_time";
@customElement("event-subscribe-card")
class EventSubscribeCard extends LitElement {

View File

@ -1,7 +1,7 @@
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import { EventsMixin } from "../../mixins/events-mixin";
import { EventsMixin } from "../../../mixins/events-mixin";
/*
* @appliesMixin EventsMixin

View File

@ -0,0 +1,121 @@
import {
LitElement,
TemplateResult,
html,
CSSResultArray,
css,
customElement,
property,
} from "lit-element";
import "@polymer/app-layout/app-header-layout/app-header-layout";
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@polymer/paper-icon-button/paper-icon-button";
import "@polymer/paper-tabs/paper-tab";
import "@polymer/paper-tabs/paper-tabs";
import "../../components/ha-menu-button";
import "../../resources/ha-style";
import "./developer-tools-router";
import scrollToTarget from "../../common/dom/scroll-to-target";
import { haStyle } from "../../resources/styles";
import { HomeAssistant, Route } from "../../types";
import { navigate } from "../../common/navigate";
import isComponentLoaded from "../../common/config/is_component_loaded";
@customElement("ha-panel-developer-tools")
class PanelDeveloperTools extends LitElement {
@property() public hass!: HomeAssistant;
@property() public route!: Route;
@property() public narrow!: boolean;
protected render(): TemplateResult | void {
const page = this._page;
return html`
<app-header-layout has-scrolling-region>
<app-header fixed slot="header">
<app-toolbar>
<ha-menu-button></ha-menu-button>
<div main-title>Developer Tools</div>
</app-toolbar>
<paper-tabs
scrollable
attr-for-selected="page-name"
.selected=${page}
@iron-activate=${this.handlePageSelected}
>
<paper-tab page-name="info">
${this.hass.localize("panel.dev-info")}
</paper-tab>
<paper-tab page-name="event">
${this.hass.localize("panel.dev-events")}
</paper-tab>
${isComponentLoaded(this.hass, "mqtt")
? html`
<paper-tab page-name="mqtt">
${this.hass.localize("panel.dev-mqtt")}
</paper-tab>
`
: ""}
<paper-tab page-name="service">
${this.hass.localize("panel.dev-services")}
</paper-tab>
<paper-tab page-name="state">
${this.hass.localize("panel.dev-states")}
</paper-tab>
<paper-tab page-name="template">
${this.hass.localize("panel.dev-templates")}
</paper-tab>
</paper-tabs>
</app-header>
<developer-tools-router
.route=${this.route}
.narrow=${this.narrow}
.hass=${this.hass}
></developer-tools-router>
</app-header-layout>
`;
}
private handlePageSelected(ev) {
const newPage = ev.detail.item.getAttribute("page-name");
if (newPage !== this._page) {
navigate(this, `/developer-tools/${newPage}`);
}
scrollToTarget(
this,
// @ts-ignore
this.shadowRoot!.querySelector("app-header-layout").header.scrollTarget
);
}
private get _page() {
return this.route.path.substr(1);
}
static get styles(): CSSResultArray {
return [
haStyle,
css`
:host {
color: var(--primary-text-color);
--paper-card-header-color: var(--primary-text-color);
}
paper-tabs {
margin-left: 12px;
--paper-tabs-selection-bar-color: #fff;
text-transform: uppercase;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-panel-developer-tools": PanelDeveloperTools;
}
}

View File

@ -0,0 +1,194 @@
import {
LitElement,
html,
CSSResult,
css,
TemplateResult,
property,
} from "lit-element";
import { HomeAssistant } from "../../../types";
import { haStyle } from "../../../resources/styles";
import "./system-log-card";
import "./error-log-card";
import "./system-health-card";
const JS_VERSION = __BUILD__;
const OPT_IN_PANEL = "states";
class HaPanelDevInfo extends LitElement {
@property() public hass!: HomeAssistant;
protected render(): TemplateResult | void {
const hass = this.hass;
const customUiList: Array<{ name: string; url: string; version: string }> =
(window as any).CUSTOM_UI_LIST || [];
const nonDefaultLink =
localStorage.defaultPage === OPT_IN_PANEL && OPT_IN_PANEL === "states"
? "/lovelace"
: "/states";
const nonDefaultLinkText =
localStorage.defaultPage === OPT_IN_PANEL && OPT_IN_PANEL === "states"
? "Go to the Lovelace UI"
: "Go to the states UI";
const defaultPageText = `${
localStorage.defaultPage === OPT_IN_PANEL ? "Remove" : "Set"
} ${OPT_IN_PANEL} as default page on this device`;
return html`
<div class="about">
<p class="version">
<a href="https://www.home-assistant.io" target="_blank"
><img
src="/static/icons/favicon-192x192.png"
height="192"
alt="Home Assistant logo"
/></a>
<br />
Home Assistant<br />
${hass.config.version}
</p>
<p>
Path to configuration.yaml: ${hass.config.config_dir}
</p>
<p class="develop">
<a
href="https://www.home-assistant.io/developers/credits/"
target="_blank"
>
Developed by a bunch of awesome people.
</a>
</p>
<p>
Published under the Apache 2.0 license<br />
Source:
<a
href="https://github.com/home-assistant/home-assistant"
target="_blank"
>server</a
>
&mdash;
<a
href="https://github.com/home-assistant/home-assistant-polymer"
target="_blank"
>frontend-ui</a
>
</p>
<p>
Built using
<a href="https://www.python.org">Python 3</a>,
<a href="https://www.polymer-project.org" target="_blank">Polymer</a>,
Icons by
<a href="https://www.google.com/design/icons/" target="_blank"
>Google</a
>
and
<a href="https://MaterialDesignIcons.com" target="_blank"
>MaterialDesignIcons.com</a
>.
</p>
<p>
Frontend JavaScript version: ${JS_VERSION}
${customUiList.length > 0
? html`
<div>
Custom UIs:
${customUiList.map(
(item) => html`
<div>
<a href="${item.url}" target="_blank"> ${item.name}</a>:
${item.version}
</div>
`
)}
</div>
`
: ""}
</p>
<p>
<a href="${nonDefaultLink}">${nonDefaultLinkText}</a><br />
<mwc-button @click="${this._toggleDefaultPage}" raised>
${defaultPageText}
</mwc-button>
</p>
</div>
<system-health-card .hass=${this.hass}></system-health-card>
<system-log-card .hass=${this.hass}></system-log-card>
<error-log-card .hass=${this.hass}></error-log-card>
`;
}
protected firstUpdated(changedProps): void {
super.firstUpdated(changedProps);
// Legacy custom UI can be slow to register, give them time.
const customUI = ((window as any).CUSTOM_UI_LIST || []).length;
setTimeout(() => {
if (((window as any).CUSTOM_UI_LIST || []).length !== customUI.length) {
this.requestUpdate();
}
}, 1000);
}
protected _toggleDefaultPage(): void {
if (localStorage.defaultPage === OPT_IN_PANEL) {
delete localStorage.defaultPage;
} else {
localStorage.defaultPage = OPT_IN_PANEL;
}
this.requestUpdate();
}
static get styles(): CSSResult[] {
return [
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
}
.content {
padding: 16px 0px 16px 0;
direction: ltr;
}
.about {
text-align: center;
line-height: 2em;
}
.version {
@apply --paper-font-headline;
}
.develop {
@apply --paper-font-subhead;
}
.about a {
color: var(--dark-primary-color);
}
system-health-card {
display: block;
max-width: 600px;
margin: 0 auto;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"developer-tools-info": HaPanelDevInfo;
}
}
customElements.define("developer-tools-info", HaPanelDevInfo);

View File

@ -8,11 +8,11 @@ import {
} from "lit-element";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
import "../../components/dialog/ha-paper-dialog";
import "../../../components/dialog/ha-paper-dialog";
import { SystemLogDetailDialogParams } from "./show-dialog-system-log-detail";
import { PolymerChangedEvent } from "../../polymer-types";
import { haStyleDialog } from "../../resources/styles";
import { PolymerChangedEvent } from "../../../polymer-types";
import { haStyleDialog } from "../../../resources/styles";
class DialogSystemLogDetail extends LitElement {
private _params?: SystemLogDetailDialogParams;

View File

@ -9,8 +9,8 @@ import {
import "@polymer/paper-icon-button/paper-icon-button";
import "@material/mwc-button";
import { HomeAssistant } from "../../types";
import { fetchErrorLog } from "../../data/error_log";
import { HomeAssistant } from "../../../types";
import { fetchErrorLog } from "../../../data/error_log";
class ErrorLogCard extends LitElement {
public hass?: HomeAssistant;

View File

@ -1,5 +1,5 @@
import { fireEvent } from "../../common/dom/fire_event";
import { LoggedError } from "../../data/system_log";
import { fireEvent } from "../../../common/dom/fire_event";
import { LoggedError } from "../../../data/system_log";
declare global {
// for fire event

View File

@ -7,13 +7,13 @@ import {
TemplateResult,
} from "lit-element";
import "@polymer/paper-spinner/paper-spinner";
import "../../components/ha-card";
import "../../../components/ha-card";
import { HomeAssistant } from "../../types";
import { HomeAssistant } from "../../../types";
import {
SystemHealthInfo,
fetchSystemHealthInfo,
} from "../../data/system_health";
} from "../../../data/system_health";
const sortKeys = (a: string, b: string) => {
if (a === "homeassistant") {

View File

@ -10,13 +10,13 @@ import "@polymer/paper-icon-button/paper-icon-button";
import "@polymer/paper-item/paper-item-body";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-spinner/paper-spinner";
import "../../components/ha-card";
import "../../components/buttons/ha-call-service-button";
import "../../components/buttons/ha-progress-button";
import { HomeAssistant } from "../../types";
import { LoggedError, fetchSystemLog } from "../../data/system_log";
import formatDateTime from "../../common/datetime/format_date_time";
import formatTime from "../../common/datetime/format_time";
import "../../../components/ha-card";
import "../../../components/buttons/ha-call-service-button";
import "../../../components/buttons/ha-progress-button";
import { HomeAssistant } from "../../../types";
import { LoggedError, fetchSystemLog } from "../../../data/system_log";
import formatDateTime from "../../../common/datetime/format_date_time";
import formatTime from "../../../common/datetime/format_time";
import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail";
const formatLogTime = (date, language: string) => {

View File

@ -7,10 +7,10 @@ import "@polymer/paper-input/paper-textarea";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../components/ha-card";
import "../../components/ha-menu-button";
import "../../resources/ha-style";
import "../../util/app-localstorage-document";
import "../../../components/ha-card";
import "../../../components/ha-menu-button";
import "../../../resources/ha-style";
import "../../../util/app-localstorage-document";
class HaPanelDevMqtt extends PolymerElement {
static get template() {
@ -86,4 +86,4 @@ class HaPanelDevMqtt extends PolymerElement {
}
}
customElements.define("ha-panel-dev-mqtt", HaPanelDevMqtt);
customElements.define("developer-tools-mqtt", HaPanelDevMqtt);

View File

@ -1,17 +1,13 @@
import "@polymer/app-layout/app-header-layout/app-header-layout";
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@material/mwc-button";
import "@polymer/paper-input/paper-textarea";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import { ENTITY_COMPONENT_DOMAINS } from "../../data/entity";
import "../../components/entity/ha-entity-picker";
import "../../components/ha-menu-button";
import "../../components/ha-service-picker";
import "../../resources/ha-style";
import "../../util/app-localstorage-document";
import { ENTITY_COMPONENT_DOMAINS } from "../../../data/entity";
import "../../../components/entity/ha-entity-picker";
import "../../../components/ha-service-picker";
import "../../../resources/ha-style";
import "../../../util/app-localstorage-document";
const ERROR_SENTINEL = {};
class HaPanelDevService extends PolymerElement {
@ -22,9 +18,7 @@ class HaPanelDevService extends PolymerElement {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
}
.content {
display: block;
padding: 16px;
direction: ltr;
}
@ -81,14 +75,6 @@ class HaPanelDevService extends PolymerElement {
}
</style>
<app-header-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<ha-menu-button></ha-menu-button>
<div main-title>Services</div>
</app-toolbar>
</app-header>
<app-localstorage-document
key="panel-dev-service-state-domain-service"
data="{{domainService}}"
@ -102,8 +88,8 @@ class HaPanelDevService extends PolymerElement {
<div class="content">
<p>
The service dev tool allows you to call any available service in
Home Assistant.
The service dev tool allows you to call any available service in Home
Assistant.
</p>
<div class="ha-form">
@ -159,11 +145,7 @@ class HaPanelDevService extends PolymerElement {
<td colspan="3">This service takes no parameters.</td>
</tr>
</template>
<template
is="dom-repeat"
items="[[_attributes]]"
as="attribute"
>
<template is="dom-repeat" items="[[_attributes]]" as="attribute">
<tr>
<td><pre>[[attribute.key]]</pre></td>
<td>[[attribute.description]]</td>
@ -174,7 +156,6 @@ class HaPanelDevService extends PolymerElement {
</template>
</template>
</div>
</app-header-layout>
`;
}
@ -304,4 +285,4 @@ class HaPanelDevService extends PolymerElement {
}
}
customElements.define("ha-panel-dev-service", HaPanelDevService);
customElements.define("developer-tools-service", HaPanelDevService);

View File

@ -1,6 +1,3 @@
import "@polymer/app-layout/app-header-layout/app-header-layout";
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@material/mwc-button";
import "@polymer/paper-checkbox/paper-checkbox";
import "@polymer/paper-input/paper-input";
@ -8,10 +5,9 @@ import "@polymer/paper-input/paper-textarea";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../components/entity/ha-entity-picker";
import "../../components/ha-menu-button";
import "../../resources/ha-style";
import { EventsMixin } from "../../mixins/events-mixin";
import "../../../components/entity/ha-entity-picker";
import "../../../resources/ha-style";
import { EventsMixin } from "../../../mixins/events-mixin";
/*
* @appliesMixin EventsMixin
@ -24,9 +20,7 @@ class HaPanelDevState extends EventsMixin(PolymerElement) {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
}
.content {
display: block;
padding: 16px;
direction: ltr;
}
@ -70,15 +64,6 @@ class HaPanelDevState extends EventsMixin(PolymerElement) {
}
</style>
<app-header-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<ha-menu-button></ha-menu-button>
<div main-title>States</div>
</app-toolbar>
</app-header>
<div class="content">
<div>
<p>
Set the representation of a device within Home Assistant.<br />
@ -169,8 +154,6 @@ class HaPanelDevState extends EventsMixin(PolymerElement) {
</tr>
</template>
</table>
</div>
</app-header-layout>
`;
}
@ -351,4 +334,4 @@ class HaPanelDevState extends EventsMixin(PolymerElement) {
}
}
customElements.define("ha-panel-dev-state", HaPanelDevState);
customElements.define("developer-tools-state", HaPanelDevState);

View File

@ -1,6 +1,3 @@
import "@polymer/app-layout/app-header-layout/app-header-layout";
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@polymer/paper-input/paper-textarea";
import "@polymer/paper-spinner/paper-spinner";
import { timeOut } from "@polymer/polymer/lib/utils/async";
@ -8,8 +5,7 @@ import { Debouncer } from "@polymer/polymer/lib/utils/debounce";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../components/ha-menu-button";
import "../../resources/ha-style";
import "../../../resources/ha-style";
class HaPanelDevTemplate extends PolymerElement {
static get template() {
@ -67,14 +63,6 @@ class HaPanelDevTemplate extends PolymerElement {
}
</style>
<app-header-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<ha-menu-button></ha-menu-button>
<div main-title>Templates</div>
</app-toolbar>
</app-header>
<div class$="[[computeFormClasses(narrow)]]">
<div class="edit-pane">
<p>
@ -112,7 +100,6 @@ class HaPanelDevTemplate extends PolymerElement {
<pre class$="[[computeRenderedClasses(error)]]">[[processed]]</pre>
</div>
</div>
</app-header-layout>
`;
}
@ -207,4 +194,4 @@ For loop example:
}
}
customElements.define("ha-panel-dev-template", HaPanelDevTemplate);
customElements.define("developer-tools-template", HaPanelDevTemplate);