mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-10 19:06:36 +00:00
Add developer tools panel (#3313)
This commit is contained in:
parent
618d25ce48
commit
58e6be12af
@ -22,6 +22,7 @@ const BUILT_IN_PANEL_ICONS = [
|
|||||||
"mailbox", // Mailbox
|
"mailbox", // Mailbox
|
||||||
"tooltip-account", // Map
|
"tooltip-account", // Map
|
||||||
"cart", // Shopping List
|
"cart", // Shopping List
|
||||||
|
"hammer", // developer-tools
|
||||||
];
|
];
|
||||||
|
|
||||||
// Given an icon name, load the SVG file
|
// Given an icon name, load the SVG file
|
||||||
|
@ -14,7 +14,6 @@ import "@polymer/paper-listbox/paper-listbox";
|
|||||||
import "./ha-icon";
|
import "./ha-icon";
|
||||||
|
|
||||||
import "../components/user/ha-user-badge";
|
import "../components/user/ha-user-badge";
|
||||||
import isComponentLoaded from "../common/config/is_component_loaded";
|
|
||||||
import { HomeAssistant, PanelInfo } from "../types";
|
import { HomeAssistant, PanelInfo } from "../types";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { DEFAULT_PANEL } from "../common/const";
|
import { DEFAULT_PANEL } from "../common/const";
|
||||||
@ -23,47 +22,64 @@ import {
|
|||||||
ExternalConfig,
|
ExternalConfig,
|
||||||
} from "../external_app/external_config";
|
} from "../external_app/external_config";
|
||||||
|
|
||||||
|
const SHOW_AFTER_SPACER = ["config", "developer-tools"];
|
||||||
|
|
||||||
const computeUrl = (urlPath) => `/${urlPath}`;
|
const computeUrl = (urlPath) => `/${urlPath}`;
|
||||||
|
|
||||||
const computePanels = (hass: HomeAssistant) => {
|
const SORT_VALUE = {
|
||||||
|
map: 1,
|
||||||
|
logbook: 2,
|
||||||
|
history: 3,
|
||||||
|
"developer-tools": 9,
|
||||||
|
configuration: 10,
|
||||||
|
};
|
||||||
|
|
||||||
|
const panelSorter = (a, b) => {
|
||||||
|
const aBuiltIn = a.component_name in SORT_VALUE;
|
||||||
|
const bBuiltIn = b.component_name in SORT_VALUE;
|
||||||
|
|
||||||
|
if (aBuiltIn && bBuiltIn) {
|
||||||
|
return SORT_VALUE[a.component_name] - SORT_VALUE[b.component_name];
|
||||||
|
}
|
||||||
|
if (aBuiltIn) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bBuiltIn) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// both not built in, sort by title
|
||||||
|
if (a.title! < b.title!) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a.title! > b.title!) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const computePanels = (hass: HomeAssistant): [PanelInfo[], PanelInfo[]] => {
|
||||||
const panels = hass.panels;
|
const panels = hass.panels;
|
||||||
if (!panels) {
|
if (!panels) {
|
||||||
return [];
|
return [[], []];
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortValue = {
|
const beforeSpacer: PanelInfo[] = [];
|
||||||
map: 1,
|
const afterSpacer: PanelInfo[] = [];
|
||||||
logbook: 2,
|
|
||||||
history: 3,
|
|
||||||
};
|
|
||||||
const result: PanelInfo[] = Object.values(panels).filter(
|
|
||||||
(panel) => panel.title
|
|
||||||
);
|
|
||||||
|
|
||||||
result.sort((a, b) => {
|
Object.values(panels).forEach((panel) => {
|
||||||
const aBuiltIn = a.component_name in sortValue;
|
if (!panel.title) {
|
||||||
const bBuiltIn = b.component_name in sortValue;
|
return;
|
||||||
|
|
||||||
if (aBuiltIn && bBuiltIn) {
|
|
||||||
return sortValue[a.component_name] - sortValue[b.component_name];
|
|
||||||
}
|
}
|
||||||
if (aBuiltIn) {
|
(SHOW_AFTER_SPACER.includes(panel.component_name)
|
||||||
return -1;
|
? afterSpacer
|
||||||
}
|
: beforeSpacer
|
||||||
if (bBuiltIn) {
|
).push(panel);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// both not built in, sort by title
|
|
||||||
if (a.title! < b.title!) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (a.title! > b.title!) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
beforeSpacer.sort(panelSorter);
|
||||||
|
afterSpacer.sort(panelSorter);
|
||||||
|
|
||||||
|
return [beforeSpacer, afterSpacer];
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderPanel = (hass, panel) => html`
|
const renderPanel = (hass, panel) => html`
|
||||||
@ -100,12 +116,7 @@ class HaSidebar extends LitElement {
|
|||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
const panels = computePanels(hass);
|
const [beforeSpacer, afterSpacer] = computePanels(hass);
|
||||||
const configPanelIdx = panels.findIndex(
|
|
||||||
(panel) => panel.component_name === "config"
|
|
||||||
);
|
|
||||||
const configPanel =
|
|
||||||
configPanelIdx === -1 ? undefined : panels.splice(configPanelIdx, 1)[0];
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
${this.expanded
|
${this.expanded
|
||||||
@ -137,69 +148,11 @@ class HaSidebar extends LitElement {
|
|||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
${panels.map((panel) => renderPanel(hass, panel))}
|
${beforeSpacer.map((panel) => renderPanel(hass, panel))}
|
||||||
|
|
||||||
<div class="spacer" disabled></div>
|
<div class="spacer" disabled></div>
|
||||||
|
|
||||||
${this.expanded && hass.user && hass.user.is_admin
|
${afterSpacer.map((panel) => renderPanel(hass, panel))}
|
||||||
? 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>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
${this._externalConfig && this._externalConfig.hasSettingsScreen
|
${this._externalConfig && this._externalConfig.hasSettingsScreen
|
||||||
? html`
|
? html`
|
||||||
<a
|
<a
|
||||||
@ -223,7 +176,6 @@ class HaSidebar extends LitElement {
|
|||||||
</a>
|
</a>
|
||||||
`
|
`
|
||||||
: ""}
|
: ""}
|
||||||
${configPanel ? renderPanel(hass, configPanel) : ""}
|
|
||||||
${hass.user
|
${hass.user
|
||||||
? html`
|
? html`
|
||||||
<a
|
<a
|
||||||
@ -280,7 +232,6 @@ class HaSidebar extends LitElement {
|
|||||||
return (
|
return (
|
||||||
hass.panels !== oldHass.panels ||
|
hass.panels !== oldHass.panels ||
|
||||||
hass.panelUrl !== oldHass.panelUrl ||
|
hass.panelUrl !== oldHass.panelUrl ||
|
||||||
hass.config.components !== oldHass.config.components ||
|
|
||||||
hass.user !== oldHass.user ||
|
hass.user !== oldHass.user ||
|
||||||
hass.localize !== oldHass.localize
|
hass.localize !== oldHass.localize
|
||||||
);
|
);
|
||||||
@ -458,12 +409,6 @@ class HaSidebar extends LitElement {
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
|
||||||
height: 1px;
|
|
||||||
background-color: var(--divider-color);
|
|
||||||
margin: 4px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.subheader {
|
.subheader {
|
||||||
color: var(--sidebar-text-color);
|
color: var(--sidebar-text-color);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from "./hass-router-page";
|
} from "./hass-router-page";
|
||||||
import { removeInitSkeleton } from "../util/init-skeleton";
|
import { removeInitSkeleton } from "../util/init-skeleton";
|
||||||
|
|
||||||
const CACHE_COMPONENTS = ["lovelace", "states"];
|
const CACHE_COMPONENTS = ["lovelace", "states", "developer-tools"];
|
||||||
const COMPONENTS = {
|
const COMPONENTS = {
|
||||||
calendar: () =>
|
calendar: () =>
|
||||||
import(/* webpackChunkName: "panel-calendar" */ "../panels/calendar/ha-panel-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"),
|
import(/* webpackChunkName: "panel-config" */ "../panels/config/ha-panel-config"),
|
||||||
custom: () =>
|
custom: () =>
|
||||||
import(/* webpackChunkName: "panel-custom" */ "../panels/custom/ha-panel-custom"),
|
import(/* webpackChunkName: "panel-custom" */ "../panels/custom/ha-panel-custom"),
|
||||||
"dev-event": () =>
|
"developer-tools": () =>
|
||||||
import(/* webpackChunkName: "panel-dev-event" */ "../panels/dev-event/ha-panel-dev-event"),
|
import(/* webpackChunkName: "panel-developer-tools" */ "../panels/developer-tools/ha-panel-developer-tools"),
|
||||||
"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"),
|
|
||||||
lovelace: () =>
|
lovelace: () =>
|
||||||
import(/* webpackChunkName: "panel-lovelace" */ "../panels/lovelace/ha-panel-lovelace"),
|
import(/* webpackChunkName: "panel-lovelace" */ "../panels/lovelace/ha-panel-lovelace"),
|
||||||
states: () =>
|
states: () =>
|
||||||
@ -52,14 +42,17 @@ const COMPONENTS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getRoutes = (panels: Panels): RouterOptions => {
|
const getRoutes = (panels: Panels): RouterOptions => {
|
||||||
const routes: { [route: string]: RouteOptions } = {};
|
const routes: RouterOptions["routes"] = {};
|
||||||
|
|
||||||
Object.values(panels).forEach((panel) => {
|
Object.values(panels).forEach((panel) => {
|
||||||
routes[panel.url_path] = {
|
const data: RouteOptions = {
|
||||||
load: COMPONENTS[panel.component_name],
|
|
||||||
tag: `ha-panel-${panel.component_name}`,
|
tag: `ha-panel-${panel.component_name}`,
|
||||||
cache: CACHE_COMPONENTS.includes(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 {
|
return {
|
||||||
|
@ -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
|
|
||||||
>
|
|
||||||
—
|
|
||||||
<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);
|
|
68
src/panels/developer-tools/developer-tools-router.ts
Normal file
68
src/panels/developer-tools/developer-tools-router.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/paper-input/paper-input";
|
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 { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import "../../components/ha-menu-button";
|
import "../../../resources/ha-style";
|
||||||
import "../../resources/ha-style";
|
|
||||||
import "./events-list";
|
import "./events-list";
|
||||||
import "./event-subscribe-card";
|
import "./event-subscribe-card";
|
||||||
import { EventsMixin } from "../../mixins/events-mixin";
|
import { EventsMixin } from "../../../mixins/events-mixin";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin EventsMixin
|
* @appliesMixin EventsMixin
|
||||||
@ -26,12 +22,10 @@ class HaPanelDevEvent extends EventsMixin(PolymerElement) {
|
|||||||
-ms-user-select: initial;
|
-ms-user-select: initial;
|
||||||
-webkit-user-select: initial;
|
-webkit-user-select: initial;
|
||||||
-moz-user-select: initial;
|
-moz-user-select: initial;
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
@apply --paper-font-body1;
|
@apply --paper-font-body1;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ha-form {
|
.ha-form {
|
||||||
@ -49,45 +43,34 @@ class HaPanelDevEvent extends EventsMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<app-header-layout has-scrolling-region>
|
<div class$="[[computeFormClasses(narrow)]]">
|
||||||
<app-header slot="header" fixed>
|
<div class="flex">
|
||||||
<app-toolbar>
|
<p>Fire an event on the event bus.</p>
|
||||||
<ha-menu-button></ha-menu-button>
|
|
||||||
<div main-title>Events</div>
|
|
||||||
</app-toolbar>
|
|
||||||
</app-header>
|
|
||||||
|
|
||||||
<div class="content">
|
<div class="ha-form">
|
||||||
<div class$="[[computeFormClasses(narrow)]]">
|
<paper-input
|
||||||
<div class="flex">
|
label="Event Type"
|
||||||
<p>Fire an event on the event bus.</p>
|
autofocus
|
||||||
|
required
|
||||||
<div class="ha-form">
|
value="{{eventType}}"
|
||||||
<paper-input
|
></paper-input>
|
||||||
label="Event Type"
|
<paper-textarea
|
||||||
autofocus
|
label="Event Data (JSON, optional)"
|
||||||
required
|
value="{{eventData}}"
|
||||||
value="{{eventType}}"
|
></paper-textarea>
|
||||||
></paper-input>
|
<mwc-button on-click="fireEvent" raised>Fire Event</mwc-button>
|
||||||
<paper-textarea
|
|
||||||
label="Event Data (JSON, optional)"
|
|
||||||
value="{{eventData}}"
|
|
||||||
></paper-textarea>
|
|
||||||
<mwc-button on-click="fireEvent" raised>Fire Event</mwc-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div class="header">Available Events</div>
|
|
||||||
<events-list
|
|
||||||
on-event-selected="eventSelected"
|
|
||||||
hass="[[hass]]"
|
|
||||||
></events-list>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<event-subscribe-card hass="[[hass]]"></event-subscribe-card>
|
|
||||||
</div>
|
</div>
|
||||||
</app-header-layout>
|
|
||||||
|
<div>
|
||||||
|
<div class="header">Available Events</div>
|
||||||
|
<events-list
|
||||||
|
on-event-selected="eventSelected"
|
||||||
|
hass="[[hass]]"
|
||||||
|
></events-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<event-subscribe-card hass="[[hass]]"></event-subscribe-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,4 +122,4 @@ class HaPanelDevEvent extends EventsMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-panel-dev-event", HaPanelDevEvent);
|
customElements.define("developer-tools-event", HaPanelDevEvent);
|
@ -10,10 +10,10 @@ import {
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import { HassEvent } from "home-assistant-js-websocket";
|
import { HassEvent } from "home-assistant-js-websocket";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { PolymerChangedEvent } from "../../polymer-types";
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
import "../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import format_time from "../../common/datetime/format_time";
|
import format_time from "../../../common/datetime/format_time";
|
||||||
|
|
||||||
@customElement("event-subscribe-card")
|
@customElement("event-subscribe-card")
|
||||||
class EventSubscribeCard extends LitElement {
|
class EventSubscribeCard extends LitElement {
|
@ -1,7 +1,7 @@
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import { EventsMixin } from "../../mixins/events-mixin";
|
import { EventsMixin } from "../../../mixins/events-mixin";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin EventsMixin
|
* @appliesMixin EventsMixin
|
121
src/panels/developer-tools/ha-panel-developer-tools.ts
Normal file
121
src/panels/developer-tools/ha-panel-developer-tools.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
194
src/panels/developer-tools/info/developer-tools-info.ts
Normal file
194
src/panels/developer-tools/info/developer-tools-info.ts
Normal 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
|
||||||
|
>
|
||||||
|
—
|
||||||
|
<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);
|
@ -8,11 +8,11 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
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 { SystemLogDetailDialogParams } from "./show-dialog-system-log-detail";
|
||||||
import { PolymerChangedEvent } from "../../polymer-types";
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
import { haStyleDialog } from "../../resources/styles";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
|
|
||||||
class DialogSystemLogDetail extends LitElement {
|
class DialogSystemLogDetail extends LitElement {
|
||||||
private _params?: SystemLogDetailDialogParams;
|
private _params?: SystemLogDetailDialogParams;
|
@ -9,8 +9,8 @@ import {
|
|||||||
import "@polymer/paper-icon-button/paper-icon-button";
|
import "@polymer/paper-icon-button/paper-icon-button";
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { fetchErrorLog } from "../../data/error_log";
|
import { fetchErrorLog } from "../../../data/error_log";
|
||||||
|
|
||||||
class ErrorLogCard extends LitElement {
|
class ErrorLogCard extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass?: HomeAssistant;
|
@ -1,5 +1,5 @@
|
|||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { LoggedError } from "../../data/system_log";
|
import { LoggedError } from "../../../data/system_log";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
@ -7,13 +7,13 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import "../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import {
|
import {
|
||||||
SystemHealthInfo,
|
SystemHealthInfo,
|
||||||
fetchSystemHealthInfo,
|
fetchSystemHealthInfo,
|
||||||
} from "../../data/system_health";
|
} from "../../../data/system_health";
|
||||||
|
|
||||||
const sortKeys = (a: string, b: string) => {
|
const sortKeys = (a: string, b: string) => {
|
||||||
if (a === "homeassistant") {
|
if (a === "homeassistant") {
|
@ -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-body";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import "../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../components/buttons/ha-call-service-button";
|
import "../../../components/buttons/ha-call-service-button";
|
||||||
import "../../components/buttons/ha-progress-button";
|
import "../../../components/buttons/ha-progress-button";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { LoggedError, fetchSystemLog } from "../../data/system_log";
|
import { LoggedError, fetchSystemLog } from "../../../data/system_log";
|
||||||
import formatDateTime from "../../common/datetime/format_date_time";
|
import formatDateTime from "../../../common/datetime/format_date_time";
|
||||||
import formatTime from "../../common/datetime/format_time";
|
import formatTime from "../../../common/datetime/format_time";
|
||||||
import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail";
|
import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail";
|
||||||
|
|
||||||
const formatLogTime = (date, language: string) => {
|
const formatLogTime = (date, language: string) => {
|
@ -7,10 +7,10 @@ import "@polymer/paper-input/paper-textarea";
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import "../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
import "../../components/ha-menu-button";
|
import "../../../components/ha-menu-button";
|
||||||
import "../../resources/ha-style";
|
import "../../../resources/ha-style";
|
||||||
import "../../util/app-localstorage-document";
|
import "../../../util/app-localstorage-document";
|
||||||
|
|
||||||
class HaPanelDevMqtt extends PolymerElement {
|
class HaPanelDevMqtt extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
@ -86,4 +86,4 @@ class HaPanelDevMqtt extends PolymerElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-panel-dev-mqtt", HaPanelDevMqtt);
|
customElements.define("developer-tools-mqtt", HaPanelDevMqtt);
|
@ -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 "@material/mwc-button";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import { ENTITY_COMPONENT_DOMAINS } from "../../data/entity";
|
import { ENTITY_COMPONENT_DOMAINS } from "../../../data/entity";
|
||||||
import "../../components/entity/ha-entity-picker";
|
import "../../../components/entity/ha-entity-picker";
|
||||||
import "../../components/ha-menu-button";
|
import "../../../components/ha-service-picker";
|
||||||
import "../../components/ha-service-picker";
|
import "../../../resources/ha-style";
|
||||||
import "../../resources/ha-style";
|
import "../../../util/app-localstorage-document";
|
||||||
import "../../util/app-localstorage-document";
|
|
||||||
|
|
||||||
const ERROR_SENTINEL = {};
|
const ERROR_SENTINEL = {};
|
||||||
class HaPanelDevService extends PolymerElement {
|
class HaPanelDevService extends PolymerElement {
|
||||||
@ -22,9 +18,7 @@ class HaPanelDevService extends PolymerElement {
|
|||||||
-ms-user-select: initial;
|
-ms-user-select: initial;
|
||||||
-webkit-user-select: initial;
|
-webkit-user-select: initial;
|
||||||
-moz-user-select: initial;
|
-moz-user-select: initial;
|
||||||
}
|
display: block;
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
@ -81,100 +75,87 @@ class HaPanelDevService extends PolymerElement {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<app-header-layout has-scrolling-region>
|
<app-localstorage-document
|
||||||
<app-header slot="header" fixed>
|
key="panel-dev-service-state-domain-service"
|
||||||
<app-toolbar>
|
data="{{domainService}}"
|
||||||
<ha-menu-button></ha-menu-button>
|
>
|
||||||
<div main-title>Services</div>
|
</app-localstorage-document>
|
||||||
</app-toolbar>
|
<app-localstorage-document
|
||||||
</app-header>
|
key="[[_computeServicedataKey(domainService)]]"
|
||||||
|
data="{{serviceData}}"
|
||||||
|
>
|
||||||
|
</app-localstorage-document>
|
||||||
|
|
||||||
<app-localstorage-document
|
<div class="content">
|
||||||
key="panel-dev-service-state-domain-service"
|
<p>
|
||||||
data="{{domainService}}"
|
The service dev tool allows you to call any available service in Home
|
||||||
>
|
Assistant.
|
||||||
</app-localstorage-document>
|
</p>
|
||||||
<app-localstorage-document
|
|
||||||
key="[[_computeServicedataKey(domainService)]]"
|
|
||||||
data="{{serviceData}}"
|
|
||||||
>
|
|
||||||
</app-localstorage-document>
|
|
||||||
|
|
||||||
<div class="content">
|
<div class="ha-form">
|
||||||
<p>
|
<ha-service-picker
|
||||||
The service dev tool allows you to call any available service in
|
hass="[[hass]]"
|
||||||
Home Assistant.
|
value="{{domainService}}"
|
||||||
</p>
|
></ha-service-picker>
|
||||||
|
<template is="dom-if" if="[[_computeHasEntity(_attributes)]]">
|
||||||
<div class="ha-form">
|
<ha-entity-picker
|
||||||
<ha-service-picker
|
|
||||||
hass="[[hass]]"
|
hass="[[hass]]"
|
||||||
value="{{domainService}}"
|
value="[[_computeEntityValue(parsedJSON)]]"
|
||||||
></ha-service-picker>
|
on-change="_entityPicked"
|
||||||
<template is="dom-if" if="[[_computeHasEntity(_attributes)]]">
|
disabled="[[!validJSON]]"
|
||||||
<ha-entity-picker
|
domain-filter="[[_computeEntityDomainFilter(_domain)]]"
|
||||||
hass="[[hass]]"
|
allow-custom-entity
|
||||||
value="[[_computeEntityValue(parsedJSON)]]"
|
></ha-entity-picker>
|
||||||
on-change="_entityPicked"
|
|
||||||
disabled="[[!validJSON]]"
|
|
||||||
domain-filter="[[_computeEntityDomainFilter(_domain)]]"
|
|
||||||
allow-custom-entity
|
|
||||||
></ha-entity-picker>
|
|
||||||
</template>
|
|
||||||
<paper-textarea
|
|
||||||
always-float-label
|
|
||||||
label="Service Data (JSON, optional)"
|
|
||||||
value="{{serviceData}}"
|
|
||||||
autocapitalize="none"
|
|
||||||
autocomplete="off"
|
|
||||||
spellcheck="false"
|
|
||||||
></paper-textarea>
|
|
||||||
<mwc-button on-click="_callService" raised disabled="[[!validJSON]]"
|
|
||||||
>Call Service</mwc-button
|
|
||||||
>
|
|
||||||
<template is="dom-if" if="[[!validJSON]]">
|
|
||||||
<span class="error">Invalid JSON</span>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template is="dom-if" if="[[!domainService]]">
|
|
||||||
<h1>Select a service to see the description</h1>
|
|
||||||
</template>
|
</template>
|
||||||
|
<paper-textarea
|
||||||
<template is="dom-if" if="[[domainService]]">
|
always-float-label
|
||||||
<template is="dom-if" if="[[!_description]]">
|
label="Service Data (JSON, optional)"
|
||||||
<h1>No description is available</h1>
|
value="{{serviceData}}"
|
||||||
</template>
|
autocapitalize="none"
|
||||||
<template is="dom-if" if="[[_description]]">
|
autocomplete="off"
|
||||||
<h3>[[_description]]</h3>
|
spellcheck="false"
|
||||||
|
></paper-textarea>
|
||||||
<table class="attributes">
|
<mwc-button on-click="_callService" raised disabled="[[!validJSON]]"
|
||||||
<tr>
|
>Call Service</mwc-button
|
||||||
<th>Parameter</th>
|
>
|
||||||
<th>Description</th>
|
<template is="dom-if" if="[[!validJSON]]">
|
||||||
<th>Example</th>
|
<span class="error">Invalid JSON</span>
|
||||||
</tr>
|
|
||||||
<template is="dom-if" if="[[!_attributes.length]]">
|
|
||||||
<tr>
|
|
||||||
<td colspan="3">This service takes no parameters.</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
<template
|
|
||||||
is="dom-repeat"
|
|
||||||
items="[[_attributes]]"
|
|
||||||
as="attribute"
|
|
||||||
>
|
|
||||||
<tr>
|
|
||||||
<td><pre>[[attribute.key]]</pre></td>
|
|
||||||
<td>[[attribute.description]]</td>
|
|
||||||
<td>[[attribute.example]]</td>
|
|
||||||
</tr>
|
|
||||||
</template>
|
|
||||||
</table>
|
|
||||||
</template>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</app-header-layout>
|
|
||||||
|
<template is="dom-if" if="[[!domainService]]">
|
||||||
|
<h1>Select a service to see the description</h1>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template is="dom-if" if="[[domainService]]">
|
||||||
|
<template is="dom-if" if="[[!_description]]">
|
||||||
|
<h1>No description is available</h1>
|
||||||
|
</template>
|
||||||
|
<template is="dom-if" if="[[_description]]">
|
||||||
|
<h3>[[_description]]</h3>
|
||||||
|
|
||||||
|
<table class="attributes">
|
||||||
|
<tr>
|
||||||
|
<th>Parameter</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Example</th>
|
||||||
|
</tr>
|
||||||
|
<template is="dom-if" if="[[!_attributes.length]]">
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">This service takes no parameters.</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
<template is="dom-repeat" items="[[_attributes]]" as="attribute">
|
||||||
|
<tr>
|
||||||
|
<td><pre>[[attribute.key]]</pre></td>
|
||||||
|
<td>[[attribute.description]]</td>
|
||||||
|
<td>[[attribute.example]]</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,4 +285,4 @@ class HaPanelDevService extends PolymerElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-panel-dev-service", HaPanelDevService);
|
customElements.define("developer-tools-service", HaPanelDevService);
|
@ -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 "@material/mwc-button";
|
||||||
import "@polymer/paper-checkbox/paper-checkbox";
|
import "@polymer/paper-checkbox/paper-checkbox";
|
||||||
import "@polymer/paper-input/paper-input";
|
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 { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import "../../components/entity/ha-entity-picker";
|
import "../../../components/entity/ha-entity-picker";
|
||||||
import "../../components/ha-menu-button";
|
import "../../../resources/ha-style";
|
||||||
import "../../resources/ha-style";
|
import { EventsMixin } from "../../../mixins/events-mixin";
|
||||||
import { EventsMixin } from "../../mixins/events-mixin";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin EventsMixin
|
* @appliesMixin EventsMixin
|
||||||
@ -24,9 +20,7 @@ class HaPanelDevState extends EventsMixin(PolymerElement) {
|
|||||||
-ms-user-select: initial;
|
-ms-user-select: initial;
|
||||||
-webkit-user-select: initial;
|
-webkit-user-select: initial;
|
||||||
-moz-user-select: initial;
|
-moz-user-select: initial;
|
||||||
}
|
display: block;
|
||||||
|
|
||||||
.content {
|
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
@ -70,107 +64,96 @@ class HaPanelDevState extends EventsMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<app-header-layout has-scrolling-region>
|
<div>
|
||||||
<app-header slot="header" fixed>
|
<p>
|
||||||
<app-toolbar>
|
Set the representation of a device within Home Assistant.<br />
|
||||||
<ha-menu-button></ha-menu-button>
|
This will not communicate with the actual device.
|
||||||
<div main-title>States</div>
|
</p>
|
||||||
</app-toolbar>
|
|
||||||
</app-header>
|
|
||||||
|
|
||||||
<div class="content">
|
<ha-entity-picker
|
||||||
<div>
|
autofocus
|
||||||
<p>
|
hass="[[hass]]"
|
||||||
Set the representation of a device within Home Assistant.<br />
|
value="{{_entityId}}"
|
||||||
This will not communicate with the actual device.
|
allow-custom-entity
|
||||||
</p>
|
></ha-entity-picker>
|
||||||
|
<paper-input
|
||||||
|
label="State"
|
||||||
|
required
|
||||||
|
autocapitalize="none"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
spellcheck="false"
|
||||||
|
value="{{_state}}"
|
||||||
|
class="state-input"
|
||||||
|
></paper-input>
|
||||||
|
<paper-textarea
|
||||||
|
label="State attributes (JSON, optional)"
|
||||||
|
autocapitalize="none"
|
||||||
|
autocomplete="off"
|
||||||
|
spellcheck="false"
|
||||||
|
value="{{_stateAttributes}}"
|
||||||
|
></paper-textarea>
|
||||||
|
<mwc-button on-click="handleSetState" raised>Set State</mwc-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ha-entity-picker
|
<h1>Current entities</h1>
|
||||||
autofocus
|
<table class="entities">
|
||||||
hass="[[hass]]"
|
<tr>
|
||||||
value="{{_entityId}}"
|
<th>Entity</th>
|
||||||
allow-custom-entity
|
<th>State</th>
|
||||||
></ha-entity-picker>
|
<th hidden$="[[narrow]]">
|
||||||
|
Attributes
|
||||||
|
<paper-checkbox checked="{{_showAttributes}}"></paper-checkbox>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
<paper-input
|
<paper-input
|
||||||
label="State"
|
label="Filter entities"
|
||||||
required
|
type="search"
|
||||||
autocapitalize="none"
|
value="{{_entityFilter}}"
|
||||||
autocomplete="off"
|
|
||||||
autocorrect="off"
|
|
||||||
spellcheck="false"
|
|
||||||
value="{{_state}}"
|
|
||||||
class="state-input"
|
|
||||||
></paper-input>
|
></paper-input>
|
||||||
<paper-textarea
|
</th>
|
||||||
label="State attributes (JSON, optional)"
|
<th>
|
||||||
autocapitalize="none"
|
<paper-input
|
||||||
autocomplete="off"
|
label="Filter states"
|
||||||
spellcheck="false"
|
type="search"
|
||||||
value="{{_stateAttributes}}"
|
value="{{_stateFilter}}"
|
||||||
></paper-textarea>
|
></paper-input>
|
||||||
<mwc-button on-click="handleSetState" raised>Set State</mwc-button>
|
</th>
|
||||||
</div>
|
<th hidden$="[[!computeShowAttributes(narrow, _showAttributes)]]">
|
||||||
|
<paper-input
|
||||||
<h1>Current entities</h1>
|
label="Filter attributes"
|
||||||
<table class="entities">
|
type="search"
|
||||||
<tr>
|
value="{{_attributeFilter}}"
|
||||||
<th>Entity</th>
|
></paper-input>
|
||||||
<th>State</th>
|
</th>
|
||||||
<th hidden$="[[narrow]]">
|
</tr>
|
||||||
Attributes
|
<tr hidden$="[[!computeShowEntitiesPlaceholder(_entities)]]">
|
||||||
<paper-checkbox checked="{{_showAttributes}}"></paper-checkbox>
|
<td colspan="3">No entities</td>
|
||||||
</th>
|
</tr>
|
||||||
</tr>
|
<template is="dom-repeat" items="[[_entities]]" as="entity">
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<td>
|
||||||
<paper-input
|
<paper-icon-button
|
||||||
label="Filter entities"
|
on-click="entityMoreInfo"
|
||||||
type="search"
|
icon="hass:open-in-new"
|
||||||
value="{{_entityFilter}}"
|
alt="More Info"
|
||||||
></paper-input>
|
title="More Info"
|
||||||
</th>
|
>
|
||||||
<th>
|
</paper-icon-button>
|
||||||
<paper-input
|
<a href="#" on-click="entitySelected">[[entity.entity_id]]</a>
|
||||||
label="Filter states"
|
</td>
|
||||||
type="search"
|
<td>[[entity.state]]</td>
|
||||||
value="{{_stateFilter}}"
|
<template
|
||||||
></paper-input>
|
is="dom-if"
|
||||||
</th>
|
if="[[computeShowAttributes(narrow, _showAttributes)]]"
|
||||||
<th hidden$="[[!computeShowAttributes(narrow, _showAttributes)]]">
|
>
|
||||||
<paper-input
|
<td>[[attributeString(entity)]]</td>
|
||||||
label="Filter attributes"
|
|
||||||
type="search"
|
|
||||||
value="{{_attributeFilter}}"
|
|
||||||
></paper-input>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr hidden$="[[!computeShowEntitiesPlaceholder(_entities)]]">
|
|
||||||
<td colspan="3">No entities</td>
|
|
||||||
</tr>
|
|
||||||
<template is="dom-repeat" items="[[_entities]]" as="entity">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<paper-icon-button
|
|
||||||
on-click="entityMoreInfo"
|
|
||||||
icon="hass:open-in-new"
|
|
||||||
alt="More Info"
|
|
||||||
title="More Info"
|
|
||||||
>
|
|
||||||
</paper-icon-button>
|
|
||||||
<a href="#" on-click="entitySelected">[[entity.entity_id]]</a>
|
|
||||||
</td>
|
|
||||||
<td>[[entity.state]]</td>
|
|
||||||
<template
|
|
||||||
is="dom-if"
|
|
||||||
if="[[computeShowAttributes(narrow, _showAttributes)]]"
|
|
||||||
>
|
|
||||||
<td>[[attributeString(entity)]]</td>
|
|
||||||
</template>
|
|
||||||
</tr>
|
|
||||||
</template>
|
</template>
|
||||||
</table>
|
</tr>
|
||||||
</div>
|
</template>
|
||||||
</app-header-layout>
|
</table>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,4 +334,4 @@ class HaPanelDevState extends EventsMixin(PolymerElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-panel-dev-state", HaPanelDevState);
|
customElements.define("developer-tools-state", HaPanelDevState);
|
@ -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-input/paper-textarea";
|
||||||
import "@polymer/paper-spinner/paper-spinner";
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
import { timeOut } from "@polymer/polymer/lib/utils/async";
|
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 { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import "../../components/ha-menu-button";
|
import "../../../resources/ha-style";
|
||||||
import "../../resources/ha-style";
|
|
||||||
|
|
||||||
class HaPanelDevTemplate extends PolymerElement {
|
class HaPanelDevTemplate extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
@ -67,52 +63,43 @@ class HaPanelDevTemplate extends PolymerElement {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<app-header-layout has-scrolling-region>
|
<div class$="[[computeFormClasses(narrow)]]">
|
||||||
<app-header slot="header" fixed>
|
<div class="edit-pane">
|
||||||
<app-toolbar>
|
<p>
|
||||||
<ha-menu-button></ha-menu-button>
|
Templates are rendered using the Jinja2 template engine with some
|
||||||
<div main-title>Templates</div>
|
Home Assistant specific extensions.
|
||||||
</app-toolbar>
|
</p>
|
||||||
</app-header>
|
<ul>
|
||||||
|
<li>
|
||||||
<div class$="[[computeFormClasses(narrow)]]">
|
<a
|
||||||
<div class="edit-pane">
|
href="http://jinja.pocoo.org/docs/dev/templates/"
|
||||||
<p>
|
target="_blank"
|
||||||
Templates are rendered using the Jinja2 template engine with some
|
>Jinja2 template documentation</a
|
||||||
Home Assistant specific extensions.
|
>
|
||||||
</p>
|
</li>
|
||||||
<ul>
|
<li>
|
||||||
<li>
|
<a
|
||||||
<a
|
href="https://home-assistant.io/docs/configuration/templating/"
|
||||||
href="http://jinja.pocoo.org/docs/dev/templates/"
|
target="_blank"
|
||||||
target="_blank"
|
>Home Assistant template extensions</a
|
||||||
>Jinja2 template documentation</a
|
>
|
||||||
>
|
</li>
|
||||||
</li>
|
</ul>
|
||||||
<li>
|
<paper-textarea
|
||||||
<a
|
label="Template editor"
|
||||||
href="https://home-assistant.io/docs/configuration/templating/"
|
value="{{template}}"
|
||||||
target="_blank"
|
autofocus
|
||||||
>Home Assistant template extensions</a
|
></paper-textarea>
|
||||||
>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<paper-textarea
|
|
||||||
label="Template editor"
|
|
||||||
value="{{template}}"
|
|
||||||
autofocus
|
|
||||||
></paper-textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="render-pane">
|
|
||||||
<paper-spinner
|
|
||||||
class="render-spinner"
|
|
||||||
active="[[rendering]]"
|
|
||||||
></paper-spinner>
|
|
||||||
<pre class$="[[computeRenderedClasses(error)]]">[[processed]]</pre>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</app-header-layout>
|
|
||||||
|
<div class="render-pane">
|
||||||
|
<paper-spinner
|
||||||
|
class="render-spinner"
|
||||||
|
active="[[rendering]]"
|
||||||
|
></paper-spinner>
|
||||||
|
<pre class$="[[computeRenderedClasses(error)]]">[[processed]]</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,4 +194,4 @@ For loop example:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-panel-dev-template", HaPanelDevTemplate);
|
customElements.define("developer-tools-template", HaPanelDevTemplate);
|
Loading…
x
Reference in New Issue
Block a user