parent
7c2135f444
commit
a58a324073
@ -38,9 +38,9 @@ class DemoCard extends PolymerElement {
|
||||
}
|
||||
</style>
|
||||
<h2>[[config.heading]]</h2>
|
||||
<div class='root'>
|
||||
<div class="root">
|
||||
<div id="card"></div>
|
||||
<template is='dom-if' if='[[showConfig]]'>
|
||||
<template is="dom-if" if="[[showConfig]]">
|
||||
<pre>[[_trim(config.config)]]</pre>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@ -25,18 +25,18 @@ class DemoCards extends PolymerElement {
|
||||
}
|
||||
</style>
|
||||
<app-toolbar>
|
||||
<div class='filters'>
|
||||
<paper-toggle-button
|
||||
checked='{{_showConfig}}'
|
||||
>Show config</paper-toggle-button>
|
||||
<div class="filters">
|
||||
<paper-toggle-button checked="{{_showConfig}}"
|
||||
>Show config</paper-toggle-button
|
||||
>
|
||||
</div>
|
||||
</app-toolbar>
|
||||
<div class='cards'>
|
||||
<template is='dom-repeat' items='[[configs]]'>
|
||||
<div class="cards">
|
||||
<template is="dom-repeat" items="[[configs]]">
|
||||
<demo-card
|
||||
config='[[item]]'
|
||||
show-config='[[_showConfig]]'
|
||||
hass='[[hass]]'
|
||||
config="[[item]]"
|
||||
show-config="[[_showConfig]]"
|
||||
hass="[[hass]]"
|
||||
></demo-card>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@ -8,56 +8,56 @@ import "../../../src/components/ha-card";
|
||||
class DemoMoreInfo extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
<style>
|
||||
:host {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
ha-card {
|
||||
width: 333px;
|
||||
}
|
||||
|
||||
state-card-content {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
more-info-content {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 400px;
|
||||
margin: 16px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
:host {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
ha-card {
|
||||
width: 333px;
|
||||
}
|
||||
|
||||
state-card-content {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
more-info-content {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 400px;
|
||||
margin: 16px;
|
||||
overflow: auto;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<ha-card>
|
||||
<state-card-content
|
||||
state-obj="[[_stateObj]]"
|
||||
hass="[[hass]]"
|
||||
in-dialog
|
||||
></state-card-content>
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
:host {
|
||||
flex-direction: column;
|
||||
}
|
||||
pre {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<ha-card>
|
||||
<state-card-content
|
||||
state-obj="[[_stateObj]]"
|
||||
hass="[[hass]]"
|
||||
in-dialog
|
||||
></state-card-content>
|
||||
|
||||
<more-info-content
|
||||
hass='[[hass]]'
|
||||
state-obj='[[_stateObj]]'
|
||||
></more-info-content>
|
||||
</ha-card>
|
||||
<template is='dom-if' if='[[showConfig]]'>
|
||||
<pre>[[_jsonEntity(_stateObj)]]</pre>
|
||||
</template>
|
||||
`;
|
||||
<more-info-content
|
||||
hass="[[hass]]"
|
||||
state-obj="[[_stateObj]]"
|
||||
></more-info-content>
|
||||
</ha-card>
|
||||
<template is="dom-if" if="[[showConfig]]">
|
||||
<pre>[[_jsonEntity(_stateObj)]]</pre>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -25,18 +25,18 @@ class DemoMoreInfos extends PolymerElement {
|
||||
}
|
||||
</style>
|
||||
<app-toolbar>
|
||||
<div class='filters'>
|
||||
<paper-toggle-button
|
||||
checked='{{_showConfig}}'
|
||||
>Show entity</paper-toggle-button>
|
||||
<div class="filters">
|
||||
<paper-toggle-button checked="{{_showConfig}}"
|
||||
>Show entity</paper-toggle-button
|
||||
>
|
||||
</div>
|
||||
</app-toolbar>
|
||||
<div class='cards'>
|
||||
<template is='dom-repeat' items='[[entities]]'>
|
||||
<div class="cards">
|
||||
<template is="dom-repeat" items="[[entities]]">
|
||||
<demo-more-info
|
||||
entity-id='[[item]]'
|
||||
show-config='[[_showConfig]]'
|
||||
hass='[[hass]]'
|
||||
entity-id="[[item]]"
|
||||
show-config="[[_showConfig]]"
|
||||
hass="[[hass]]"
|
||||
></demo-more-info>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@ -51,7 +51,11 @@ const CONFIGS = [
|
||||
class DemoAlarmPanelEntity extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards id='demos' hass='[[hass]]' configs="[[_configs]]"></demo-cards>
|
||||
<demo-cards
|
||||
id="demos"
|
||||
hass="[[hass]]"
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -57,8 +57,8 @@ class DemoConditional extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
hass='[[hass]]'
|
||||
id="demos"
|
||||
hass="[[hass]]"
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
`;
|
||||
|
||||
@ -175,10 +175,7 @@ const CONFIGS = [
|
||||
class DemoEntities extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,11 @@ const CONFIGS = [
|
||||
class DemoEntityButtonEntity extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards id='demos' hass='[[hass]]' configs="[[_configs]]"></demo-cards>
|
||||
<demo-cards
|
||||
id="demos"
|
||||
hass="[[hass]]"
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -92,10 +92,7 @@ const CONFIGS = [
|
||||
class DemoFilter extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -217,10 +217,7 @@ const CONFIGS = [
|
||||
class DemoPicEntity extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ const CONFIGS = [
|
||||
class DemoLightEntity extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards id='demos' configs="[[_configs]]"></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -78,8 +78,8 @@ class DemoHuiMediaPlayerRows extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
hass='[[hass]]'
|
||||
id="demos"
|
||||
hass="[[hass]]"
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
`;
|
||||
|
||||
@ -80,10 +80,7 @@ const CONFIGS = [
|
||||
class DemoPicElements extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -23,10 +23,7 @@ const CONFIGS = [
|
||||
class DemoShoppingListEntity extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -91,10 +91,7 @@ const CONFIGS = [
|
||||
class DemoStack extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -62,10 +62,7 @@ const CONFIGS = [
|
||||
class DemoThermostatEntity extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-cards
|
||||
id='demos'
|
||||
configs="[[_configs]]"
|
||||
></demo-cards>
|
||||
<demo-cards id="demos" configs="[[_configs]]"></demo-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -34,8 +34,8 @@ class DemoMoreInfoLight extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<demo-more-infos
|
||||
hass='[[hass]]'
|
||||
entities='[[_entities]]'
|
||||
hass="[[hass]]"
|
||||
entities="[[_entities]]"
|
||||
></demo-more-infos>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -9,34 +9,48 @@ import NavigateMixin from "../../../src/mixins/navigate-mixin";
|
||||
class HassioAddonRepository extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style hassio-style">
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
a.repo {
|
||||
display: block;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[addons.length]]">
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
[[repo.name]]
|
||||
<div class="description">
|
||||
Maintained by [[repo.maintainer]]
|
||||
<a class="repo" href="[[repo.url]]" target="_blank">[[repo.url]]</a>
|
||||
</div>
|
||||
</div>
|
||||
<template is="dom-repeat" items="[[addons]]" as="addon" sort="sortAddons">
|
||||
<paper-card on-click="addonTapped">
|
||||
<div class="card-content">
|
||||
<hassio-card-content hass="[[hass]]" title="[[addon.name]]" description="[[addon.description]]" icon="[[computeIcon(addon)]]" icon-title="[[computeIconTitle(addon)]]" icon-class="[[computeIconClass(addon)]]"></hassio-card-content>
|
||||
<style include="iron-flex ha-style hassio-style">
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
a.repo {
|
||||
display: block;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[addons.length]]">
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
[[repo.name]]
|
||||
<div class="description">
|
||||
Maintained by [[repo.maintainer]]
|
||||
<a class="repo" href="[[repo.url]]" target="_blank"
|
||||
>[[repo.url]]</a
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
</div>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[addons]]"
|
||||
as="addon"
|
||||
sort="sortAddons"
|
||||
>
|
||||
<paper-card on-click="addonTapped">
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="[[addon.name]]"
|
||||
description="[[addon.description]]"
|
||||
icon="[[computeIcon(addon)]]"
|
||||
icon-title="[[computeIconTitle(addon)]]"
|
||||
icon-class="[[computeIconClass(addon)]]"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,17 +7,24 @@ import "./hassio-repositories-editor";
|
||||
class HassioAddonStore extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
hassio-addon-repository {
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
||||
<hassio-repositories-editor hass="[[hass]]" repos="[[repos]]"></hassio-repositories-editor>
|
||||
<style include="iron-flex ha-style">
|
||||
hassio-addon-repository {
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
||||
<hassio-repositories-editor
|
||||
hass="[[hass]]"
|
||||
repos="[[repos]]"
|
||||
></hassio-repositories-editor>
|
||||
|
||||
<template is="dom-repeat" items="[[repos]]" as="repo" sort="sortRepos">
|
||||
<hassio-addon-repository hass="[[hass]]" repo="[[repo]]" addons="[[computeAddons(repo.slug)]]"></hassio-addon-repository>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-repeat" items="[[repos]]" as="repo" sort="sortRepos">
|
||||
<hassio-addon-repository
|
||||
hass="[[hass]]"
|
||||
repo="[[repo]]"
|
||||
addons="[[computeAddons(repo.slug)]]"
|
||||
></hassio-addon-repository>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,48 +11,73 @@ import "../resources/hassio-style";
|
||||
class HassioRepositoriesEditor extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style hassio-style">
|
||||
.add {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
iron-icon {
|
||||
color: var(--secondary-text-color);
|
||||
margin-right: 16px;
|
||||
display: inline-block;
|
||||
}
|
||||
paper-input {
|
||||
width: calc(100% - 49px);
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
Repositories
|
||||
<div class="description">
|
||||
Configure which add-on repositories to fetch data from:
|
||||
<style include="ha-style hassio-style">
|
||||
.add {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
iron-icon {
|
||||
color: var(--secondary-text-color);
|
||||
margin-right: 16px;
|
||||
display: inline-block;
|
||||
}
|
||||
paper-input {
|
||||
width: calc(100% - 49px);
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
Repositories
|
||||
<div class="description">
|
||||
Configure which add-on repositories to fetch data from:
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template id="list" is="dom-repeat" items="[[repoList]]" as="repo" sort="sortRepos">
|
||||
<template
|
||||
id="list"
|
||||
is="dom-repeat"
|
||||
items="[[repoList]]"
|
||||
as="repo"
|
||||
sort="sortRepos"
|
||||
>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="[[repo.name]]"
|
||||
description="[[repo.url]]"
|
||||
icon="hassio:github-circle"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/supervisor/options"
|
||||
data="[[computeRemoveRepoData(repoList, repo.url)]]"
|
||||
class="warning"
|
||||
>Remove</ha-call-api-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<hassio-card-content hass="[[hass]]" title="[[repo.name]]" description="[[repo.url]]" icon="hassio:github-circle"></hassio-card-content>
|
||||
<div class="card-content add">
|
||||
<iron-icon icon="hassio:github-circle"></iron-icon>
|
||||
<paper-input
|
||||
label="Add new repository by URL"
|
||||
value="{{repoUrl}}"
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/supervisor/options" data="[[computeRemoveRepoData(repoList, repo.url)]]" class="warning">Remove</ha-call-api-button>
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/supervisor/options"
|
||||
data="[[computeAddRepoData(repoList, repoUrl)]]"
|
||||
>Add</ha-call-api-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<paper-card>
|
||||
<div class="card-content add">
|
||||
<iron-icon icon="hassio:github-circle"></iron-icon>
|
||||
<paper-input label="Add new repository by URL" value="{{repoUrl}}"></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/supervisor/options" data="[[computeAddRepoData(repoList, repoUrl)]]">Add</ha-call-api-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,49 +14,61 @@ import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
class HassioAddonAudio extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host,
|
||||
paper-card,
|
||||
paper-dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
paper-item {
|
||||
width: 450px;
|
||||
}
|
||||
.card-actions {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Audio">
|
||||
<div class="card-content">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="errors">[[error]]</div>
|
||||
</template>
|
||||
<style include="ha-style">
|
||||
:host,
|
||||
paper-card,
|
||||
paper-dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
paper-item {
|
||||
width: 450px;
|
||||
}
|
||||
.card-actions {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Audio">
|
||||
<div class="card-content">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="errors">[[error]]</div>
|
||||
</template>
|
||||
|
||||
<paper-dropdown-menu label="Input">
|
||||
<paper-listbox slot="dropdown-content" attr-for-selected="device" selected="{{selectedInput}}">
|
||||
<template is="dom-repeat" items="[[inputDevices]]">
|
||||
<paper-item device\$="[[item.device]]">[[item.name]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-dropdown-menu label="Output">
|
||||
<paper-listbox slot="dropdown-content" attr-for-selected="device" selected="{{selectedOutput}}">
|
||||
<template is="dom-repeat" items="[[outputDevices]]">
|
||||
<paper-item device\$="[[item.device]]">[[item.name]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="_saveSettings">Save</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
<paper-dropdown-menu label="Input">
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
attr-for-selected="device"
|
||||
selected="{{selectedInput}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[inputDevices]]">
|
||||
<paper-item device\$="[[item.device]]"
|
||||
>[[item.name]]</paper-item
|
||||
>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-dropdown-menu label="Output">
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
attr-for-selected="device"
|
||||
selected="{{selectedOutput}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[outputDevices]]">
|
||||
<paper-item device\$="[[item.device]]"
|
||||
>[[item.name]]</paper-item
|
||||
>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="_saveSettings">Save</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,42 +9,53 @@ import "../../../src/components/buttons/ha-call-api-button";
|
||||
class HassioAddonConfig extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.card-actions {
|
||||
@apply --layout;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
iron-autogrow-textarea {
|
||||
width: 100%;
|
||||
font-family: monospace;
|
||||
}
|
||||
.syntaxerror {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Config">
|
||||
<div class="card-content">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="errors">[[error]]</div>
|
||||
</template>
|
||||
<iron-autogrow-textarea id="config" value="{{config}}"></iron-autogrow-textarea>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/addons/[[addonSlug]]/options" data="[[resetData]]">Reset to defaults</ha-call-api-button>
|
||||
<paper-button on-click="saveTapped" disabled="[[!configParsed]]">Save</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.card-actions {
|
||||
@apply --layout;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
iron-autogrow-textarea {
|
||||
width: 100%;
|
||||
font-family: monospace;
|
||||
}
|
||||
.syntaxerror {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Config">
|
||||
<div class="card-content">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="errors">[[error]]</div>
|
||||
</template>
|
||||
<iron-autogrow-textarea
|
||||
id="config"
|
||||
value="{{config}}"
|
||||
></iron-autogrow-textarea>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/options"
|
||||
data="[[resetData]]"
|
||||
>Reset to defaults</ha-call-api-button
|
||||
>
|
||||
<paper-button on-click="saveTapped" disabled="[[!configParsed]]"
|
||||
>Save</paper-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -15,139 +15,200 @@ import "../components/hassio-card-content";
|
||||
class HassioAddonInfo extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.addon-header {
|
||||
@apply --paper-font-headline;
|
||||
}
|
||||
.light-color {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.addon-version {
|
||||
float: right;
|
||||
font-size: 15px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.description {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.logo img {
|
||||
max-height: 60px;
|
||||
margin: 16px 0;
|
||||
display: block;
|
||||
}
|
||||
.state div{
|
||||
width: 150px;
|
||||
display: inline-block;
|
||||
}
|
||||
paper-toggle-button {
|
||||
display: inline;
|
||||
}
|
||||
iron-icon.running {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
iron-icon.stopped {
|
||||
color: var(--google-red-300);
|
||||
}
|
||||
ha-call-api-button {
|
||||
font-weight: 500;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
ha-markdown img {
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[computeUpdateAvailable(addon)]]">
|
||||
<paper-card heading="Update available! 🎉">
|
||||
<div class="card-content">
|
||||
<hassio-card-content hass="[[hass]]" title="[[addon.name]] [[addon.last_version]] is available" description="You are currently running version [[addon.version]]" icon="hassio:arrow-up-bold-circle" icon-class="update"></hassio-card-content>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/addons/[[addonSlug]]/update">Update</ha-call-api-button>
|
||||
<template is="dom-if" if="[[addon.changelog]]">
|
||||
<paper-button on-click="openChangelog">Changelog</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.addon-header {
|
||||
@apply --paper-font-headline;
|
||||
}
|
||||
.light-color {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.addon-version {
|
||||
float: right;
|
||||
font-size: 15px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.description {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.logo img {
|
||||
max-height: 60px;
|
||||
margin: 16px 0;
|
||||
display: block;
|
||||
}
|
||||
.state div {
|
||||
width: 150px;
|
||||
display: inline-block;
|
||||
}
|
||||
paper-toggle-button {
|
||||
display: inline;
|
||||
}
|
||||
iron-icon.running {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
iron-icon.stopped {
|
||||
color: var(--google-red-300);
|
||||
}
|
||||
ha-call-api-button {
|
||||
font-weight: 500;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
ha-markdown img {
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[computeUpdateAvailable(addon)]]">
|
||||
<paper-card heading="Update available! 🎉">
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="[[addon.name]] [[addon.last_version]] is available"
|
||||
description="You are currently running version [[addon.version]]"
|
||||
icon="hassio:arrow-up-bold-circle"
|
||||
icon-class="update"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/update"
|
||||
>Update</ha-call-api-button
|
||||
>
|
||||
<template is="dom-if" if="[[addon.changelog]]">
|
||||
<paper-button on-click="openChangelog">Changelog</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<div class="addon-header">[[addon.name]]
|
||||
<div class="addon-version light-color">
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
[[addon.version]]
|
||||
<template is="dom-if" if="[[isRunning]]">
|
||||
<iron-icon title="Add-on is running" class="running" icon="hassio:circle"></iron-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isRunning]]">
|
||||
<iron-icon title="Add-on is stopped" class="stopped" icon="hassio:circle"></iron-icon>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!addon.version]]">
|
||||
[[addon.last_version]]
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description light-color">
|
||||
[[addon.description]].<br>
|
||||
Visit <a href="[[addon.url]]" target="_blank">[[addon.name]] page</a> for details.
|
||||
</div>
|
||||
<template is="dom-if" if="[[addon.logo]]">
|
||||
<a href="[[addon.url]]" target="_blank" class="logo">
|
||||
<img src="/api/hassio/addons/[[addonSlug]]/logo">
|
||||
</a>
|
||||
</template>
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
<div class="state">
|
||||
<div>Start on boot</div>
|
||||
<paper-toggle-button on-change="startOnBootToggled" checked="[[computeStartOnBoot(addon.boot)]]"></paper-toggle-button>
|
||||
</div>
|
||||
<div class="state">
|
||||
<div>Auto update</div>
|
||||
<paper-toggle-button on-change="autoUpdateToggled" checked="[[addon.auto_update]]"></paper-toggle-button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
<paper-button class="warning" on-click="_unistallClicked">Uninstall</paper-button>
|
||||
<template is="dom-if" if="[[addon.build]]">
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/addons/[[addonSlug]]/rebuild">Rebuild</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isRunning]]">
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/addons/[[addonSlug]]/restart">Restart</ha-call-api-button>
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/addons/[[addonSlug]]/stop">Stop</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isRunning]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/addons/[[addonSlug]]/start">Start</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[computeShowWebUI(addon.webui, isRunning)]]">
|
||||
<a href="[[pathWebui(addon.webui)]]" tabindex="-1" target="_blank" class="right"><paper-button>Open web UI</paper-button></a>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!addon.version]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/addons/[[addonSlug]]/install">Install</ha-call-api-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
<template is="dom-if" if="[[addon.long_description]]">
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<ha-markdown content="[[addon.long_description]]"></ha-markdown>
|
||||
<div class="addon-header">
|
||||
[[addon.name]]
|
||||
<div class="addon-version light-color">
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
[[addon.version]]
|
||||
<template is="dom-if" if="[[isRunning]]">
|
||||
<iron-icon
|
||||
title="Add-on is running"
|
||||
class="running"
|
||||
icon="hassio:circle"
|
||||
></iron-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isRunning]]">
|
||||
<iron-icon
|
||||
title="Add-on is stopped"
|
||||
class="stopped"
|
||||
icon="hassio:circle"
|
||||
></iron-icon>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!addon.version]]">
|
||||
[[addon.last_version]]
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description light-color">
|
||||
[[addon.description]].<br />
|
||||
Visit
|
||||
<a href="[[addon.url]]" target="_blank">[[addon.name]] page</a> for
|
||||
details.
|
||||
</div>
|
||||
<template is="dom-if" if="[[addon.logo]]">
|
||||
<a href="[[addon.url]]" target="_blank" class="logo">
|
||||
<img src="/api/hassio/addons/[[addonSlug]]/logo" />
|
||||
</a>
|
||||
</template>
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
<div class="state">
|
||||
<div>Start on boot</div>
|
||||
<paper-toggle-button
|
||||
on-change="startOnBootToggled"
|
||||
checked="[[computeStartOnBoot(addon.boot)]]"
|
||||
></paper-toggle-button>
|
||||
</div>
|
||||
<div class="state">
|
||||
<div>Auto update</div>
|
||||
<paper-toggle-button
|
||||
on-change="autoUpdateToggled"
|
||||
checked="[[addon.auto_update]]"
|
||||
></paper-toggle-button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
<paper-button class="warning" on-click="_unistallClicked"
|
||||
>Uninstall</paper-button
|
||||
>
|
||||
<template is="dom-if" if="[[addon.build]]">
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/rebuild"
|
||||
>Rebuild</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template is="dom-if" if="[[isRunning]]">
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/restart"
|
||||
>Restart</ha-call-api-button
|
||||
>
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/stop"
|
||||
>Stop</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!isRunning]]">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/start"
|
||||
>Start</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[computeShowWebUI(addon.webui, isRunning)]]"
|
||||
>
|
||||
<a
|
||||
href="[[pathWebui(addon.webui)]]"
|
||||
tabindex="-1"
|
||||
target="_blank"
|
||||
class="right"
|
||||
><paper-button>Open web UI</paper-button></a
|
||||
>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!addon.version]]">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/install"
|
||||
>Install</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[addon.long_description]]">
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<ha-markdown content="[[addon.long_description]]"></ha-markdown>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -8,24 +8,22 @@ import "../../../src/resources/ha-style";
|
||||
class HassioAddonLogs extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host,
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Log">
|
||||
<div class="card-content">
|
||||
<pre>[[log]]</pre>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="refresh">Refresh</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
<style include="ha-style">
|
||||
:host,
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Log">
|
||||
<div class="card-content"><pre>[[log]]</pre></div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="refresh">Refresh</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,51 +10,60 @@ import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
class HassioAddonNetwork extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.card-actions {
|
||||
@apply --layout;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Network">
|
||||
<div class="card-content">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="errors">[[error]]</div>
|
||||
</template>
|
||||
|
||||
<table>
|
||||
<tbody><tr>
|
||||
<th>Container</th>
|
||||
<th>Host</th>
|
||||
</tr>
|
||||
<template is="dom-repeat" items="[[config]]">
|
||||
<tr>
|
||||
<td>
|
||||
[[item.container]]
|
||||
</td>
|
||||
<td>
|
||||
<paper-input value="{{item.host}}" no-label-float=""></paper-input>
|
||||
</td>
|
||||
</tr>
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.card-actions {
|
||||
@apply --layout;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="Network">
|
||||
<div class="card-content">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="errors">[[error]]</div>
|
||||
</template>
|
||||
</tbody></table>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/addons/[[addonSlug]]/options" data="[[resetData]]">Reset to defaults</ha-call-api-button>
|
||||
<paper-button on-click="saveTapped">Save</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Container</th>
|
||||
<th>Host</th>
|
||||
</tr>
|
||||
<template is="dom-repeat" items="[[config]]">
|
||||
<tr>
|
||||
<td>[[item.container]]</td>
|
||||
<td>
|
||||
<paper-input
|
||||
value="{{item.host}}"
|
||||
no-label-float=""
|
||||
></paper-input>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/addons/[[addonSlug]]/options"
|
||||
data="[[resetData]]"
|
||||
>Reset to defaults</ha-call-api-button
|
||||
>
|
||||
<paper-button on-click="saveTapped">Save</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,69 +18,102 @@ import "./hassio-addon-network";
|
||||
class HassioAddonView extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
--paper-card-header-color: var(--primary-text-color);
|
||||
}
|
||||
.content {
|
||||
padding: 24px 0 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
hassio-addon-info,
|
||||
hassio-addon-network,
|
||||
hassio-addon-audio,
|
||||
hassio-addon-config {
|
||||
margin-bottom: 24px;
|
||||
width: 600px;
|
||||
}
|
||||
hassio-addon-logs {
|
||||
max-width: calc(100% - 8px);
|
||||
min-width: 600px;
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
<style include="iron-flex ha-style">
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
--paper-card-header-color: var(--primary-text-color);
|
||||
}
|
||||
.content {
|
||||
padding: 24px 0 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
hassio-addon-info,
|
||||
hassio-addon-network,
|
||||
hassio-addon-audio,
|
||||
hassio-addon-config,
|
||||
hassio-addon-logs {
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
hassio-addon-config {
|
||||
margin-bottom: 24px;
|
||||
width: 600px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<app-route route="[[route]]" pattern="/addon/:slug" data="{{routeData}}" active="{{routeMatches}}"></app-route>
|
||||
<app-header-layout has-scrolling-region="">
|
||||
<app-header fixed="" slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button hassio narrow="[[narrow]]" show-menu="[[showMenu]]"></ha-menu-button>
|
||||
<paper-icon-button icon="hassio:arrow-left" on-click="backTapped"></paper-icon-button>
|
||||
<div main-title="">Hass.io: add-on details</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<div class="content">
|
||||
<hassio-addon-info hass="[[hass]]" addon="[[addon]]" addon-slug="[[routeData.slug]]"></hassio-addon-info>
|
||||
hassio-addon-logs {
|
||||
max-width: calc(100% - 8px);
|
||||
min-width: 600px;
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
hassio-addon-info,
|
||||
hassio-addon-network,
|
||||
hassio-addon-audio,
|
||||
hassio-addon-config,
|
||||
hassio-addon-logs {
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/addon/:slug"
|
||||
data="{{routeData}}"
|
||||
active="{{routeMatches}}"
|
||||
></app-route>
|
||||
<app-header-layout has-scrolling-region="">
|
||||
<app-header fixed="" slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
hassio
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<paper-icon-button
|
||||
icon="hassio:arrow-left"
|
||||
on-click="backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">Hass.io: add-on details</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<div class="content">
|
||||
<hassio-addon-info
|
||||
hass="[[hass]]"
|
||||
addon="[[addon]]"
|
||||
addon-slug="[[routeData.slug]]"
|
||||
></hassio-addon-info>
|
||||
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
<hassio-addon-config hass="[[hass]]" addon="[[addon]]" addon-slug="[[routeData.slug]]"></hassio-addon-config>
|
||||
<template is="dom-if" if="[[addon.version]]">
|
||||
<hassio-addon-config
|
||||
hass="[[hass]]"
|
||||
addon="[[addon]]"
|
||||
addon-slug="[[routeData.slug]]"
|
||||
></hassio-addon-config>
|
||||
|
||||
<template is="dom-if" if="[[addon.audio]]">
|
||||
<hassio-addon-audio hass="[[hass]]" addon="[[addon]]"></hassio-addon-audio>
|
||||
<template is="dom-if" if="[[addon.audio]]">
|
||||
<hassio-addon-audio
|
||||
hass="[[hass]]"
|
||||
addon="[[addon]]"
|
||||
></hassio-addon-audio>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[addon.network]]">
|
||||
<hassio-addon-network
|
||||
hass="[[hass]]"
|
||||
addon="[[addon]]"
|
||||
addon-slug="[[routeData.slug]]"
|
||||
></hassio-addon-network>
|
||||
</template>
|
||||
|
||||
<hassio-addon-logs
|
||||
hass="[[hass]]"
|
||||
addon-slug="[[routeData.slug]]"
|
||||
></hassio-addon-logs>
|
||||
</template>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
|
||||
<template is="dom-if" if="[[addon.network]]">
|
||||
<hassio-addon-network hass="[[hass]]" addon="[[addon]]" addon-slug="[[routeData.slug]]"></hassio-addon-network>
|
||||
</template>
|
||||
|
||||
<hassio-addon-logs hass="[[hass]]" addon-slug="[[routeData.slug]]"></hassio-addon-logs>
|
||||
</template>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
|
||||
<hassio-markdown-dialog title="[[markdownTitle]]" content="[[markdownContent]]"></hassio-markdown-dialog>
|
||||
`;
|
||||
<hassio-markdown-dialog
|
||||
title="[[markdownTitle]]"
|
||||
content="[[markdownContent]]"
|
||||
></hassio-markdown-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,54 +7,62 @@ import "../../../src/components/ha-relative-time";
|
||||
class HassioCardContent extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
iron-icon {
|
||||
margin-right: 16px;
|
||||
margin-top: 16px;
|
||||
float: left;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
iron-icon.update {
|
||||
color: var(--paper-orange-400);
|
||||
}
|
||||
iron-icon.running,
|
||||
iron-icon.installed {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
iron-icon.hassupdate,
|
||||
iron-icon.snapshot {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
.title {
|
||||
color: var(--primary-text-color);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
.addition {
|
||||
color: var(--secondary-text-color);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 2.4em;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
ha-relative-time {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<iron-icon icon="[[icon]]" class\$="[[iconClass]]" title="[[iconTitle]]"></iron-icon>
|
||||
<div>
|
||||
<div class="title">[[title]]</div>
|
||||
<div class="addition">
|
||||
<template is="dom-if" if="[[description]]">
|
||||
[[description]]
|
||||
</template>
|
||||
<template is="dom-if" if="[[datetime]]">
|
||||
<ha-relative-time hass="[[hass]]" class="addition" datetime="[[datetime]]"></ha-relative-time>
|
||||
</template>
|
||||
<style>
|
||||
iron-icon {
|
||||
margin-right: 16px;
|
||||
margin-top: 16px;
|
||||
float: left;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
iron-icon.update {
|
||||
color: var(--paper-orange-400);
|
||||
}
|
||||
iron-icon.running,
|
||||
iron-icon.installed {
|
||||
color: var(--paper-green-400);
|
||||
}
|
||||
iron-icon.hassupdate,
|
||||
iron-icon.snapshot {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
.title {
|
||||
color: var(--primary-text-color);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
.addition {
|
||||
color: var(--secondary-text-color);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 2.4em;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
ha-relative-time {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<iron-icon
|
||||
icon="[[icon]]"
|
||||
class\$="[[iconClass]]"
|
||||
title="[[iconTitle]]"
|
||||
></iron-icon>
|
||||
<div>
|
||||
<div class="title">[[title]]</div>
|
||||
<div class="addition">
|
||||
<template is="dom-if" if="[[description]]">
|
||||
[[description]]
|
||||
</template>
|
||||
<template is="dom-if" if="[[datetime]]">
|
||||
<ha-relative-time
|
||||
hass="[[hass]]"
|
||||
class="addition"
|
||||
datetime="[[datetime]]"
|
||||
></ha-relative-time>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,29 +9,43 @@ import NavigateMixin from "../../../src/mixins/navigate-mixin";
|
||||
class HassioAddons extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style hassio-style">
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<div class="content card-group">
|
||||
<div class="title">Add-ons</div>
|
||||
<template is="dom-if" if="[[!addons.length]]">
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
You don't have any add-ons installed yet. Head over to <a href="#" on-click="openStore">the add-on store</a> to get started!
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[addons]]" as="addon" sort="sortAddons">
|
||||
<paper-card on-click="addonTapped">
|
||||
<div class="card-content">
|
||||
<hassio-card-content hass="[[hass]]" title="[[addon.name]]" description="[[addon.description]]" icon="[[computeIcon(addon)]]" icon-title="[[computeIconTitle(addon)]]" icon-class="[[computeIconClass(addon)]]"></hassio-card-content>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
<style include="ha-style hassio-style">
|
||||
paper-card {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<div class="content card-group">
|
||||
<div class="title">Add-ons</div>
|
||||
<template is="dom-if" if="[[!addons.length]]">
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
You don't have any add-ons installed yet. Head over to
|
||||
<a href="#" on-click="openStore">the add-on store</a> to get
|
||||
started!
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[addons]]"
|
||||
as="addon"
|
||||
sort="sortAddons"
|
||||
>
|
||||
<paper-card on-click="addonTapped">
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="[[addon.name]]"
|
||||
description="[[addon.description]]"
|
||||
icon="[[computeIcon(addon)]]"
|
||||
icon-title="[[computeIconTitle(addon)]]"
|
||||
icon-class="[[computeIconClass(addon)]]"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -8,16 +8,22 @@ import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
class HassioDashboard extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<hassio-hass-update hass="[[hass]]" hass-info="[[hassInfo]]"></hassio-hass-update>
|
||||
<hassio-addons hass="[[hass]]" addons="[[supervisorInfo.addons]]"></hassio-addons>
|
||||
</div>
|
||||
`;
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<hassio-hass-update
|
||||
hass="[[hass]]"
|
||||
hass-info="[[hassInfo]]"
|
||||
></hassio-hass-update>
|
||||
<hassio-addons
|
||||
hass="[[hass]]"
|
||||
addons="[[supervisorInfo.addons]]"
|
||||
></hassio-addons>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,40 +10,60 @@ import "../resources/hassio-style";
|
||||
class HassioHassUpdate extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style hassio-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[computeUpdateAvailable(hassInfo)]]">
|
||||
<div class="content">
|
||||
<div class="card-group">
|
||||
<div class="title">Update available! 🎉</div>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<hassio-card-content hass="[[hass]]" title="Home Assistant [[hassInfo.last_version]] is available" description="You are currently running version [[hassInfo.version]]" icon="hassio:home-assistant" icon-class="hassupdate"></hassio-card-content>
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="error">Error: [[error]]</div>
|
||||
</template>
|
||||
<p><a href='https://www.home-assistant.io/latest-release-notes/' target='_blank'>Read the release notes</a></p>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/homeassistant/update">Update</ha-call-api-button>
|
||||
<a href="https://github.com/home-assistant/home-assistant/releases" target="_blank"><paper-button>Release notes</paper-button></a>
|
||||
</div>
|
||||
</paper-card>
|
||||
<style include="ha-style hassio-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[computeUpdateAvailable(hassInfo)]]">
|
||||
<div class="content">
|
||||
<div class="card-group">
|
||||
<div class="title">Update available! 🎉</div>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="Home Assistant [[hassInfo.last_version]] is available"
|
||||
description="You are currently running version [[hassInfo.version]]"
|
||||
icon="hassio:home-assistant"
|
||||
icon-class="hassupdate"
|
||||
></hassio-card-content>
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="error">Error: [[error]]</div>
|
||||
</template>
|
||||
<p>
|
||||
<a
|
||||
href="https://www.home-assistant.io/latest-release-notes/"
|
||||
target="_blank"
|
||||
>Read the release notes</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/homeassistant/update"
|
||||
>Update</ha-call-api-button
|
||||
>
|
||||
<a
|
||||
href="https://github.com/home-assistant/home-assistant/releases"
|
||||
target="_blank"
|
||||
><paper-button>Release notes</paper-button></a
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,10 +7,15 @@ import "./resources/hassio-icons";
|
||||
class HassioApp extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<template is="dom-if" if="[[hass]]">
|
||||
<hassio-main hass="[[hass]]" narrow="[[narrow]]" show-menu="[[showMenu]]" route="[[route]]"></hassio-main>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[hass]]">
|
||||
<hassio-main
|
||||
hass="[[hass]]"
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
route="[[route]]"
|
||||
></hassio-main>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,22 +14,48 @@ import NavigateMixin from "../../src/mixins/navigate-mixin";
|
||||
class HassioMain extends EventsMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<app-route route="[[route]]" pattern="/:page" data="{{routeData}}"></app-route>
|
||||
<hassio-data id="data" hass="[[hass]]" supervisor="{{supervisorInfo}}" homeassistant="{{hassInfo}}" host="{{hostInfo}}"></hassio-data>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/:page"
|
||||
data="{{routeData}}"
|
||||
></app-route>
|
||||
<hassio-data
|
||||
id="data"
|
||||
hass="[[hass]]"
|
||||
supervisor="{{supervisorInfo}}"
|
||||
homeassistant="{{hassInfo}}"
|
||||
host="{{hostInfo}}"
|
||||
></hassio-data>
|
||||
|
||||
<template is="dom-if" if="[[!loaded]]">
|
||||
<hass-loading-screen narrow="[[narrow]]" show-menu="[[showMenu]]"></hass-loading-screen>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!loaded]]">
|
||||
<hass-loading-screen
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></hass-loading-screen>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[loaded]]">
|
||||
<template is="dom-if" if="[[!equalsAddon(routeData.page)]]">
|
||||
<hassio-pages-with-tabs hass="[[hass]]" narrow="[[narrow]]" show-menu="[[showMenu]]" page="[[routeData.page]]" supervisor-info="[[supervisorInfo]]" hass-info="[[hassInfo]]" host-info="[[hostInfo]]"></hassio-pages-with-tabs>
|
||||
<template is="dom-if" if="[[loaded]]">
|
||||
<template is="dom-if" if="[[!equalsAddon(routeData.page)]]">
|
||||
<hassio-pages-with-tabs
|
||||
hass="[[hass]]"
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
page="[[routeData.page]]"
|
||||
supervisor-info="[[supervisorInfo]]"
|
||||
hass-info="[[hassInfo]]"
|
||||
host-info="[[hostInfo]]"
|
||||
></hassio-pages-with-tabs>
|
||||
</template>
|
||||
<template is="dom-if" if="[[equalsAddon(routeData.page)]]">
|
||||
<hassio-addon-view
|
||||
hass="[[hass]]"
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
route="[[route]]"
|
||||
></hassio-addon-view>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[equalsAddon(routeData.page)]]">
|
||||
<hassio-addon-view hass="[[hass]]" narrow="[[narrow]]" show-menu="[[showMenu]]" route="[[route]]"></hassio-addon-view>
|
||||
</template>
|
||||
</template>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,55 +11,58 @@ import "../../src/resources/ha-style";
|
||||
class HassioMarkdownDialog extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style-dialog">
|
||||
paper-dialog {
|
||||
min-width: 350px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
app-toolbar {
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
color: var(--primary-text-color);
|
||||
background-color: var(--secondary-background-color);
|
||||
}
|
||||
app-toolbar [main-title] {
|
||||
margin-left: 16px;
|
||||
}
|
||||
paper-checkbox {
|
||||
display: block;
|
||||
margin: 4px;
|
||||
}
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
<style include="ha-style-dialog">
|
||||
paper-dialog {
|
||||
max-height: 100%;
|
||||
}
|
||||
paper-dialog::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: inherit;
|
||||
min-width: 350px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
app-toolbar {
|
||||
color: var(--text-primary-color);
|
||||
background-color: var(--primary-color);
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
color: var(--primary-text-color);
|
||||
background-color: var(--secondary-background-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" with-backdrop="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hassio:close" dialog-dismiss=""></paper-icon-button>
|
||||
<div main-title="">[[title]]</div>
|
||||
</app-toolbar>
|
||||
<paper-dialog-scrollable>
|
||||
<ha-markdown content="[[content]]"></ha-markdown>
|
||||
</paper-dialog-scrollable>
|
||||
</paper-dialog>
|
||||
`;
|
||||
app-toolbar [main-title] {
|
||||
margin-left: 16px;
|
||||
}
|
||||
paper-checkbox {
|
||||
display: block;
|
||||
margin: 4px;
|
||||
}
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
paper-dialog {
|
||||
max-height: 100%;
|
||||
}
|
||||
paper-dialog::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: inherit;
|
||||
}
|
||||
app-toolbar {
|
||||
color: var(--text-primary-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" with-backdrop="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hassio:close"
|
||||
dialog-dismiss=""
|
||||
></paper-icon-button>
|
||||
<div main-title="">[[title]]</div>
|
||||
</app-toolbar>
|
||||
<paper-dialog-scrollable>
|
||||
<ha-markdown content="[[content]]"></ha-markdown>
|
||||
</paper-dialog-scrollable>
|
||||
</paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -23,53 +23,85 @@ import NavigateMixin from "../../src/mixins/navigate-mixin";
|
||||
class HassioPagesWithTabs extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-positioning ha-style">
|
||||
: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;
|
||||
}
|
||||
</style>
|
||||
<app-header-layout id="layout" has-scrolling-region>
|
||||
<app-header fixed slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button hassio narrow="[[narrow]]" show-menu="[[showMenu]]"></ha-menu-button>
|
||||
<div main-title>Hass.io</div>
|
||||
<template is="dom-if" if="[[showRefreshButton(page)]]">
|
||||
<paper-icon-button icon="hassio:refresh" on-click="refreshClicked"></paper-icon-button>
|
||||
</template>
|
||||
</app-toolbar>
|
||||
<paper-tabs scrollable="" selected="[[page]]" attr-for-selected="page-name" on-iron-activate="handlePageSelected">
|
||||
<paper-tab page-name="dashboard">Dashboard</paper-tab>
|
||||
<paper-tab page-name="snapshots">Snapshots</paper-tab>
|
||||
<paper-tab page-name="store">Add-on store</paper-tab>
|
||||
<paper-tab page-name="system">System</paper-tab>
|
||||
</paper-tabs>
|
||||
</app-header>
|
||||
<template is="dom-if" if="[[equals(page, "dashboard")]]">
|
||||
<hassio-dashboard hass="[[hass]]" supervisor-info="[[supervisorInfo]]" hass-info="[[hassInfo]]"></hassio-dashboard>
|
||||
</template>
|
||||
<style include="iron-flex iron-positioning ha-style">
|
||||
: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;
|
||||
}
|
||||
</style>
|
||||
<app-header-layout id="layout" has-scrolling-region>
|
||||
<app-header fixed slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
hassio
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>Hass.io</div>
|
||||
<template is="dom-if" if="[[showRefreshButton(page)]]">
|
||||
<paper-icon-button
|
||||
icon="hassio:refresh"
|
||||
on-click="refreshClicked"
|
||||
></paper-icon-button>
|
||||
</template>
|
||||
</app-toolbar>
|
||||
<paper-tabs
|
||||
scrollable=""
|
||||
selected="[[page]]"
|
||||
attr-for-selected="page-name"
|
||||
on-iron-activate="handlePageSelected"
|
||||
>
|
||||
<paper-tab page-name="dashboard">Dashboard</paper-tab>
|
||||
<paper-tab page-name="snapshots">Snapshots</paper-tab>
|
||||
<paper-tab page-name="store">Add-on store</paper-tab>
|
||||
<paper-tab page-name="system">System</paper-tab>
|
||||
</paper-tabs>
|
||||
</app-header>
|
||||
<template is="dom-if" if="[[equals(page, "dashboard")]]">
|
||||
<hassio-dashboard
|
||||
hass="[[hass]]"
|
||||
supervisor-info="[[supervisorInfo]]"
|
||||
hass-info="[[hassInfo]]"
|
||||
></hassio-dashboard>
|
||||
</template>
|
||||
<template is="dom-if" if="[[equals(page, "snapshots")]]">
|
||||
<hassio-snapshots
|
||||
hass="[[hass]]"
|
||||
installed-addons="[[supervisorInfo.addons]]"
|
||||
snapshot-slug="{{snapshotSlug}}"
|
||||
snapshot-deleted="{{snapshotDeleted}}"
|
||||
></hassio-snapshots>
|
||||
</template>
|
||||
<template is="dom-if" if="[[equals(page, "store")]]">
|
||||
<hassio-addon-store hass="[[hass]]"></hassio-addon-store>
|
||||
</template>
|
||||
<template is="dom-if" if="[[equals(page, "system")]]">
|
||||
<hassio-system
|
||||
hass="[[hass]]"
|
||||
supervisor-info="[[supervisorInfo]]"
|
||||
host-info="[[hostInfo]]"
|
||||
></hassio-system>
|
||||
</template>
|
||||
</app-header-layout>
|
||||
|
||||
<hassio-markdown-dialog
|
||||
title="[[markdownTitle]]"
|
||||
content="[[markdownContent]]"
|
||||
></hassio-markdown-dialog>
|
||||
|
||||
<template is="dom-if" if="[[equals(page, "snapshots")]]">
|
||||
<hassio-snapshots hass="[[hass]]" installed-addons="[[supervisorInfo.addons]]" snapshot-slug="{{snapshotSlug}}" snapshot-deleted="{{snapshotDeleted}}"></hassio-snapshots>
|
||||
<hassio-snapshot
|
||||
hass="[[hass]]"
|
||||
snapshot-slug="{{snapshotSlug}}"
|
||||
snapshot-deleted="{{snapshotDeleted}}"
|
||||
></hassio-snapshot>
|
||||
</template>
|
||||
<template is="dom-if" if="[[equals(page, "store")]]">
|
||||
<hassio-addon-store hass="[[hass]]"></hassio-addon-store>
|
||||
</template>
|
||||
<template is="dom-if" if="[[equals(page, "system")]]">
|
||||
<hassio-system hass="[[hass]]" supervisor-info="[[supervisorInfo]]" host-info="[[hostInfo]]"></hassio-system>
|
||||
</template>
|
||||
</app-header-layout>
|
||||
|
||||
<hassio-markdown-dialog title="[[markdownTitle]]" content="[[markdownContent]]"></hassio-markdown-dialog>
|
||||
|
||||
<template is="dom-if" if="[[equals(page, "snapshots")]]">
|
||||
<hassio-snapshot hass="[[hass]]" snapshot-slug="{{snapshotSlug}}" snapshot-deleted="{{snapshotDeleted}}"></hassio-snapshot>
|
||||
</template>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -13,99 +13,130 @@ import "../../../src/resources/ha-style";
|
||||
class HassioSnapshot extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style-dialog">
|
||||
paper-dialog {
|
||||
min-width: 350px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
app-toolbar {
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
color: var(--primary-text-color);
|
||||
background-color: var(--secondary-background-color);
|
||||
}
|
||||
app-toolbar [main-title] {
|
||||
margin-left: 16px;
|
||||
}
|
||||
paper-dialog-scrollable {
|
||||
margin: 0;
|
||||
}
|
||||
paper-checkbox {
|
||||
display: block;
|
||||
margin: 4px;
|
||||
}
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
<style include="ha-style-dialog">
|
||||
paper-dialog {
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
min-width: 350px;
|
||||
font-size: 14px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
app-toolbar {
|
||||
color: var(--text-primary-color);
|
||||
background-color: var(--primary-color);
|
||||
margin: 0;
|
||||
padding: 0 16px;
|
||||
color: var(--primary-text-color);
|
||||
background-color: var(--secondary-background-color);
|
||||
}
|
||||
}
|
||||
.details {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.download {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.warning,
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" with-backdrop="" on-iron-overlay-closed="_dialogClosed">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hassio:close" dialog-dismiss=""></paper-icon-button>
|
||||
<div main-title="">[[_computeName(snapshot)]]</div>
|
||||
</app-toolbar>
|
||||
<div class="details">
|
||||
[[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])<br>
|
||||
[[_formatDatetime(snapshot.date)]]
|
||||
</div>
|
||||
<div>Home Assistant:</div>
|
||||
<paper-checkbox checked="{{restoreHass}}">
|
||||
Home Assistant [[snapshot.homeassistant]]
|
||||
</paper-checkbox>
|
||||
<template is="dom-if" if="[[snapshot.addons.length]]">
|
||||
<div>Folders:</div>
|
||||
<template is="dom-repeat" items="[[snapshot.folders]]">
|
||||
<paper-checkbox checked="{{item.checked}}">
|
||||
[[item.name]]
|
||||
</paper-checkbox>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[snapshot.addons.length]]">
|
||||
<div>Add-ons:</div>
|
||||
<paper-dialog-scrollable>
|
||||
<template is="dom-repeat" items="[[snapshot.addons]]" sort="_sortAddons">
|
||||
app-toolbar [main-title] {
|
||||
margin-left: 16px;
|
||||
}
|
||||
paper-dialog-scrollable {
|
||||
margin: 0;
|
||||
}
|
||||
paper-checkbox {
|
||||
display: block;
|
||||
margin: 4px;
|
||||
}
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
paper-dialog {
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
app-toolbar {
|
||||
color: var(--text-primary-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
.details {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.download {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.warning,
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
</style>
|
||||
<paper-dialog
|
||||
id="dialog"
|
||||
with-backdrop=""
|
||||
on-iron-overlay-closed="_dialogClosed"
|
||||
>
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hassio:close"
|
||||
dialog-dismiss=""
|
||||
></paper-icon-button>
|
||||
<div main-title="">[[_computeName(snapshot)]]</div>
|
||||
</app-toolbar>
|
||||
<div class="details">
|
||||
[[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])<br />
|
||||
[[_formatDatetime(snapshot.date)]]
|
||||
</div>
|
||||
<div>Home Assistant:</div>
|
||||
<paper-checkbox checked="{{restoreHass}}">
|
||||
Home Assistant [[snapshot.homeassistant]]
|
||||
</paper-checkbox>
|
||||
<template is="dom-if" if="[[snapshot.addons.length]]">
|
||||
<div>Folders:</div>
|
||||
<template is="dom-repeat" items="[[snapshot.folders]]">
|
||||
<paper-checkbox checked="{{item.checked}}">
|
||||
[[item.name]]
|
||||
<span class="details">([[item.version]])</span>
|
||||
</paper-checkbox>
|
||||
</template>
|
||||
</paper-dialog-scrollable>
|
||||
</template>
|
||||
<template is="dom-if" if="[[snapshot.protected]]">
|
||||
<paper-input autofocus="" label="Password" type="password" value="{{snapshotPassword}}"></paper-input>
|
||||
</template>
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<p class="error">Error: [[error]]</p>
|
||||
</template>
|
||||
<div class="buttons">
|
||||
<paper-icon-button icon="hassio:delete" on-click="_deleteClicked" class="warning" title="Delete snapshot"></paper-icon-button>
|
||||
<a href="[[_computeDownloadUrl(snapshotSlug)]]" download="[[_computeDownloadName(snapshot)]]">
|
||||
<paper-icon-button icon="hassio:download" class="download" title="Download snapshot"></paper-icon-button>
|
||||
</a>
|
||||
<paper-button on-click="_partialRestoreClicked">Restore selected</paper-button>
|
||||
<template is="dom-if" if="[[_isFullSnapshot(snapshot.type)]]">
|
||||
<paper-button on-click="_fullRestoreClicked">Wipe & restore</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
`;
|
||||
<template is="dom-if" if="[[snapshot.addons.length]]">
|
||||
<div>Add-ons:</div>
|
||||
<paper-dialog-scrollable>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[snapshot.addons]]"
|
||||
sort="_sortAddons"
|
||||
>
|
||||
<paper-checkbox checked="{{item.checked}}">
|
||||
[[item.name]] <span class="details">([[item.version]])</span>
|
||||
</paper-checkbox>
|
||||
</template>
|
||||
</paper-dialog-scrollable>
|
||||
</template>
|
||||
<template is="dom-if" if="[[snapshot.protected]]">
|
||||
<paper-input
|
||||
autofocus=""
|
||||
label="Password"
|
||||
type="password"
|
||||
value="{{snapshotPassword}}"
|
||||
></paper-input>
|
||||
</template>
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<p class="error">Error: [[error]]</p>
|
||||
</template>
|
||||
<div class="buttons">
|
||||
<paper-icon-button
|
||||
icon="hassio:delete"
|
||||
on-click="_deleteClicked"
|
||||
class="warning"
|
||||
title="Delete snapshot"
|
||||
></paper-icon-button>
|
||||
<a
|
||||
href="[[_computeDownloadUrl(snapshotSlug)]]"
|
||||
download="[[_computeDownloadName(snapshot)]]"
|
||||
>
|
||||
<paper-icon-button
|
||||
icon="hassio:download"
|
||||
class="download"
|
||||
title="Download snapshot"
|
||||
></paper-icon-button>
|
||||
</a>
|
||||
<paper-button on-click="_partialRestoreClicked"
|
||||
>Restore selected</paper-button
|
||||
>
|
||||
<template is="dom-if" if="[[_isFullSnapshot(snapshot.type)]]">
|
||||
<paper-button on-click="_fullRestoreClicked"
|
||||
>Wipe & restore</paper-button
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,90 +14,120 @@ import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
class HassioSnapshots extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style hassio-style">
|
||||
paper-radio-group {
|
||||
display: block;
|
||||
}
|
||||
paper-radio-button {
|
||||
padding: 0 0 2px 2px;
|
||||
}
|
||||
paper-radio-button,
|
||||
paper-checkbox,
|
||||
paper-input[type="password"] {
|
||||
display: block;
|
||||
margin: 4px 0 4px 48px;
|
||||
}
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
Create snapshot
|
||||
<div class="description">
|
||||
Snapshots allow you to easily backup and
|
||||
restore all data of your Hass.io instance.
|
||||
<style include="ha-style hassio-style">
|
||||
paper-radio-group {
|
||||
display: block;
|
||||
}
|
||||
paper-radio-button {
|
||||
padding: 0 0 2px 2px;
|
||||
}
|
||||
paper-radio-button,
|
||||
paper-checkbox,
|
||||
paper-input[type="password"] {
|
||||
display: block;
|
||||
margin: 4px 0 4px 48px;
|
||||
}
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<div class="card-group">
|
||||
<div class="title">
|
||||
Create snapshot
|
||||
<div class="description">
|
||||
Snapshots allow you to easily backup and restore all data of your
|
||||
Hass.io instance.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<paper-input autofocus="" label="Name" value="{{snapshotName}}"></paper-input>
|
||||
Type:
|
||||
<paper-radio-group selected="{{snapshotType}}">
|
||||
<paper-radio-button name="full">
|
||||
Full snapshot
|
||||
</paper-radio-button>
|
||||
<paper-radio-button name="partial">
|
||||
Partial snapshot
|
||||
</paper-radio-button>
|
||||
</paper-radio-group>
|
||||
<template is="dom-if" if="[[!_fullSelected(snapshotType)]]">
|
||||
Folders:
|
||||
<template is="dom-repeat" items="[[folderList]]">
|
||||
<paper-checkbox checked="{{item.checked}}">
|
||||
[[item.name]]
|
||||
</paper-checkbox>
|
||||
</template>
|
||||
Add-ons:
|
||||
<template is="dom-repeat" items="[[addonList]]" sort="_sortAddons">
|
||||
<paper-checkbox checked="{{item.checked}}">
|
||||
[[item.name]]
|
||||
</paper-checkbox>
|
||||
</template>
|
||||
</template>
|
||||
Security:
|
||||
<paper-checkbox checked="{{snapshotHasPassword}}">Password protection</paper-checkbox>
|
||||
<template is="dom-if" if="[[snapshotHasPassword]]">
|
||||
<paper-input label="Password" type="password" value="{{snapshotPassword}}"></paper-input>
|
||||
</template>
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<p class="error">[[error]]</p>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button disabled="[[creatingSnapshot]]" on-click="_createSnapshot">Create</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
|
||||
<div class="card-group">
|
||||
<div class="title">Available snapshots</div>
|
||||
<template is="dom-if" if="[[!snapshots.length]]">
|
||||
<paper-card>
|
||||
<div class="card-content">You don't have any snapshots yet.</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[snapshots]]" as="snapshot" sort="_sortSnapshots">
|
||||
<paper-card class="pointer" on-click="_snapshotClicked">
|
||||
<div class="card-content">
|
||||
<hassio-card-content hass="[[hass]]" title="[[_computeName(snapshot)]]" description="[[_computeDetails(snapshot)]]" datetime="[[snapshot.date]]" icon="[[_computeIcon(snapshot.type)]]" icon-class="snapshot"></hassio-card-content>
|
||||
<paper-input
|
||||
autofocus=""
|
||||
label="Name"
|
||||
value="{{snapshotName}}"
|
||||
></paper-input>
|
||||
Type:
|
||||
<paper-radio-group selected="{{snapshotType}}">
|
||||
<paper-radio-button name="full">
|
||||
Full snapshot
|
||||
</paper-radio-button>
|
||||
<paper-radio-button name="partial">
|
||||
Partial snapshot
|
||||
</paper-radio-button>
|
||||
</paper-radio-group>
|
||||
<template is="dom-if" if="[[!_fullSelected(snapshotType)]]">
|
||||
Folders:
|
||||
<template is="dom-repeat" items="[[folderList]]">
|
||||
<paper-checkbox checked="{{item.checked}}">
|
||||
[[item.name]]
|
||||
</paper-checkbox>
|
||||
</template>
|
||||
Add-ons:
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[addonList]]"
|
||||
sort="_sortAddons"
|
||||
>
|
||||
<paper-checkbox checked="{{item.checked}}">
|
||||
[[item.name]]
|
||||
</paper-checkbox>
|
||||
</template>
|
||||
</template>
|
||||
Security:
|
||||
<paper-checkbox checked="{{snapshotHasPassword}}"
|
||||
>Password protection</paper-checkbox
|
||||
>
|
||||
<template is="dom-if" if="[[snapshotHasPassword]]">
|
||||
<paper-input
|
||||
label="Password"
|
||||
type="password"
|
||||
value="{{snapshotPassword}}"
|
||||
></paper-input>
|
||||
</template>
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<p class="error">[[error]]</p>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button
|
||||
disabled="[[creatingSnapshot]]"
|
||||
on-click="_createSnapshot"
|
||||
>Create</paper-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="card-group">
|
||||
<div class="title">Available snapshots</div>
|
||||
<template is="dom-if" if="[[!snapshots.length]]">
|
||||
<paper-card>
|
||||
<div class="card-content">You don't have any snapshots yet.</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[snapshots]]"
|
||||
as="snapshot"
|
||||
sort="_sortSnapshots"
|
||||
>
|
||||
<paper-card class="pointer" on-click="_snapshotClicked">
|
||||
<div class="card-content">
|
||||
<hassio-card-content
|
||||
hass="[[hass]]"
|
||||
title="[[_computeName(snapshot)]]"
|
||||
description="[[_computeDetails(snapshot)]]"
|
||||
datetime="[[snapshot.date]]"
|
||||
icon="[[_computeIcon(snapshot.type)]]"
|
||||
icon-class="snapshot"
|
||||
></hassio-card-content>
|
||||
</div>
|
||||
</paper-card>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,90 +9,110 @@ import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
class HassioHostInfo extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
display: inline-block;
|
||||
width: 400px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.card-content {
|
||||
height: 200px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
@media screen and (max-width: 830px) {
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
margin-top: 8px;
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
width: 400px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
.card-content {
|
||||
height: auto;
|
||||
height: 200px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
}
|
||||
.info {
|
||||
width: 100%;
|
||||
}
|
||||
.info td:nth-child(2) {
|
||||
text-align: right;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
paper-button.info {
|
||||
max-width: calc(50% - 12px);
|
||||
}
|
||||
table.info {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h2>Host system</h2>
|
||||
<table class="info">
|
||||
<tbody><tr>
|
||||
<td>Hostname</td>
|
||||
<td>[[data.hostname]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>System</td>
|
||||
<td>[[data.operating_system]]</td>
|
||||
</tr>
|
||||
<template is="dom-if" if="[[data.deployment]]">
|
||||
<tr>
|
||||
<td>Deployment</td>
|
||||
<td>[[data.deployment]]</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody></table>
|
||||
<paper-button raised on-click="_showHardware" class="info">
|
||||
Hardware
|
||||
</paper-button>
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'hostname')]]">
|
||||
<paper-button raised on-click="_changeHostnameClicked" class="info">
|
||||
Change hostname
|
||||
@media screen and (max-width: 830px) {
|
||||
paper-card {
|
||||
margin-top: 8px;
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.card-content {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
width: 100%;
|
||||
}
|
||||
.info td:nth-child(2) {
|
||||
text-align: right;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
paper-button.info {
|
||||
max-width: calc(50% - 12px);
|
||||
}
|
||||
table.info {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h2>Host system</h2>
|
||||
<table class="info">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Hostname</td>
|
||||
<td>[[data.hostname]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>System</td>
|
||||
<td>[[data.operating_system]]</td>
|
||||
</tr>
|
||||
<template is="dom-if" if="[[data.deployment]]">
|
||||
<tr>
|
||||
<td>Deployment</td>
|
||||
<td>[[data.deployment]]</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
<paper-button raised on-click="_showHardware" class="info">
|
||||
Hardware
|
||||
</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">Error: [[errors]]</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'reboot')]]">
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/host/reboot">Reboot</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'shutdown')]]">
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/host/shutdown">Shutdown</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'hassos')]]">
|
||||
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/hassos/config/sync" title="Load HassOS configs or updates from USB">Import from USB</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_computeUpdateAvailable(_hassOs)]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/hassos/update">Update</ha-call-api-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'hostname')]]">
|
||||
<paper-button raised on-click="_changeHostnameClicked" class="info">
|
||||
Change hostname
|
||||
</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">Error: [[errors]]</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'reboot')]]">
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/host/reboot"
|
||||
>Reboot</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'shutdown')]]">
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/host/shutdown"
|
||||
>Shutdown</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_featureAvailable(data, 'hassos')]]">
|
||||
<ha-call-api-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
path="hassio/hassos/config/sync"
|
||||
title="Load HassOS configs or updates from USB"
|
||||
>Import from USB</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_computeUpdateAvailable(_hassOs)]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/hassos/update"
|
||||
>Update</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,73 +9,96 @@ import EventsMixin from "../../../src/mixins/events-mixin";
|
||||
class HassioSupervisorInfo extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
display: inline-block;
|
||||
width: 400px;
|
||||
}
|
||||
.card-content {
|
||||
height: 200px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
@media screen and (max-width: 830px) {
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
width: 400px;
|
||||
}
|
||||
.card-content {
|
||||
height: auto;
|
||||
height: 200px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
}
|
||||
.info {
|
||||
width: 100%;
|
||||
}
|
||||
.info td:nth-child(2) {
|
||||
text-align: right;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h2>Hass.io supervisor</h2>
|
||||
<table class="info">
|
||||
<tbody><tr>
|
||||
<td>Version</td>
|
||||
<td>
|
||||
[[data.version]]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Latest version</td>
|
||||
<td>[[data.last_version]]</td>
|
||||
</tr>
|
||||
<template is="dom-if" if="[[!_equals(data.channel, "stable")]]">
|
||||
<tr>
|
||||
<td>Channel</td>
|
||||
<td>[[data.channel]]</td>
|
||||
</tr>
|
||||
@media screen and (max-width: 830px) {
|
||||
paper-card {
|
||||
width: 100%;
|
||||
}
|
||||
.card-content {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
width: 100%;
|
||||
}
|
||||
.info td:nth-child(2) {
|
||||
text-align: right;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h2>Hass.io supervisor</h2>
|
||||
<table class="info">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Version</td>
|
||||
<td>[[data.version]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Latest version</td>
|
||||
<td>[[data.last_version]]</td>
|
||||
</tr>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[!_equals(data.channel, "stable")]]"
|
||||
>
|
||||
<tr>
|
||||
<td>Channel</td>
|
||||
<td>[[data.channel]]</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">Error: [[errors]]</div>
|
||||
</template>
|
||||
</tbody></table>
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">Error: [[errors]]</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/supervisor/reload">Reload</ha-call-api-button>
|
||||
<template is="dom-if" if="[[computeUpdateAvailable(data)]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/supervisor/update">Update</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(data.channel, "beta")]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/supervisor/options" data="[[leaveBeta]]">Leave beta channel</ha-call-api-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(data.channel, "stable")]]">
|
||||
<paper-button on-click="_joinBeta" class="warning" title="Get beta updates for Home Assistant (RCs), supervisor and host">Join beta channel</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/supervisor/reload"
|
||||
>Reload</ha-call-api-button
|
||||
>
|
||||
<template is="dom-if" if="[[computeUpdateAvailable(data)]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/supervisor/update"
|
||||
>Update</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(data.channel, "beta")]]"
|
||||
>
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/supervisor/options"
|
||||
data="[[leaveBeta]]"
|
||||
>Leave beta channel</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(data.channel, "stable")]]"
|
||||
>
|
||||
<paper-button
|
||||
on-click="_joinBeta"
|
||||
class="warning"
|
||||
title="Get beta updates for Home Assistant (RCs), supervisor and host"
|
||||
>Join beta channel</paper-button
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,23 +6,21 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HassioSupervisorLog extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<pre>[[log]]</pre>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="refreshTapped">Refresh</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
<style include="ha-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content"><pre>[[log]]</pre></div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="refreshTapped">Refresh</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,26 +9,32 @@ import "./hassio-supervisor-log";
|
||||
class HassioSystem extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin: 4px;
|
||||
}
|
||||
.title {
|
||||
margin-top: 24px;
|
||||
color: var(--primary-text-color);
|
||||
font-size: 2em;
|
||||
padding-left: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<div class="title">Information</div>
|
||||
<hassio-supervisor-info hass="[[hass]]" data="[[supervisorInfo]]"></hassio-supervisor-info>
|
||||
<hassio-host-info hass="[[hass]]" data="[[hostInfo]]"></hassio-host-info>
|
||||
<div class="title">System log</div>
|
||||
<hassio-supervisor-log hass="[[hass]]"></hassio-supervisor-log>
|
||||
</div>
|
||||
`;
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin: 4px;
|
||||
}
|
||||
.title {
|
||||
margin-top: 24px;
|
||||
color: var(--primary-text-color);
|
||||
font-size: 2em;
|
||||
padding-left: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<div class="title">Information</div>
|
||||
<hassio-supervisor-info
|
||||
hass="[[hass]]"
|
||||
data="[[supervisorInfo]]"
|
||||
></hassio-supervisor-info>
|
||||
<hassio-host-info
|
||||
hass="[[hass]]"
|
||||
data="[[hostInfo]]"
|
||||
></hassio-host-info>
|
||||
<div class="title">System log</div>
|
||||
<hassio-supervisor-log hass="[[hass]]"></hassio-supervisor-log>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,54 +7,61 @@ import LocalizeLiteMixin from "../mixins/localize-lite-mixin";
|
||||
class HaAuthFlow extends LocalizeLiteMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
/* So we can set min-height to avoid jumping during loading */
|
||||
display: block;
|
||||
}
|
||||
.action {
|
||||
margin: 24px 0 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
<form>
|
||||
<template is="dom-if" if="[[_equals(_state, "loading")]]">
|
||||
[[localize('ui.panel.page-authorize.form.working')]]:
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_state, "error")]]">
|
||||
<div class='error'>Error: [[_errorMsg]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_state, "step")]]">
|
||||
<template is="dom-if" if="[[_equals(_step.type, "abort")]]">
|
||||
[[localize('ui.panel.page-authorize.abort_intro')]]:
|
||||
<ha-markdown content="[[_computeStepAbortedReason(localize, _step)]]"></ha-markdown>
|
||||
<style>
|
||||
:host {
|
||||
/* So we can set min-height to avoid jumping during loading */
|
||||
display: block;
|
||||
}
|
||||
.action {
|
||||
margin: 24px 0 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
<form>
|
||||
<template is="dom-if" if="[[_equals(_state, "loading")]]">
|
||||
[[localize('ui.panel.page-authorize.form.working')]]:
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(_step.type, "form")]]">
|
||||
<template is="dom-if" if="[[_computeStepDescription(localize, _step)]]">
|
||||
<ha-markdown content="[[_computeStepDescription(localize, _step)]]" allow-svg></ha-markdown>
|
||||
<template is="dom-if" if="[[_equals(_state, "error")]]">
|
||||
<div class="error">Error: [[_errorMsg]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_state, "step")]]">
|
||||
<template is="dom-if" if="[[_equals(_step.type, "abort")]]">
|
||||
[[localize('ui.panel.page-authorize.abort_intro')]]:
|
||||
<ha-markdown
|
||||
content="[[_computeStepAbortedReason(localize, _step)]]"
|
||||
></ha-markdown>
|
||||
</template>
|
||||
|
||||
<ha-form
|
||||
data="{{_stepData}}"
|
||||
schema="[[_step.data_schema]]"
|
||||
error="[[_step.errors]]"
|
||||
compute-label="[[_computeLabelCallback(localize, _step)]]"
|
||||
compute-error="[[_computeErrorCallback(localize, _step)]]"
|
||||
></ha-form>
|
||||
<template is="dom-if" if="[[_equals(_step.type, "form")]]">
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_computeStepDescription(localize, _step)]]"
|
||||
>
|
||||
<ha-markdown
|
||||
content="[[_computeStepDescription(localize, _step)]]"
|
||||
allow-svg
|
||||
></ha-markdown>
|
||||
</template>
|
||||
|
||||
<ha-form
|
||||
data="{{_stepData}}"
|
||||
schema="[[_step.data_schema]]"
|
||||
error="[[_step.errors]]"
|
||||
compute-label="[[_computeLabelCallback(localize, _step)]]"
|
||||
compute-error="[[_computeErrorCallback(localize, _step)]]"
|
||||
></ha-form>
|
||||
</template>
|
||||
<div class="action">
|
||||
<paper-button raised on-click="_handleSubmit"
|
||||
>[[_computeSubmitCaption(_step.type)]]</paper-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<div class='action'>
|
||||
<paper-button
|
||||
raised
|
||||
on-click='_handleSubmit'
|
||||
>[[_computeSubmitCaption(_step.type)]]</paper-button>
|
||||
</div>
|
||||
</template>
|
||||
</form>
|
||||
`;
|
||||
</form>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,49 +12,51 @@ import "./ha-auth-flow";
|
||||
class HaAuthorize extends LocalizeLiteMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
ha-markdown {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
ha-markdown a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
ha-markdown p:last-child{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ha-pick-auth-provider {
|
||||
display: block;
|
||||
margin-top: 48px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
ha-markdown {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
ha-markdown a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
ha-markdown p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ha-pick-auth-provider {
|
||||
display: block;
|
||||
margin-top: 48px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[!_authProviders]]">
|
||||
<p>[[localize('ui.panel.page-authorize.initializing')]]</p>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_authProviders]]">
|
||||
<p>[[localize('ui.panel.page-authorize.initializing')]]</p>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_authProviders]]">
|
||||
<ha-markdown content='[[_computeIntro(localize, clientId, _authProvider)]]'></ha-markdown>
|
||||
<template is="dom-if" if="[[_authProviders]]">
|
||||
<ha-markdown
|
||||
content="[[_computeIntro(localize, clientId, _authProvider)]]"
|
||||
></ha-markdown>
|
||||
|
||||
<ha-auth-flow
|
||||
resources="[[resources]]"
|
||||
client-id="[[clientId]]"
|
||||
redirect-uri="[[redirectUri]]"
|
||||
oauth2-state="[[oauth2State]]"
|
||||
auth-provider="[[_authProvider]]"
|
||||
step="{{step}}"
|
||||
></ha-auth-flow>
|
||||
|
||||
<template is="dom-if" if="[[_computeMultiple(_authProviders)]]">
|
||||
<ha-pick-auth-provider
|
||||
<ha-auth-flow
|
||||
resources="[[resources]]"
|
||||
client-id="[[clientId]]"
|
||||
auth-providers="[[_computeInactiveProvders(_authProvider, _authProviders)]]"
|
||||
on-pick="_handleAuthProviderPick"
|
||||
></ha-pick-auth-provider>
|
||||
redirect-uri="[[redirectUri]]"
|
||||
oauth2-state="[[oauth2State]]"
|
||||
auth-provider="[[_authProvider]]"
|
||||
step="{{step}}"
|
||||
></ha-auth-flow>
|
||||
|
||||
<template is="dom-if" if="[[_computeMultiple(_authProviders)]]">
|
||||
<ha-pick-auth-provider
|
||||
resources="[[resources]]"
|
||||
client-id="[[clientId]]"
|
||||
auth-providers="[[_computeInactiveProvders(_authProvider, _authProviders)]]"
|
||||
on-pick="_handleAuthProviderPick"
|
||||
></ha-pick-auth-provider>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,22 +14,22 @@ class HaPickAuthProvider extends EventsMixin(
|
||||
) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
p {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
<p>[[localize('ui.panel.page-authorize.pick_auth_provider')]]:</p>
|
||||
<template is="dom-repeat" items="[[authProviders]]">
|
||||
<paper-item on-click="_handlePick">
|
||||
<paper-item-body>[[item.name]]</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
`;
|
||||
<style>
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
p {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
<p>[[localize('ui.panel.page-authorize.pick_auth_provider')]]:</p>
|
||||
<template is="dom-repeat" items="[[authProviders]]">
|
||||
<paper-item on-click="_handlePick">
|
||||
<paper-item-body>[[item.name]]</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,16 +6,19 @@ import "../components/entity/ha-state-label-badge";
|
||||
class HaBadgesCard extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
ha-state-label-badge {
|
||||
display: inline-block;
|
||||
margin-bottom: var(--ha-state-label-badge-margin-bottom, 16px);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-repeat" items="[[states]]">
|
||||
<ha-state-label-badge hass="[[hass]]" state="[[item]]"></ha-state-label-badge>
|
||||
</template>
|
||||
`;
|
||||
<style>
|
||||
ha-state-label-badge {
|
||||
display: inline-block;
|
||||
margin-bottom: var(--ha-state-label-badge-margin-bottom, 16px);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-repeat" items="[[states]]">
|
||||
<ha-state-label-badge
|
||||
hass="[[hass]]"
|
||||
state="[[item]]"
|
||||
></ha-state-label-badge>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,51 +14,55 @@ const UPDATE_INTERVAL = 10000; // ms
|
||||
class HaCameraCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="paper-material-styles">
|
||||
:host {
|
||||
@apply --paper-material-elevation-1;
|
||||
display: block;
|
||||
position: relative;
|
||||
font-size: 0px;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
min-height: 48px;
|
||||
line-height: 0;
|
||||
}
|
||||
.camera-feed {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.caption {
|
||||
@apply --paper-font-common-nowrap;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
<style include="paper-material-styles">
|
||||
:host {
|
||||
@apply --paper-material-elevation-1;
|
||||
display: block;
|
||||
position: relative;
|
||||
font-size: 0px;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
min-height: 48px;
|
||||
line-height: 0;
|
||||
}
|
||||
.camera-feed {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.caption {
|
||||
@apply --paper-font-common-nowrap;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
padding: 16px;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
padding: 16px;
|
||||
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[cameraFeedSrc]]">
|
||||
<img src="[[cameraFeedSrc]]" class="camera-feed" alt="[[_computeStateName(stateObj)]]">
|
||||
</template>
|
||||
<div class="caption">
|
||||
[[_computeStateName(stateObj)]]
|
||||
<template is="dom-if" if="[[!imageLoaded]]">
|
||||
([[localize('ui.card.camera.not_available')]])
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
<template is="dom-if" if="[[cameraFeedSrc]]">
|
||||
<img
|
||||
src="[[cameraFeedSrc]]"
|
||||
class="camera-feed"
|
||||
alt="[[_computeStateName(stateObj)]]"
|
||||
/>
|
||||
</template>
|
||||
<div class="caption">
|
||||
[[_computeStateName(stateObj)]]
|
||||
<template is="dom-if" if="[[!imageLoaded]]">
|
||||
([[localize('ui.card.camera.not_available')]])
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -16,54 +16,68 @@ import LocalizeMixin from "../mixins/localize-mixin";
|
||||
class HaEntitiesCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
ha-card {
|
||||
padding: 16px;
|
||||
}
|
||||
.states {
|
||||
margin: -4px 0;
|
||||
}
|
||||
.state {
|
||||
padding: 4px 0;
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
/* overwriting line-height +8 because entity-toggle can be 40px height,
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
ha-card {
|
||||
padding: 16px;
|
||||
}
|
||||
.states {
|
||||
margin: -4px 0;
|
||||
}
|
||||
.state {
|
||||
padding: 4px 0;
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
/* overwriting line-height +8 because entity-toggle can be 40px height,
|
||||
compensating this with reduced padding */
|
||||
line-height: 40px;
|
||||
color: var(--primary-text-color);
|
||||
padding: 4px 0 12px;
|
||||
}
|
||||
.header .name {
|
||||
@apply --paper-font-common-nowrap;
|
||||
}
|
||||
ha-entity-toggle {
|
||||
margin-left: 16px;
|
||||
}
|
||||
.more-info {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
line-height: 40px;
|
||||
color: var(--primary-text-color);
|
||||
padding: 4px 0 12px;
|
||||
}
|
||||
.header .name {
|
||||
@apply --paper-font-common-nowrap;
|
||||
}
|
||||
ha-entity-toggle {
|
||||
margin-left: 16px;
|
||||
}
|
||||
.more-info {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-card>
|
||||
<template is="dom-if" if="[[title]]">
|
||||
<div class$="[[computeTitleClass(groupEntity)]]" on-click="entityTapped">
|
||||
<div class="flex name">[[title]]</div>
|
||||
<template is="dom-if" if="[[showGroupToggle(groupEntity, states)]]">
|
||||
<ha-entity-toggle hass="[[hass]]" state-obj="[[groupEntity]]"></ha-entity-toggle>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<div class="states">
|
||||
<template is="dom-repeat" items="[[states]]" on-dom-change="addTapEvents">
|
||||
<div class$="[[computeStateClass(item)]]">
|
||||
<state-card-content hass="[[hass]]" class="state-card" state-obj="[[item]]"></state-card-content>
|
||||
<ha-card>
|
||||
<template is="dom-if" if="[[title]]">
|
||||
<div
|
||||
class$="[[computeTitleClass(groupEntity)]]"
|
||||
on-click="entityTapped"
|
||||
>
|
||||
<div class="flex name">[[title]]</div>
|
||||
<template is="dom-if" if="[[showGroupToggle(groupEntity, states)]]">
|
||||
<ha-entity-toggle
|
||||
hass="[[hass]]"
|
||||
state-obj="[[groupEntity]]"
|
||||
></ha-entity-toggle>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
<div class="states">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[states]]"
|
||||
on-dom-change="addTapEvents"
|
||||
>
|
||||
<div class$="[[computeStateClass(item)]]">
|
||||
<state-card-content
|
||||
hass="[[hass]]"
|
||||
class="state-card"
|
||||
state-obj="[[item]]"
|
||||
></state-card-content>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,39 +14,56 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaHistoryGraphCard extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-card:not([dialog]) .content {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
paper-card[dialog] {
|
||||
padding-top: 16px;
|
||||
background-color: transparent;
|
||||
}
|
||||
paper-card {
|
||||
width: 100%;
|
||||
/* prevent new stacking context, chart tooltip needs to overflow */
|
||||
position: static;
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
line-height: 40px;
|
||||
color: var(--primary-text-color);
|
||||
padding: 20px 16px 12px;
|
||||
@apply --paper-font-common-nowrap;
|
||||
}
|
||||
paper-card[dialog] .header {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<ha-state-history-data hass="[[hass]]" filter-type="recent-entity" entity-id="[[computeHistoryEntities(stateObj)]]" data="{{stateHistory}}" is-loading="{{stateHistoryLoading}}" cache-config="[[cacheConfig]]"></ha-state-history-data>
|
||||
<paper-card dialog$="[[inDialog]]" on-click="cardTapped" elevation="[[computeElevation(inDialog)]]">
|
||||
<div class="header">[[computeTitle(stateObj)]]</div>
|
||||
<div class="content">
|
||||
<state-history-charts hass="[[hass]]" history-data="[[stateHistory]]" is-loading-data="[[stateHistoryLoading]]" up-to-now no-single>
|
||||
</state-history-charts>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
<style>
|
||||
paper-card:not([dialog]) .content {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
paper-card[dialog] {
|
||||
padding-top: 16px;
|
||||
background-color: transparent;
|
||||
}
|
||||
paper-card {
|
||||
width: 100%;
|
||||
/* prevent new stacking context, chart tooltip needs to overflow */
|
||||
position: static;
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
line-height: 40px;
|
||||
color: var(--primary-text-color);
|
||||
padding: 20px 16px 12px;
|
||||
@apply --paper-font-common-nowrap;
|
||||
}
|
||||
paper-card[dialog] .header {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<ha-state-history-data
|
||||
hass="[[hass]]"
|
||||
filter-type="recent-entity"
|
||||
entity-id="[[computeHistoryEntities(stateObj)]]"
|
||||
data="{{stateHistory}}"
|
||||
is-loading="{{stateHistoryLoading}}"
|
||||
cache-config="[[cacheConfig]]"
|
||||
></ha-state-history-data>
|
||||
<paper-card
|
||||
dialog$="[[inDialog]]"
|
||||
on-click="cardTapped"
|
||||
elevation="[[computeElevation(inDialog)]]"
|
||||
>
|
||||
<div class="header">[[computeTitle(stateObj)]]</div>
|
||||
<div class="content">
|
||||
<state-history-charts
|
||||
hass="[[hass]]"
|
||||
history-data="[[stateHistory]]"
|
||||
is-loading-data="[[stateHistoryLoading]]"
|
||||
up-to-now
|
||||
no-single
|
||||
>
|
||||
</state-history-charts>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,169 +18,200 @@ import LocalizeMixin from "../mixins/localize-mixin";
|
||||
class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="paper-material-styles iron-flex iron-flex-alignment iron-positioning">
|
||||
:host {
|
||||
@apply --paper-material-elevation-1;
|
||||
display: block;
|
||||
position: relative;
|
||||
font-size: 0px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
<style
|
||||
include="paper-material-styles iron-flex iron-flex-alignment iron-positioning"
|
||||
>
|
||||
:host {
|
||||
@apply --paper-material-elevation-1;
|
||||
display: block;
|
||||
position: relative;
|
||||
font-size: 0px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
background-color: white;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
.banner {
|
||||
position: relative;
|
||||
background-color: white;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
|
||||
.banner:before {
|
||||
display: block;
|
||||
content: "";
|
||||
width: 100%;
|
||||
/* removed .25% from 16:9 ratio to fix YT black bars */
|
||||
padding-top: 56%;
|
||||
transition: padding-top .8s;
|
||||
}
|
||||
.banner:before {
|
||||
display: block;
|
||||
content: "";
|
||||
width: 100%;
|
||||
/* removed .25% from 16:9 ratio to fix YT black bars */
|
||||
padding-top: 56%;
|
||||
transition: padding-top 0.8s;
|
||||
}
|
||||
|
||||
.banner.no-cover {
|
||||
background-position: center center;
|
||||
background-image: url(/static/images/card_media_player_bg.png);
|
||||
background-repeat: no-repeat;
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
.banner.no-cover {
|
||||
background-position: center center;
|
||||
background-image: url(/static/images/card_media_player_bg.png);
|
||||
background-repeat: no-repeat;
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.banner.content-type-music:before {
|
||||
padding-top: 100%;
|
||||
}
|
||||
.banner.content-type-music:before {
|
||||
padding-top: 100%;
|
||||
}
|
||||
|
||||
.banner.no-cover:before {
|
||||
padding-top: 88px;
|
||||
}
|
||||
.banner.no-cover:before {
|
||||
padding-top: 88px;
|
||||
}
|
||||
|
||||
.banner > .cover {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
.banner > .cover {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
transition: opacity .8s;
|
||||
opacity: 1;
|
||||
}
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
transition: opacity 0.8s;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.banner.is-off > .cover {
|
||||
opacity: 0;
|
||||
}
|
||||
.banner.is-off > .cover {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.banner > .caption {
|
||||
@apply --paper-font-caption;
|
||||
.banner > .caption {
|
||||
@apply --paper-font-caption;
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
background-color: rgba(0, 0, 0, var(--dark-secondary-opacity));
|
||||
background-color: rgba(0, 0, 0, var(--dark-secondary-opacity));
|
||||
|
||||
padding: 8px 16px;
|
||||
padding: 8px 16px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
|
||||
transition: background-color .5s;
|
||||
}
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
.banner.is-off > .caption {
|
||||
background-color: initial;
|
||||
}
|
||||
.banner.is-off > .caption {
|
||||
background-color: initial;
|
||||
}
|
||||
|
||||
.banner > .caption .title {
|
||||
@apply --paper-font-common-nowrap;
|
||||
font-size: 1.2em;
|
||||
margin: 8px 0 4px;
|
||||
}
|
||||
.banner > .caption .title {
|
||||
@apply --paper-font-common-nowrap;
|
||||
font-size: 1.2em;
|
||||
margin: 8px 0 4px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
width: 100%;
|
||||
height: var(--paper-progress-height, 4px);
|
||||
margin-top: calc(-1*var(--paper-progress-height, 4px));
|
||||
--paper-progress-active-color: var(--accent-color);
|
||||
--paper-progress-container-color: rgba(200,200,200,0.5);
|
||||
}
|
||||
.progress {
|
||||
width: 100%;
|
||||
height: var(--paper-progress-height, 4px);
|
||||
margin-top: calc(-1 * var(--paper-progress-height, 4px));
|
||||
--paper-progress-active-color: var(--accent-color);
|
||||
--paper-progress-container-color: rgba(200, 200, 200, 0.5);
|
||||
}
|
||||
|
||||
.controls {
|
||||
position: relative;
|
||||
@apply --paper-font-body1;
|
||||
padding: 8px;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
}
|
||||
.controls {
|
||||
position: relative;
|
||||
@apply --paper-font-body1;
|
||||
padding: 8px;
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
}
|
||||
|
||||
.controls paper-icon-button {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.controls paper-icon-button {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
paper-icon-button {
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
paper-icon-button {
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
|
||||
paper-icon-button[disabled] {
|
||||
opacity: var(--dark-disabled-opacity);
|
||||
}
|
||||
paper-icon-button[disabled] {
|
||||
opacity: var(--dark-disabled-opacity);
|
||||
}
|
||||
|
||||
paper-icon-button.primary {
|
||||
width: 56px !important;
|
||||
height: 56px !important;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 8px;
|
||||
transition: background-color .5s;
|
||||
}
|
||||
paper-icon-button.primary {
|
||||
width: 56px !important;
|
||||
height: 56px !important;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
padding: 8px;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
paper-icon-button.primary[disabled] {
|
||||
background-color: rgba(0, 0, 0, var(--dark-disabled-opacity));
|
||||
}
|
||||
paper-icon-button.primary[disabled] {
|
||||
background-color: rgba(0, 0, 0, var(--dark-disabled-opacity));
|
||||
}
|
||||
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class$="[[computeBannerClasses(playerObj)]]">
|
||||
<div class="cover" id="cover"></div>
|
||||
<div class$="[[computeBannerClasses(playerObj)]]">
|
||||
<div class="cover" id="cover"></div>
|
||||
|
||||
<div class="caption">
|
||||
[[_computeStateName(stateObj)]]
|
||||
<div class="title">[[computePrimaryText(localize, playerObj)]]</div>
|
||||
[[playerObj.secondaryTitle]]<br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<paper-progress max="[[stateObj.attributes.media_duration]]" value="[[playbackPosition]]" hidden$="[[computeHideProgress(playerObj)]]" class="progress"></paper-progress>
|
||||
|
||||
<div class="controls layout horizontal justified">
|
||||
<paper-icon-button icon="hass:power" on-click="handleTogglePower" invisible$="[[computeHidePowerButton(playerObj)]]" class="self-center secondary"></paper-icon-button>
|
||||
|
||||
<div>
|
||||
<paper-icon-button icon="hass:skip-previous" invisible$="[[!playerObj.supportsPreviousTrack]]" disabled="[[playerObj.isOff]]" on-click="handlePrevious"></paper-icon-button>
|
||||
<paper-icon-button class="primary" icon="[[computePlaybackControlIcon(playerObj)]]" invisible$="[[!computePlaybackControlIcon(playerObj)]]" disabled="[[playerObj.isOff]]" on-click="handlePlaybackControl"></paper-icon-button>
|
||||
<paper-icon-button icon="hass:skip-next" invisible$="[[!playerObj.supportsNextTrack]]" disabled="[[playerObj.isOff]]" on-click="handleNext"></paper-icon-button>
|
||||
<div class="caption">
|
||||
[[_computeStateName(stateObj)]]
|
||||
<div class="title">[[computePrimaryText(localize, playerObj)]]</div>
|
||||
[[playerObj.secondaryTitle]]<br />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<paper-icon-button icon="hass:dots-vertical" on-click="handleOpenMoreInfo" class="self-center secondary"></paper-icon-button>
|
||||
<paper-progress
|
||||
max="[[stateObj.attributes.media_duration]]"
|
||||
value="[[playbackPosition]]"
|
||||
hidden$="[[computeHideProgress(playerObj)]]"
|
||||
class="progress"
|
||||
></paper-progress>
|
||||
|
||||
</div>
|
||||
`;
|
||||
<div class="controls layout horizontal justified">
|
||||
<paper-icon-button
|
||||
icon="hass:power"
|
||||
on-click="handleTogglePower"
|
||||
invisible$="[[computeHidePowerButton(playerObj)]]"
|
||||
class="self-center secondary"
|
||||
></paper-icon-button>
|
||||
|
||||
<div>
|
||||
<paper-icon-button
|
||||
icon="hass:skip-previous"
|
||||
invisible$="[[!playerObj.supportsPreviousTrack]]"
|
||||
disabled="[[playerObj.isOff]]"
|
||||
on-click="handlePrevious"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
class="primary"
|
||||
icon="[[computePlaybackControlIcon(playerObj)]]"
|
||||
invisible$="[[!computePlaybackControlIcon(playerObj)]]"
|
||||
disabled="[[playerObj.isOff]]"
|
||||
on-click="handlePlaybackControl"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:skip-next"
|
||||
invisible$="[[!playerObj.supportsNextTrack]]"
|
||||
disabled="[[playerObj.isOff]]"
|
||||
on-click="handleNext"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
|
||||
<paper-icon-button
|
||||
icon="hass:dots-vertical"
|
||||
on-click="handleOpenMoreInfo"
|
||||
class="self-center secondary"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -15,40 +15,42 @@ import computeObjectId from "../common/entity/compute_object_id";
|
||||
class HaPersistentNotificationCard extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
@apply --paper-font-body1;
|
||||
}
|
||||
ha-markdown {
|
||||
display: block;
|
||||
padding: 0 16px;
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
ha-markdown p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
ha-markdown p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ha-markdown a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
ha-markdown img {
|
||||
max-width: 100%;
|
||||
}
|
||||
paper-button {
|
||||
margin: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
:host {
|
||||
@apply --paper-font-body1;
|
||||
}
|
||||
ha-markdown {
|
||||
display: block;
|
||||
padding: 0 16px;
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
ha-markdown p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
ha-markdown p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
ha-markdown a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
ha-markdown img {
|
||||
max-width: 100%;
|
||||
}
|
||||
paper-button {
|
||||
margin: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-card header="[[computeTitle(stateObj)]]">
|
||||
<ha-markdown content="[[stateObj.attributes.message]]"></ha-markdown>
|
||||
<paper-button on-click="dismissTap">[[localize('ui.card.persistent_notification.dismiss')]]</paper-button>
|
||||
</ha-card>
|
||||
`;
|
||||
<ha-card header="[[computeTitle(stateObj)]]">
|
||||
<ha-markdown content="[[stateObj.attributes.message]]"></ha-markdown>
|
||||
<paper-button on-click="dismissTap"
|
||||
>[[localize('ui.card.persistent_notification.dismiss')]]</paper-button
|
||||
>
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,76 +10,93 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaPlantCard extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.banner {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
padding-top: 12px;
|
||||
}
|
||||
.has-plant-image .banner {
|
||||
padding-top: 30%;
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
line-height: 40px;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
.has-plant-image .header {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
padding: 16px;
|
||||
color: white;
|
||||
width: 100%;
|
||||
background:rgba(0, 0, 0, var(--dark-secondary-opacity));
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 16px 32px 24px 32px;
|
||||
}
|
||||
.has-plant-image .content {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
ha-icon {
|
||||
color: var(--paper-item-icon-color);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.attributes {
|
||||
cursor: pointer;
|
||||
}
|
||||
.attributes div {
|
||||
text-align: center;
|
||||
}
|
||||
.problem {
|
||||
color: var(--google-red-500);
|
||||
font-weight: bold;
|
||||
}
|
||||
.uom {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.banner {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
padding-top: 12px;
|
||||
}
|
||||
.has-plant-image .banner {
|
||||
padding-top: 30%;
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
line-height: 40px;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
.has-plant-image .header {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
padding: 16px;
|
||||
color: white;
|
||||
width: 100%;
|
||||
background: rgba(0, 0, 0, var(--dark-secondary-opacity));
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 16px 32px 24px 32px;
|
||||
}
|
||||
.has-plant-image .content {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
ha-icon {
|
||||
color: var(--paper-item-icon-color);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.attributes {
|
||||
cursor: pointer;
|
||||
}
|
||||
.attributes div {
|
||||
text-align: center;
|
||||
}
|
||||
.problem {
|
||||
color: var(--google-red-500);
|
||||
font-weight: bold;
|
||||
}
|
||||
.uom {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-card class$="[[computeImageClass(stateObj.attributes.entity_picture)]]">
|
||||
<div class="banner" style="background-image:url([[stateObj.attributes.entity_picture]])">
|
||||
<div class="header">[[computeTitle(stateObj)]]</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<template is="dom-repeat" items="[[computeAttributes(stateObj.attributes)]]">
|
||||
<div class="attributes" on-click="attributeClicked">
|
||||
<div><ha-icon icon="[[computeIcon(item, stateObj.attributes.battery)]]"></ha-icon></div>
|
||||
<div class$="[[computeAttributeClass(stateObj.attributes.problem, item)]]">
|
||||
[[computeValue(stateObj.attributes, item)]]
|
||||
<ha-card
|
||||
class$="[[computeImageClass(stateObj.attributes.entity_picture)]]"
|
||||
>
|
||||
<div
|
||||
class="banner"
|
||||
style="background-image:url([[stateObj.attributes.entity_picture]])"
|
||||
>
|
||||
<div class="header">[[computeTitle(stateObj)]]</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[computeAttributes(stateObj.attributes)]]"
|
||||
>
|
||||
<div class="attributes" on-click="attributeClicked">
|
||||
<div>
|
||||
<ha-icon
|
||||
icon="[[computeIcon(item, stateObj.attributes.battery)]]"
|
||||
></ha-icon>
|
||||
</div>
|
||||
<div
|
||||
class$="[[computeAttributeClass(stateObj.attributes.problem, item)]]"
|
||||
>
|
||||
[[computeValue(stateObj.attributes, item)]]
|
||||
</div>
|
||||
<div class="uom">
|
||||
[[computeUom(stateObj.attributes.unit_of_measurement_dict,
|
||||
item)]]
|
||||
</div>
|
||||
</div>
|
||||
<div class="uom">[[computeUom(stateObj.attributes.unit_of_measurement_dict, item)]]</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
</template>
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -106,9 +106,7 @@ class HaWeatherCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
<ha-card>
|
||||
<div class="header">
|
||||
[[computeState(stateObj.state, localize)]]
|
||||
<div class="name">
|
||||
[[stateObj.attributes.friendly_name]]
|
||||
</div>
|
||||
<div class="name">[[stateObj.attributes.friendly_name]]</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="now">
|
||||
@ -117,26 +115,38 @@ class HaWeatherCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
<ha-icon icon="[[getWeatherIcon(stateObj.state)]]"></ha-icon>
|
||||
</template>
|
||||
<div class="temp">
|
||||
[[stateObj.attributes.temperature]]<span>[[getUnit('temperature')]]</span>
|
||||
[[stateObj.attributes.temperature]]<span
|
||||
>[[getUnit('temperature')]]</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attributes">
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.pressure)]]">
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_showValue(stateObj.attributes.pressure)]]"
|
||||
>
|
||||
<div>
|
||||
[[localize('ui.card.weather.attributes.air_pressure')]]:
|
||||
[[stateObj.attributes.pressure]] [[getUnit('air_pressure')]]
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.humidity)]]">
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_showValue(stateObj.attributes.humidity)]]"
|
||||
>
|
||||
<div>
|
||||
[[localize('ui.card.weather.attributes.humidity')]]:
|
||||
[[stateObj.attributes.humidity]] %
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.wind_speed)]]">
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_showValue(stateObj.attributes.wind_speed)]]"
|
||||
>
|
||||
<div>
|
||||
[[localize('ui.card.weather.attributes.wind_speed')]]:
|
||||
[[getWind(stateObj.attributes.wind_speed, stateObj.attributes.wind_bearing, localize)]]
|
||||
[[getWind(stateObj.attributes.wind_speed,
|
||||
stateObj.attributes.wind_bearing, localize)]]
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@ -145,22 +155,31 @@ class HaWeatherCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
<div class="forecast">
|
||||
<template is="dom-repeat" items="[[forecast]]">
|
||||
<div>
|
||||
<div class="weekday">[[computeDate(item.datetime)]]<br>
|
||||
<div class="weekday">
|
||||
[[computeDate(item.datetime)]]<br />
|
||||
<template is="dom-if" if="[[!_showValue(item.templow)]]">
|
||||
[[computeTime(item.datetime)]]
|
||||
</template>
|
||||
</div>
|
||||
<template is="dom-if" if="[[_showValue(item.condition)]]">
|
||||
<div class="icon">
|
||||
<ha-icon icon="[[getWeatherIcon(item.condition)]]"></ha-icon>
|
||||
<ha-icon
|
||||
icon="[[getWeatherIcon(item.condition)]]"
|
||||
></ha-icon>
|
||||
</div>
|
||||
</template>
|
||||
<div class="temp">[[item.temperature]] [[getUnit('temperature')]]</div>
|
||||
<div class="temp">
|
||||
[[item.temperature]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
<template is="dom-if" if="[[_showValue(item.templow)]]">
|
||||
<div class="templow">[[item.templow]] [[getUnit('temperature')]]</div>
|
||||
<div class="templow">
|
||||
[[item.templow]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(item.precipitation)]]">
|
||||
<div class="precipitation">[[item.precipitation]] [[getUnit('precipitation')]]</div>
|
||||
<div class="precipitation">
|
||||
[[item.precipitation]] [[getUnit('precipitation')]]
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -8,9 +8,8 @@ export default function attributeClassNames(
|
||||
return "";
|
||||
}
|
||||
return attributes
|
||||
.map(
|
||||
(attribute) =>
|
||||
attribute in stateObj.attributes ? "has-" + attribute : ""
|
||||
.map((attribute) =>
|
||||
attribute in stateObj.attributes ? "has-" + attribute : ""
|
||||
)
|
||||
.filter((attr) => attr !== "")
|
||||
.join(" ");
|
||||
|
||||
@ -12,10 +12,9 @@ export default function featureClassNames(
|
||||
const features = stateObj.attributes.supported_features;
|
||||
|
||||
return Object.keys(classNames)
|
||||
.map(
|
||||
(feature) =>
|
||||
// tslint:disable-next-line
|
||||
(features & Number(feature)) !== 0 ? classNames[feature] : ""
|
||||
.map((feature) =>
|
||||
// tslint:disable-next-line
|
||||
(features & Number(feature)) !== 0 ? classNames[feature] : ""
|
||||
)
|
||||
.filter((attr) => attr !== "")
|
||||
.join(" ");
|
||||
|
||||
@ -10,7 +10,8 @@ class HaCallApiButton extends LitElement {
|
||||
.progress="${this.progress}"
|
||||
@click="${this._buttonTapped}"
|
||||
?disabled="${this.disabled}"
|
||||
><slot></slot></ha-progress-button>
|
||||
><slot></slot
|
||||
></ha-progress-button>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -10,8 +10,13 @@ import EventsMixin from "../../mixins/events-mixin";
|
||||
class HaCallServiceButton extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<ha-progress-button id="progress" progress="[[progress]]" on-click="buttonTapped"><slot></slot></ha-progress-button>
|
||||
`;
|
||||
<ha-progress-button
|
||||
id="progress"
|
||||
progress="[[progress]]"
|
||||
on-click="buttonTapped"
|
||||
><slot></slot
|
||||
></ha-progress-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,53 +6,55 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HaProgressButton extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
<style>
|
||||
.container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
paper-button {
|
||||
transition: all 1s;
|
||||
}
|
||||
paper-button {
|
||||
transition: all 1s;
|
||||
}
|
||||
|
||||
.success paper-button {
|
||||
color: white;
|
||||
background-color: var(--google-green-500);
|
||||
transition: none;
|
||||
}
|
||||
.success paper-button {
|
||||
color: white;
|
||||
background-color: var(--google-green-500);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.error paper-button {
|
||||
color: white;
|
||||
background-color: var(--google-red-500);
|
||||
transition: none;
|
||||
}
|
||||
.error paper-button {
|
||||
color: white;
|
||||
background-color: var(--google-red-500);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
paper-button[disabled] {
|
||||
color: #c8c8c8;
|
||||
}
|
||||
paper-button[disabled] {
|
||||
color: #c8c8c8;
|
||||
}
|
||||
|
||||
.progress {
|
||||
@apply --layout;
|
||||
@apply --layout-center-center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="container" id="container">
|
||||
<paper-button id="button" disabled="[[computeDisabled(disabled, progress)]]" on-click="buttonTapped">
|
||||
<slot></slot>
|
||||
</paper-button>
|
||||
<template is="dom-if" if="[[progress]]">
|
||||
<div class="progress">
|
||||
<paper-spinner active=""></paper-spinner>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
.progress {
|
||||
@apply --layout;
|
||||
@apply --layout-center-center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
<div class="container" id="container">
|
||||
<paper-button
|
||||
id="button"
|
||||
disabled="[[computeDisabled(disabled, progress)]]"
|
||||
on-click="buttonTapped"
|
||||
>
|
||||
<slot></slot>
|
||||
</paper-button>
|
||||
<template is="dom-if" if="[[progress]]">
|
||||
<div class="progress"><paper-spinner active=""></paper-spinner></div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,120 +18,126 @@ class HaChartBase extends mixinBehaviors(
|
||||
) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
.chartHeader {
|
||||
padding: 6px 0 0 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.chartHeader > div {
|
||||
vertical-align: top;
|
||||
padding: 0 8px;
|
||||
}
|
||||
.chartHeader > div.chartTitle {
|
||||
padding-top: 8px;
|
||||
flex: 0 0 0;
|
||||
max-width: 30%;
|
||||
}
|
||||
.chartHeader > div.chartLegend {
|
||||
flex: 1 1;
|
||||
min-width: 70%;
|
||||
}
|
||||
:root{
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
.chartTooltip {
|
||||
font-size: 90%;
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
background: rgba(80, 80, 80, .9);
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
pointer-events: none;
|
||||
transform: translate(-50%, 12px);
|
||||
z-index: 1000;
|
||||
width: 200px;
|
||||
transition: opacity 0.15s ease-in-out;
|
||||
}
|
||||
.chartLegend ul,
|
||||
.chartTooltip ul {
|
||||
display: inline-block;
|
||||
padding: 0 0px;
|
||||
margin: 5px 0 0 0;
|
||||
width: 100%
|
||||
}
|
||||
.chartTooltip li {
|
||||
display: block;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.chartTooltip .title {
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
.chartLegend li {
|
||||
display: inline-block;
|
||||
padding: 0 6px;
|
||||
max-width: 49%;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.chartLegend li:nth-child(odd):last-of-type {
|
||||
/* Make last item take full width if it is odd-numbered. */
|
||||
max-width: 100%;
|
||||
}
|
||||
.chartLegend li[data-hidden] {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.chartLegend em,
|
||||
.chartTooltip em {
|
||||
border-radius: 5px;
|
||||
display: inline-block;
|
||||
height: 10px;
|
||||
margin-right: 4px;
|
||||
width: 10px;
|
||||
}
|
||||
paper-icon-button {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[unit]]">
|
||||
<div class="chartHeader">
|
||||
<div class="chartTitle">[[unit]]</div>
|
||||
<div class="chartLegend">
|
||||
<ul>
|
||||
<template is="dom-repeat" items="[[metas]]">
|
||||
<li on-click="_legendClick" data-hidden$="[[item.hidden]]">
|
||||
<em style$="background-color:[[item.bgColor]]"></em>
|
||||
[[item.label]]
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
.chartHeader {
|
||||
padding: 6px 0 0 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.chartHeader > div {
|
||||
vertical-align: top;
|
||||
padding: 0 8px;
|
||||
}
|
||||
.chartHeader > div.chartTitle {
|
||||
padding-top: 8px;
|
||||
flex: 0 0 0;
|
||||
max-width: 30%;
|
||||
}
|
||||
.chartHeader > div.chartLegend {
|
||||
flex: 1 1;
|
||||
min-width: 70%;
|
||||
}
|
||||
:root {
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
.chartTooltip {
|
||||
font-size: 90%;
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
background: rgba(80, 80, 80, 0.9);
|
||||
color: white;
|
||||
border-radius: 3px;
|
||||
pointer-events: none;
|
||||
transform: translate(-50%, 12px);
|
||||
z-index: 1000;
|
||||
width: 200px;
|
||||
transition: opacity 0.15s ease-in-out;
|
||||
}
|
||||
.chartLegend ul,
|
||||
.chartTooltip ul {
|
||||
display: inline-block;
|
||||
padding: 0 0px;
|
||||
margin: 5px 0 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
.chartTooltip li {
|
||||
display: block;
|
||||
white-space: pre-line;
|
||||
}
|
||||
.chartTooltip .title {
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
.chartLegend li {
|
||||
display: inline-block;
|
||||
padding: 0 6px;
|
||||
max-width: 49%;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.chartLegend li:nth-child(odd):last-of-type {
|
||||
/* Make last item take full width if it is odd-numbered. */
|
||||
max-width: 100%;
|
||||
}
|
||||
.chartLegend li[data-hidden] {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.chartLegend em,
|
||||
.chartTooltip em {
|
||||
border-radius: 5px;
|
||||
display: inline-block;
|
||||
height: 10px;
|
||||
margin-right: 4px;
|
||||
width: 10px;
|
||||
}
|
||||
paper-icon-button {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[unit]]">
|
||||
<div class="chartHeader">
|
||||
<div class="chartTitle">[[unit]]</div>
|
||||
<div class="chartLegend">
|
||||
<ul>
|
||||
<template is="dom-repeat" items="[[metas]]">
|
||||
<li on-click="_legendClick" data-hidden$="[[item.hidden]]">
|
||||
<em style$="background-color:[[item.bgColor]]"></em>
|
||||
[[item.label]]
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div id="chartTarget" style="height:40px; width:100%">
|
||||
<canvas id="chartCanvas"></canvas>
|
||||
<div
|
||||
class$="chartTooltip [[tooltip.yAlign]]"
|
||||
style$="opacity:[[tooltip.opacity]]; top:[[tooltip.top]]; left:[[tooltip.left]]; padding:[[tooltip.yPadding]]px [[tooltip.xPadding]]px"
|
||||
>
|
||||
<div class="title">[[tooltip.title]]</div>
|
||||
<div>
|
||||
<ul>
|
||||
<template is="dom-repeat" items="[[tooltip.lines]]">
|
||||
<li>
|
||||
<em style$="background-color:[[item.bgColor]]"></em
|
||||
>[[item.text]]
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div id="chartTarget" style="height:40px; width:100%">
|
||||
<canvas id="chartCanvas"></canvas>
|
||||
<div class$="chartTooltip [[tooltip.yAlign]]" style$="opacity:[[tooltip.opacity]]; top:[[tooltip.top]]; left:[[tooltip.left]]; padding:[[tooltip.yPadding]]px [[tooltip.xPadding]]px">
|
||||
<div class="title">[[tooltip.title]]</div>
|
||||
<div>
|
||||
<ul>
|
||||
<template is="dom-repeat" items="[[tooltip.lines]]">
|
||||
<li><em style$="background-color:[[item.bgColor]]"></em>[[item.text]]</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
get chart() {
|
||||
|
||||
@ -18,56 +18,70 @@ import EventsMixin from "../../mixins/events-mixin";
|
||||
class HaEntityPicker extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-input > paper-icon-button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<vaadin-combo-box-light
|
||||
items="[[_states]]"
|
||||
item-value-path="entity_id"
|
||||
item-label-path="entity_id"
|
||||
value="{{value}}"
|
||||
opened="{{opened}}"
|
||||
allow-custom-value="[[allowCustomEntity]]"
|
||||
on-change='_fireChanged'
|
||||
>
|
||||
<paper-input
|
||||
autofocus="[[autofocus]]"
|
||||
label="[[_computeLabel(label, localize)]]"
|
||||
class="input"
|
||||
autocapitalize='none'
|
||||
autocomplete='off'
|
||||
autocorrect='off'
|
||||
spellcheck='false'
|
||||
value="[[value]]"
|
||||
disabled="[[disabled]]">
|
||||
<paper-icon-button slot="suffix" class="clear-button" icon="hass:close" no-ripple="" hidden$="[[!value]]">Clear</paper-icon-button>
|
||||
<paper-icon-button slot="suffix" class="toggle-button" icon="[[_computeToggleIcon(opened)]]" hidden="[[!_states.length]]">Toggle</paper-icon-button>
|
||||
</paper-input>
|
||||
<template>
|
||||
<style>
|
||||
paper-icon-item {
|
||||
margin: -10px;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<paper-icon-item>
|
||||
<state-badge state-obj="[[item]]" slot="item-icon"></state-badge>
|
||||
<paper-item-body two-line="">
|
||||
<div>[[_computeStateName(item)]]</div>
|
||||
<div secondary="">[[item.entity_id]]</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
</template>
|
||||
</vaadin-combo-box-light>
|
||||
`;
|
||||
<style>
|
||||
paper-input > paper-icon-button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<vaadin-combo-box-light
|
||||
items="[[_states]]"
|
||||
item-value-path="entity_id"
|
||||
item-label-path="entity_id"
|
||||
value="{{value}}"
|
||||
opened="{{opened}}"
|
||||
allow-custom-value="[[allowCustomEntity]]"
|
||||
on-change="_fireChanged"
|
||||
>
|
||||
<paper-input
|
||||
autofocus="[[autofocus]]"
|
||||
label="[[_computeLabel(label, localize)]]"
|
||||
class="input"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
spellcheck="false"
|
||||
value="[[value]]"
|
||||
disabled="[[disabled]]"
|
||||
>
|
||||
<paper-icon-button
|
||||
slot="suffix"
|
||||
class="clear-button"
|
||||
icon="hass:close"
|
||||
no-ripple=""
|
||||
hidden$="[[!value]]"
|
||||
>Clear</paper-icon-button
|
||||
>
|
||||
<paper-icon-button
|
||||
slot="suffix"
|
||||
class="toggle-button"
|
||||
icon="[[_computeToggleIcon(opened)]]"
|
||||
hidden="[[!_states.length]]"
|
||||
>Toggle</paper-icon-button
|
||||
>
|
||||
</paper-input>
|
||||
<template>
|
||||
<style>
|
||||
paper-icon-item {
|
||||
margin: -10px;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<paper-icon-item>
|
||||
<state-badge state-obj="[[item]]" slot="item-icon"></state-badge>
|
||||
<paper-item-body two-line="">
|
||||
<div>[[_computeStateName(item)]]</div>
|
||||
<div secondary="">[[item.entity_id]]</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
</template>
|
||||
</vaadin-combo-box-light>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,34 +9,48 @@ import computeStateDomain from "../../common/entity/compute_state_domain";
|
||||
class HaEntityToggle extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
white-space: nowrap;
|
||||
min-width: 38px;
|
||||
}
|
||||
paper-icon-button {
|
||||
color: var(--paper-icon-button-inactive-color, var(--primary-text-color));
|
||||
transition: color .5s;
|
||||
}
|
||||
paper-icon-button[state-active] {
|
||||
color: var(--paper-icon-button-active-color, var(--primary-color));
|
||||
}
|
||||
paper-toggle-button {
|
||||
cursor: pointer;
|
||||
--paper-toggle-button-label-spacing: 0;
|
||||
padding: 13px 5px;
|
||||
margin: -4px -5px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
:host {
|
||||
white-space: nowrap;
|
||||
min-width: 38px;
|
||||
}
|
||||
paper-icon-button {
|
||||
color: var(
|
||||
--paper-icon-button-inactive-color,
|
||||
var(--primary-text-color)
|
||||
);
|
||||
transition: color 0.5s;
|
||||
}
|
||||
paper-icon-button[state-active] {
|
||||
color: var(--paper-icon-button-active-color, var(--primary-color));
|
||||
}
|
||||
paper-toggle-button {
|
||||
cursor: pointer;
|
||||
--paper-toggle-button-label-spacing: 0;
|
||||
padding: 13px 5px;
|
||||
margin: -4px -5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[stateObj.attributes.assumed_state]]">
|
||||
<paper-icon-button icon="hass:flash-off" on-click="turnOff" state-active$="[[!isOn]]"></paper-icon-button>
|
||||
<paper-icon-button icon="hass:flash" on-click="turnOn" state-active$="[[isOn]]"></paper-icon-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!stateObj.attributes.assumed_state]]">
|
||||
<paper-toggle-button checked="[[toggleChecked]]" on-change="toggleChanged"></paper-toggle-button>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[stateObj.attributes.assumed_state]]">
|
||||
<paper-icon-button
|
||||
icon="hass:flash-off"
|
||||
on-click="turnOff"
|
||||
state-active$="[[!isOn]]"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:flash"
|
||||
on-click="turnOn"
|
||||
state-active$="[[isOn]]"
|
||||
></paper-icon-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!stateObj.attributes.assumed_state]]">
|
||||
<paper-toggle-button
|
||||
checked="[[toggleChecked]]"
|
||||
on-change="toggleChanged"
|
||||
></paper-toggle-button>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,7 +6,9 @@ import stateIcon from "../../common/entity/state_icon";
|
||||
|
||||
class HaStateIcon extends PolymerElement {
|
||||
static get template() {
|
||||
return html`<ha-icon icon="[[computeIcon(stateObj)]]"></ha-icon>`;
|
||||
return html`
|
||||
<ha-icon icon="[[computeIcon(stateObj)]]"></ha-icon>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -21,46 +21,56 @@ import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
class HaStateLabelBadge extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
cursor: pointer;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ha-label-badge {
|
||||
--ha-label-badge-color: var(--label-badge-red, #DF4C1E);
|
||||
}
|
||||
ha-label-badge.has-unit_of_measurement {
|
||||
--ha-label-badge-label-text-transform: none;
|
||||
}
|
||||
ha-label-badge {
|
||||
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
||||
}
|
||||
ha-label-badge.has-unit_of_measurement {
|
||||
--ha-label-badge-label-text-transform: none;
|
||||
}
|
||||
|
||||
ha-label-badge.binary_sensor,
|
||||
ha-label-badge.updater {
|
||||
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
||||
}
|
||||
ha-label-badge.binary_sensor,
|
||||
ha-label-badge.updater {
|
||||
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
||||
}
|
||||
|
||||
.red {
|
||||
--ha-label-badge-color: var(--label-badge-red, #DF4C1E);
|
||||
}
|
||||
.red {
|
||||
--ha-label-badge-color: var(--label-badge-red, #df4c1e);
|
||||
}
|
||||
|
||||
.blue {
|
||||
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
||||
}
|
||||
.blue {
|
||||
--ha-label-badge-color: var(--label-badge-blue, #039be5);
|
||||
}
|
||||
|
||||
.green {
|
||||
--ha-label-badge-color: var(--label-badge-green, #0DA035);
|
||||
}
|
||||
.green {
|
||||
--ha-label-badge-color: var(--label-badge-green, #0da035);
|
||||
}
|
||||
|
||||
.yellow {
|
||||
--ha-label-badge-color: var(--label-badge-yellow, #f4b400);
|
||||
}
|
||||
.yellow {
|
||||
--ha-label-badge-color: var(--label-badge-yellow, #f4b400);
|
||||
}
|
||||
|
||||
.grey {
|
||||
--ha-label-badge-color: var(--label-badge-grey, var(--paper-grey-500));
|
||||
}
|
||||
</style>
|
||||
.grey {
|
||||
--ha-label-badge-color: var(
|
||||
--label-badge-grey,
|
||||
var(--paper-grey-500)
|
||||
);
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-label-badge class$="[[computeClassNames(state)]]" value="[[computeValue(localize, state)]]" icon="[[computeIcon(state)]]" image="[[computeImage(state)]]" label="[[computeLabel(localize, state, _timerTimeRemaining)]]" description="[[computeDescription(state)]]"></ha-label-badge>
|
||||
`;
|
||||
<ha-label-badge
|
||||
class$="[[computeClassNames(state)]]"
|
||||
value="[[computeValue(localize, state)]]"
|
||||
icon="[[computeIcon(state)]]"
|
||||
image="[[computeImage(state)]]"
|
||||
label="[[computeLabel(localize, state, _timerTimeRemaining)]]"
|
||||
description="[[computeDescription(state)]]"
|
||||
></ha-label-badge>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -8,45 +8,45 @@ import stateIcon from "../../common/entity/state_icon";
|
||||
class StateBadge extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
color: var(--paper-item-icon-color, #44739e);
|
||||
border-radius: 50%;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
background-size: cover;
|
||||
line-height: 40px;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
color: var(--paper-item-icon-color, #44739e);
|
||||
border-radius: 50%;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
background-size: cover;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
ha-icon {
|
||||
transition: color .3s ease-in-out, filter .3s ease-in-out;
|
||||
}
|
||||
ha-icon {
|
||||
transition: color 0.3s ease-in-out, filter 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* Color the icon if light or sun is on */
|
||||
ha-icon[data-domain=light][data-state=on],
|
||||
ha-icon[data-domain=switch][data-state=on],
|
||||
ha-icon[data-domain=binary_sensor][data-state=on],
|
||||
ha-icon[data-domain=fan][data-state=on],
|
||||
ha-icon[data-domain=sun][data-state=above_horizon] {
|
||||
color: var(--paper-item-icon-active-color, #FDD835);
|
||||
}
|
||||
/* Color the icon if light or sun is on */
|
||||
ha-icon[data-domain="light"][data-state="on"],
|
||||
ha-icon[data-domain="switch"][data-state="on"],
|
||||
ha-icon[data-domain="binary_sensor"][data-state="on"],
|
||||
ha-icon[data-domain="fan"][data-state="on"],
|
||||
ha-icon[data-domain="sun"][data-state="above_horizon"] {
|
||||
color: var(--paper-item-icon-active-color, #fdd835);
|
||||
}
|
||||
|
||||
/* Color the icon if unavailable */
|
||||
ha-icon[data-state=unavailable] {
|
||||
color: var(--state-icon-unavailable-color);
|
||||
}
|
||||
</style>
|
||||
/* Color the icon if unavailable */
|
||||
ha-icon[data-state="unavailable"] {
|
||||
color: var(--state-icon-unavailable-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-icon
|
||||
id="icon"
|
||||
data-domain$="[[_computeDomain(stateObj)]]"
|
||||
data-state$="[[stateObj.state]]"
|
||||
icon="[[_computeIcon(stateObj)]]"
|
||||
></ha-icon>
|
||||
`;
|
||||
<ha-icon
|
||||
id="icon"
|
||||
data-domain$="[[_computeDomain(stateObj)]]"
|
||||
data-state$="[[stateObj.state]]"
|
||||
icon="[[_computeIcon(stateObj)]]"
|
||||
></ha-icon>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -8,70 +8,74 @@ import computeStateName from "../../common/entity/compute_state_name";
|
||||
class StateInfo extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
${this.styleTemplate}
|
||||
${this.stateBadgeTemplate}
|
||||
${this.infoTemplate}
|
||||
`;
|
||||
${this.styleTemplate} ${this.stateBadgeTemplate} ${this.infoTemplate}
|
||||
`;
|
||||
}
|
||||
|
||||
static get styleTemplate() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
@apply --paper-font-body1;
|
||||
min-width: 120px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
@apply --paper-font-body1;
|
||||
min-width: 120px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
state-badge {
|
||||
float: left;
|
||||
}
|
||||
state-badge {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.info {
|
||||
margin-left: 56px;
|
||||
}
|
||||
.info {
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
.name {
|
||||
@apply --paper-font-common-nowrap;
|
||||
color: var(--primary-text-color);
|
||||
line-height: 40px;
|
||||
}
|
||||
.name {
|
||||
@apply --paper-font-common-nowrap;
|
||||
color: var(--primary-text-color);
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.name[in-dialog], :host([secondary-line]) .name {
|
||||
line-height: 20px;
|
||||
}
|
||||
.name[in-dialog],
|
||||
:host([secondary-line]) .name {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.time-ago, .extra-info, .extra-info > * {
|
||||
@apply --paper-font-common-nowrap;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
.time-ago,
|
||||
.extra-info,
|
||||
.extra-info > * {
|
||||
@apply --paper-font-common-nowrap;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
}
|
||||
|
||||
static get stateBadgeTemplate() {
|
||||
return html`
|
||||
<state-badge state-obj="[[stateObj]]"></state-badge>
|
||||
`;
|
||||
<state-badge state-obj="[[stateObj]]"></state-badge>
|
||||
`;
|
||||
}
|
||||
|
||||
static get infoTemplate() {
|
||||
return html`
|
||||
<div class="info">
|
||||
<div class="name" in-dialog$="[[inDialog]]">[[computeStateName(stateObj)]]</div>
|
||||
|
||||
<template is="dom-if" if="[[inDialog]]">
|
||||
<div class="time-ago">
|
||||
<ha-relative-time hass="[[hass]]" datetime="[[stateObj.last_changed]]"></ha-relative-time>
|
||||
<div class="info">
|
||||
<div class="name" in-dialog$="[[inDialog]]">
|
||||
[[computeStateName(stateObj)]]
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!inDialog]]">
|
||||
<div class="extra-info">
|
||||
<slot>
|
||||
</slot></div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
|
||||
<template is="dom-if" if="[[inDialog]]">
|
||||
<div class="time-ago">
|
||||
<ha-relative-time
|
||||
hass="[[hass]]"
|
||||
datetime="[[stateObj.last_changed]]"
|
||||
></ha-relative-time>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!inDialog]]">
|
||||
<div class="extra-info"><slot> </slot></div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,27 +7,35 @@ import hassAttributeUtil from "../util/hass-attributes-util";
|
||||
class HaAttributes extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
.data-entry .value {
|
||||
max-width: 200px;
|
||||
}
|
||||
.attribution {
|
||||
color: var(--secondary-text-color);
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
.data-entry .value {
|
||||
max-width: 200px;
|
||||
}
|
||||
.attribution {
|
||||
color: var(--secondary-text-color);
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layout vertical">
|
||||
<template is="dom-repeat" items="[[computeDisplayAttributes(stateObj, filtersArray)]]" as="attribute">
|
||||
<div class="data-entry layout justified horizontal">
|
||||
<div class="key">[[formatAttribute(attribute)]]</div>
|
||||
<div class="value">[[formatAttributeValue(stateObj, attribute)]]</div>
|
||||
<div class="layout vertical">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[computeDisplayAttributes(stateObj, filtersArray)]]"
|
||||
as="attribute"
|
||||
>
|
||||
<div class="data-entry layout justified horizontal">
|
||||
<div class="key">[[formatAttribute(attribute)]]</div>
|
||||
<div class="value">
|
||||
[[formatAttributeValue(stateObj, attribute)]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="attribution" hidden$="[[!computeAttribution(stateObj)]]">
|
||||
[[computeAttribution(stateObj)]]
|
||||
</div>
|
||||
</template>
|
||||
<div class="attribution" hidden$="[[!computeAttribution(stateObj)]]">[[computeAttribution(stateObj)]]</div>
|
||||
</div>
|
||||
`;
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -5,27 +5,27 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HaCard extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="paper-material-styles">
|
||||
:host {
|
||||
@apply --paper-material-elevation-1;
|
||||
display: block;
|
||||
border-radius: 2px;
|
||||
transition: all 0.30s ease-out;
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
@apply --paper-font-common-expensive-kerning;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
padding: 24px 16px 16px;
|
||||
}
|
||||
</style>
|
||||
<style include="paper-material-styles">
|
||||
:host {
|
||||
@apply --paper-material-elevation-1;
|
||||
display: block;
|
||||
border-radius: 2px;
|
||||
transition: all 0.3s ease-out;
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-headline;
|
||||
@apply --paper-font-common-expensive-kerning;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
padding: 24px 16px 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[header]]">
|
||||
<div class="header">[[header]]</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
`;
|
||||
<template is="dom-if" if="[[header]]">
|
||||
<div class="header">[[header]]</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -78,72 +78,75 @@ const iterateDomainSorted = (collection, func) => {
|
||||
class HaCards extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-factors"></style>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
padding: 4px 4px 0;
|
||||
transform: translateZ(0);
|
||||
position: relative;
|
||||
}
|
||||
<style include="iron-flex iron-flex-factors"></style>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
padding: 4px 4px 0;
|
||||
transform: translateZ(0);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.badges {
|
||||
font-size: 85%;
|
||||
text-align: center;
|
||||
padding-top: 16px;
|
||||
}
|
||||
.badges {
|
||||
font-size: 85%;
|
||||
text-align: center;
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.column {
|
||||
max-width: 500px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.column {
|
||||
max-width: 500px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
ha-card-chooser {
|
||||
display: block;
|
||||
margin: 4px 4px 8px;
|
||||
}
|
||||
ha-card-chooser {
|
||||
display: block;
|
||||
margin: 4px 4px 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
:host {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
:host {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
ha-card-chooser {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
ha-card-chooser {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 599px) {
|
||||
.column {
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@media (max-width: 599px) {
|
||||
.column {
|
||||
max-width: 600px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="main">
|
||||
<template is="dom-if" if="[[cards.badges]]">
|
||||
<div class="badges">
|
||||
<template is="dom-if" if="[[cards.demo]]">
|
||||
<ha-demo-badge></ha-demo-badge>
|
||||
<div id="main">
|
||||
<template is="dom-if" if="[[cards.badges]]">
|
||||
<div class="badges">
|
||||
<template is="dom-if" if="[[cards.demo]]">
|
||||
<ha-demo-badge></ha-demo-badge>
|
||||
</template>
|
||||
|
||||
<ha-badges-card
|
||||
states="[[cards.badges]]"
|
||||
hass="[[hass]]"
|
||||
></ha-badges-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<ha-badges-card states="[[cards.badges]]" hass="[[hass]]"></ha-badges-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="horizontal layout center-justified">
|
||||
<template is="dom-repeat" items="[[cards.columns]]" as="column">
|
||||
<div class="column flex-1">
|
||||
<template is="dom-repeat" items="[[column]]" as="card">
|
||||
<ha-card-chooser card-data="[[card]]"></ha-card-chooser>
|
||||
<div class="horizontal layout center-justified">
|
||||
<template is="dom-repeat" items="[[cards.columns]]" as="column">
|
||||
<div class="column flex-1">
|
||||
<template is="dom-repeat" items="[[column]]" as="card">
|
||||
<ha-card-chooser card-data="[[card]]"></ha-card-chooser>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,44 +11,48 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaClimateControl extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
/* local DOM styles go here */
|
||||
:host {
|
||||
@apply --layout-flex;
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
.in-flux#target_temperature {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
#target_temperature {
|
||||
@apply --layout-self-center;
|
||||
font-size: 200%;
|
||||
}
|
||||
.control-buttons {
|
||||
font-size: 200%;
|
||||
text-align: right;
|
||||
}
|
||||
paper-icon-button {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
</style>
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
/* local DOM styles go here */
|
||||
:host {
|
||||
@apply --layout-flex;
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
.in-flux#target_temperature {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
#target_temperature {
|
||||
@apply --layout-self-center;
|
||||
font-size: 200%;
|
||||
}
|
||||
.control-buttons {
|
||||
font-size: 200%;
|
||||
text-align: right;
|
||||
}
|
||||
paper-icon-button {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- local DOM goes here -->
|
||||
<div id="target_temperature">
|
||||
[[value]] [[units]]
|
||||
</div>
|
||||
<div class="control-buttons">
|
||||
<div>
|
||||
<paper-icon-button icon="hass:chevron-up" on-click="incrementValue"></paper-icon-button>
|
||||
<!-- local DOM goes here -->
|
||||
<div id="target_temperature">[[value]] [[units]]</div>
|
||||
<div class="control-buttons">
|
||||
<div>
|
||||
<paper-icon-button
|
||||
icon="hass:chevron-up"
|
||||
on-click="incrementValue"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div>
|
||||
<paper-icon-button
|
||||
icon="hass:chevron-down"
|
||||
on-click="decrementValue"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<paper-icon-button icon="hass:chevron-down" on-click="decrementValue"></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,43 +9,41 @@ import LocalizeMixin from "../mixins/localize-mixin";
|
||||
class HaClimateState extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.target {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.target {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.current {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.current {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.state-label {
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
</style>
|
||||
.state-label {
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="target">
|
||||
<template is="dom-if" if="[[_hasKnownState(stateObj.state)]]">
|
||||
<span class="state-label">
|
||||
[[_localizeState(stateObj.state)]]
|
||||
</span>
|
||||
</template>
|
||||
[[computeTarget(hass, stateObj)]]
|
||||
</div>
|
||||
|
||||
<template is="dom-if" if="[[currentStatus]]">
|
||||
<div class="current">
|
||||
[[localize('ui.card.climate.currently')]]: [[currentStatus]]
|
||||
<div class="target">
|
||||
<template is="dom-if" if="[[_hasKnownState(stateObj.state)]]">
|
||||
<span class="state-label"> [[_localizeState(stateObj.state)]] </span>
|
||||
</template>
|
||||
[[computeTarget(hass, stateObj)]]
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
|
||||
<template is="dom-if" if="[[currentStatus]]">
|
||||
<div class="current">
|
||||
[[localize('ui.card.climate.currently')]]: [[currentStatus]]
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,73 +11,95 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 330px;
|
||||
}
|
||||
#canvas > * {
|
||||
display: block;
|
||||
}
|
||||
#interactionLayer {
|
||||
color: white;
|
||||
position: absolute;
|
||||
cursor: crosshair;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
#backgroundLayer {
|
||||
width: 100%;
|
||||
overflow: visible;
|
||||
--wheel-bordercolor: var(--ha-color-picker-wheel-bordercolor, white);
|
||||
--wheel-borderwidth: var(--ha-color-picker-wheel-borderwidth, 3);
|
||||
--wheel-shadow: var(--ha-color-picker-wheel-shadow, rgb(15, 15, 15) 10px 5px 5px 0px);
|
||||
}
|
||||
#canvas {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 330px;
|
||||
}
|
||||
#canvas > * {
|
||||
display: block;
|
||||
}
|
||||
#interactionLayer {
|
||||
color: white;
|
||||
position: absolute;
|
||||
cursor: crosshair;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
#backgroundLayer {
|
||||
width: 100%;
|
||||
overflow: visible;
|
||||
--wheel-bordercolor: var(--ha-color-picker-wheel-bordercolor, white);
|
||||
--wheel-borderwidth: var(--ha-color-picker-wheel-borderwidth, 3);
|
||||
--wheel-shadow: var(
|
||||
--ha-color-picker-wheel-shadow,
|
||||
rgb(15, 15, 15) 10px 5px 5px 0px
|
||||
);
|
||||
}
|
||||
|
||||
#marker {
|
||||
fill: currentColor;
|
||||
stroke: var(--ha-color-picker-marker-bordercolor, white);
|
||||
stroke-width: var(--ha-color-picker-marker-borderwidth, 3);
|
||||
filter: url(#marker-shadow)
|
||||
}
|
||||
.dragging #marker {
|
||||
}
|
||||
#marker {
|
||||
fill: currentColor;
|
||||
stroke: var(--ha-color-picker-marker-bordercolor, white);
|
||||
stroke-width: var(--ha-color-picker-marker-borderwidth, 3);
|
||||
filter: url(#marker-shadow);
|
||||
}
|
||||
.dragging #marker {
|
||||
}
|
||||
|
||||
#colorTooltip {
|
||||
display: none;
|
||||
fill: currentColor;
|
||||
stroke: var(--ha-color-picker-tooltip-bordercolor, white);
|
||||
stroke-width: var(--ha-color-picker-tooltip-borderwidth, 3);
|
||||
}
|
||||
#colorTooltip {
|
||||
display: none;
|
||||
fill: currentColor;
|
||||
stroke: var(--ha-color-picker-tooltip-bordercolor, white);
|
||||
stroke-width: var(--ha-color-picker-tooltip-borderwidth, 3);
|
||||
}
|
||||
|
||||
.touch.dragging #colorTooltip {
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="canvas">
|
||||
<svg id="interactionLayer">
|
||||
<defs>
|
||||
<filter id="marker-shadow" x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox">
|
||||
<feOffset result="offOut" in="SourceAlpha" dx="2" dy="2"></feOffset>
|
||||
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="2"></feGaussianBlur>
|
||||
<feComponentTransfer in="blurOut" result="alphaOut">
|
||||
<feFuncA type="linear" slope="0.3"></feFuncA>
|
||||
</feComponentTransfer>
|
||||
<feBlend in="SourceGraphic" in2="alphaOut" mode="normal"></feBlend>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<canvas id="backgroundLayer"></canvas>
|
||||
</div>
|
||||
`;
|
||||
.touch.dragging #colorTooltip {
|
||||
display: inherit;
|
||||
}
|
||||
</style>
|
||||
<div id="canvas">
|
||||
<svg id="interactionLayer">
|
||||
<defs>
|
||||
<filter
|
||||
id="marker-shadow"
|
||||
x="-50%"
|
||||
y="-50%"
|
||||
width="200%"
|
||||
height="200%"
|
||||
filterUnits="objectBoundingBox"
|
||||
>
|
||||
<feOffset
|
||||
result="offOut"
|
||||
in="SourceAlpha"
|
||||
dx="2"
|
||||
dy="2"
|
||||
></feOffset>
|
||||
<feGaussianBlur
|
||||
result="blurOut"
|
||||
in="offOut"
|
||||
stdDeviation="2"
|
||||
></feGaussianBlur>
|
||||
<feComponentTransfer in="blurOut" result="alphaOut">
|
||||
<feFuncA type="linear" slope="0.3"></feFuncA>
|
||||
</feComponentTransfer>
|
||||
<feBlend
|
||||
in="SourceGraphic"
|
||||
in2="alphaOut"
|
||||
mode="normal"
|
||||
></feBlend>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
<canvas id="backgroundLayer"></canvas>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
@ -246,8 +268,8 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
/*
|
||||
* General event/selection handling
|
||||
*/
|
||||
* General event/selection handling
|
||||
*/
|
||||
|
||||
// Process user input to color
|
||||
processUserSelect(ev) {
|
||||
@ -290,8 +312,8 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface updating
|
||||
*/
|
||||
* Interface updating
|
||||
*/
|
||||
|
||||
// set marker position to the given color
|
||||
setMarkerOnColor(hs) {
|
||||
@ -328,8 +350,8 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
/*
|
||||
* input processing helpers
|
||||
*/
|
||||
* input processing helpers
|
||||
*/
|
||||
|
||||
// get angle (degrees)
|
||||
getAngle(dX, dY) {
|
||||
@ -349,8 +371,8 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Getting colors
|
||||
*/
|
||||
* Getting colors
|
||||
*/
|
||||
|
||||
getColor(x, y) {
|
||||
var hue = this.getAngle(x, y); // degrees, clockwise from right
|
||||
@ -387,8 +409,8 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Drawing related stuff
|
||||
*/
|
||||
* Drawing related stuff
|
||||
*/
|
||||
|
||||
setupLayers() {
|
||||
this.canvas = this.$.canvas;
|
||||
@ -410,8 +432,8 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
|
||||
drawColorWheel() {
|
||||
/*
|
||||
* Setting up all paremeters
|
||||
*/
|
||||
* Setting up all paremeters
|
||||
*/
|
||||
let shadowColor;
|
||||
let shadowOffsetX;
|
||||
let shadowOffsetY;
|
||||
@ -446,8 +468,8 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
const shadowRadius = radius + borderWidth;
|
||||
|
||||
/*
|
||||
* Drawing functions
|
||||
*/
|
||||
* Drawing functions
|
||||
*/
|
||||
function drawCircle(hueSegments, saturationSegments) {
|
||||
hueSegments = hueSegments || 360; // reset 0 segments to 360
|
||||
const angleStep = 360 / hueSegments;
|
||||
@ -524,9 +546,9 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the drawing functions
|
||||
* draws the shadow, wheel and border
|
||||
*/
|
||||
* Call the drawing functions
|
||||
* draws the shadow, wheel and border
|
||||
*/
|
||||
if (wheelStyle.shadow !== "none") {
|
||||
drawShadow();
|
||||
}
|
||||
@ -537,9 +559,9 @@ class HaColorPicker extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Draw the (draggable) marker and tooltip
|
||||
* on the interactionLayer)
|
||||
*/
|
||||
* Draw the (draggable) marker and tooltip
|
||||
* on the interactionLayer)
|
||||
*/
|
||||
|
||||
drawMarker() {
|
||||
const svgElement = this.interactionLayer;
|
||||
|
||||
@ -10,41 +10,58 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaComboBox extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-input > paper-icon-button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<vaadin-combo-box-light
|
||||
items="[[_items]]"
|
||||
item-value-path="[[itemValuePath]]"
|
||||
item-label-path="[[itemLabelPath]]"
|
||||
value="{{value}}"
|
||||
opened="{{opened}}"
|
||||
allow-custom-value="[[allowCustomValue]]"
|
||||
on-change='_fireChanged'
|
||||
>
|
||||
<paper-input autofocus="[[autofocus]]" label="[[label]]" class="input" value="[[value]]">
|
||||
<paper-icon-button slot="suffix" class="clear-button" icon="hass:close" hidden$="[[!value]]">Clear</paper-icon-button>
|
||||
<paper-icon-button slot="suffix" class="toggle-button" icon="[[_computeToggleIcon(opened)]]" hidden$="[[!items.length]]">Toggle</paper-icon-button>
|
||||
</paper-input>
|
||||
<template>
|
||||
<style>
|
||||
<style>
|
||||
paper-input > paper-icon-button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<vaadin-combo-box-light
|
||||
items="[[_items]]"
|
||||
item-value-path="[[itemValuePath]]"
|
||||
item-label-path="[[itemLabelPath]]"
|
||||
value="{{value}}"
|
||||
opened="{{opened}}"
|
||||
allow-custom-value="[[allowCustomValue]]"
|
||||
on-change="_fireChanged"
|
||||
>
|
||||
<paper-input
|
||||
autofocus="[[autofocus]]"
|
||||
label="[[label]]"
|
||||
class="input"
|
||||
value="[[value]]"
|
||||
>
|
||||
<paper-icon-button
|
||||
slot="suffix"
|
||||
class="clear-button"
|
||||
icon="hass:close"
|
||||
hidden$="[[!value]]"
|
||||
>Clear</paper-icon-button
|
||||
>
|
||||
<paper-icon-button
|
||||
slot="suffix"
|
||||
class="toggle-button"
|
||||
icon="[[_computeToggleIcon(opened)]]"
|
||||
hidden$="[[!items.length]]"
|
||||
>Toggle</paper-icon-button
|
||||
>
|
||||
</paper-input>
|
||||
<template>
|
||||
<style>
|
||||
paper-item {
|
||||
margin: -5px -10px;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<paper-item>[[_computeItemLabel(item, itemLabelPath)]]</paper-item>
|
||||
</template>
|
||||
</vaadin-combo-box-light>
|
||||
`;
|
||||
</style>
|
||||
<paper-item>[[_computeItemLabel(item, itemLabelPath)]]</paper-item>
|
||||
</template>
|
||||
</vaadin-combo-box-light>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,21 +7,35 @@ import CoverEntity from "../util/cover-model";
|
||||
class HaCoverControls extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.state {
|
||||
white-space: nowrap;
|
||||
}
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.state {
|
||||
white-space: nowrap;
|
||||
}
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="state">
|
||||
<paper-icon-button icon="hass:arrow-up" on-click="onOpenTap" invisible$="[[!entityObj.supportsOpen]]" disabled="[[computeOpenDisabled(stateObj, entityObj)]]"></paper-icon-button>
|
||||
<paper-icon-button icon="hass:stop" on-click="onStopTap" invisible$="[[!entityObj.supportsStop]]"></paper-icon-button>
|
||||
<paper-icon-button icon="hass:arrow-down" on-click="onCloseTap" invisible$="[[!entityObj.supportsClose]]" disabled="[[computeClosedDisabled(stateObj, entityObj)]]"></paper-icon-button>
|
||||
</div>
|
||||
`;
|
||||
<div class="state">
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-up"
|
||||
on-click="onOpenTap"
|
||||
invisible$="[[!entityObj.supportsOpen]]"
|
||||
disabled="[[computeOpenDisabled(stateObj, entityObj)]]"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:stop"
|
||||
on-click="onStopTap"
|
||||
invisible$="[[!entityObj.supportsStop]]"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-down"
|
||||
on-click="onCloseTap"
|
||||
invisible$="[[!entityObj.supportsClose]]"
|
||||
disabled="[[computeClosedDisabled(stateObj, entityObj)]]"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -8,19 +8,36 @@ import CoverEntity from "../util/cover-model";
|
||||
class HaCoverTiltControls extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
white-space: nowrap;
|
||||
}
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
<paper-icon-button icon="hass:arrow-top-right" on-click="onOpenTiltTap" title="Open tilt" invisible$="[[!entityObj.supportsOpenTilt]]" disabled="[[computeOpenDisabled(stateObj, entityObj)]]"></paper-icon-button>
|
||||
<paper-icon-button icon="hass:stop" on-click="onStopTiltTap" invisible$="[[!entityObj.supportsStopTilt]]" title="Stop tilt"></paper-icon-button>
|
||||
<paper-icon-button icon="hass:arrow-bottom-left" on-click="onCloseTiltTap" title="Close tilt" invisible$="[[!entityObj.supportsCloseTilt]]" disabled="[[computeClosedDisabled(stateObj, entityObj)]]"></paper-icon-button>
|
||||
`;
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
white-space: nowrap;
|
||||
}
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-top-right"
|
||||
on-click="onOpenTiltTap"
|
||||
title="Open tilt"
|
||||
invisible$="[[!entityObj.supportsOpenTilt]]"
|
||||
disabled="[[computeOpenDisabled(stateObj, entityObj)]]"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:stop"
|
||||
on-click="onStopTiltTap"
|
||||
invisible$="[[!entityObj.supportsStopTilt]]"
|
||||
title="Stop tilt"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-bottom-left"
|
||||
on-click="onCloseTiltTap"
|
||||
title="Close tilt"
|
||||
invisible$="[[!entityObj.supportsCloseTilt]]"
|
||||
disabled="[[computeClosedDisabled(stateObj, entityObj)]]"
|
||||
></paper-icon-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,14 +6,18 @@ import "./ha-label-badge";
|
||||
class HaDemoBadge extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
--ha-label-badge-color: #dac90d;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
:host {
|
||||
--ha-label-badge-color: #dac90d;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-label-badge icon="hass:emoticon" label="Demo" description=""></ha-label-badge>
|
||||
`;
|
||||
<ha-label-badge
|
||||
icon="hass:emoticon"
|
||||
label="Demo"
|
||||
description=""
|
||||
></ha-label-badge>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,107 +16,156 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaForm extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
paper-checkbox {
|
||||
display: inline-block;
|
||||
padding: 22px 0;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[_isArray(schema)]]" restamp="">
|
||||
<template is="dom-if" if="[[error.base]]">
|
||||
<div class='error'>[[computeError(error.base, schema)]]</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-repeat" items="[[schema]]">
|
||||
<ha-form data="[[_getValue(data, item)]]" schema="[[item]]" error="[[_getValue(error, item)]]" on-data-changed="_valueChanged" compute-label="[[computeLabel]]" compute-error="[[computeError]]"></ha-form>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_isArray(schema)]]" restamp="">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="error">[[computeError(error, schema)]]</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(schema.type, "string")]]" restamp="">
|
||||
<template is="dom-if" if="[[_includes(schema.name, "password")]]" restamp="">
|
||||
<paper-input
|
||||
type="[[_passwordFieldType(unmaskedPassword)]]"
|
||||
label="[[computeLabel(schema)]]"
|
||||
value="{{data}}"
|
||||
required="[[schema.required]]"
|
||||
auto-validate="[[schema.required]]"
|
||||
error-message='Required'
|
||||
>
|
||||
<paper-icon-button toggles
|
||||
active="{{unmaskedPassword}}"
|
||||
slot="suffix"
|
||||
icon="[[_passwordFieldIcon(unmaskedPassword)]]"
|
||||
id="iconButton"
|
||||
title="Click to toggle between masked and clear password">
|
||||
</paper-icon-button>
|
||||
</paper-input>
|
||||
<style>
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
paper-checkbox {
|
||||
display: inline-block;
|
||||
padding: 22px 0;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[_isArray(schema)]]" restamp="">
|
||||
<template is="dom-if" if="[[error.base]]">
|
||||
<div class="error">[[computeError(error.base, schema)]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_includes(schema.name, "password")]]" restamp="">
|
||||
|
||||
<template is="dom-repeat" items="[[schema]]">
|
||||
<ha-form
|
||||
data="[[_getValue(data, item)]]"
|
||||
schema="[[item]]"
|
||||
error="[[_getValue(error, item)]]"
|
||||
on-data-changed="_valueChanged"
|
||||
compute-label="[[computeLabel]]"
|
||||
compute-error="[[computeError]]"
|
||||
></ha-form>
|
||||
</template>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_isArray(schema)]]" restamp="">
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="error">[[computeError(error, schema)]]</div>
|
||||
</template>
|
||||
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(schema.type, "string")]]"
|
||||
restamp=""
|
||||
>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_includes(schema.name, "password")]]"
|
||||
restamp=""
|
||||
>
|
||||
<paper-input
|
||||
type="[[_passwordFieldType(unmaskedPassword)]]"
|
||||
label="[[computeLabel(schema)]]"
|
||||
value="{{data}}"
|
||||
required="[[schema.required]]"
|
||||
auto-validate="[[schema.required]]"
|
||||
error-message="Required"
|
||||
>
|
||||
<paper-icon-button
|
||||
toggles
|
||||
active="{{unmaskedPassword}}"
|
||||
slot="suffix"
|
||||
icon="[[_passwordFieldIcon(unmaskedPassword)]]"
|
||||
id="iconButton"
|
||||
title="Click to toggle between masked and clear password"
|
||||
>
|
||||
</paper-icon-button>
|
||||
</paper-input>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[!_includes(schema.name, "password")]]"
|
||||
restamp=""
|
||||
>
|
||||
<paper-input
|
||||
label="[[computeLabel(schema)]]"
|
||||
value="{{data}}"
|
||||
required="[[schema.required]]"
|
||||
auto-validate="[[schema.required]]"
|
||||
error-message="Required"
|
||||
></paper-input>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(schema.type, "integer")]]"
|
||||
restamp=""
|
||||
>
|
||||
<template is="dom-if" if="[[_isRange(schema)]]" restamp="">
|
||||
<div>
|
||||
[[computeLabel(schema)]]
|
||||
<ha-paper-slider
|
||||
pin=""
|
||||
value="{{data}}"
|
||||
min="[[schema.valueMin]]"
|
||||
max="[[schema.valueMax]]"
|
||||
></ha-paper-slider>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_isRange(schema)]]" restamp="">
|
||||
<paper-input
|
||||
label="[[computeLabel(schema)]]"
|
||||
value="{{data}}"
|
||||
type="number"
|
||||
required="[[schema.required]]"
|
||||
auto-validate="[[schema.required]]"
|
||||
error-message="Required"
|
||||
></paper-input>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(schema.type, "float")]]"
|
||||
restamp=""
|
||||
>
|
||||
<!-- TODO -->
|
||||
<paper-input
|
||||
label="[[computeLabel(schema)]]"
|
||||
value="{{data}}"
|
||||
required="[[schema.required]]"
|
||||
auto-validate="[[schema.required]]"
|
||||
error-message='Required'
|
||||
error-message="Required"
|
||||
></paper-input>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(schema.type, "integer")]]" restamp="">
|
||||
<template is="dom-if" if="[[_isRange(schema)]]" restamp="">
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(schema.type, "boolean")]]"
|
||||
restamp=""
|
||||
>
|
||||
<div>
|
||||
[[computeLabel(schema)]]
|
||||
<ha-paper-slider pin="" value="{{data}}" min="[[schema.valueMin]]" max="[[schema.valueMax]]"></ha-paper-slider>
|
||||
<paper-checkbox checked="{{data}}"
|
||||
>[[computeLabel(schema)]]</paper-checkbox
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_isRange(schema)]]" restamp="">
|
||||
<paper-input
|
||||
label="[[computeLabel(schema)]]"
|
||||
value="{{data}}"
|
||||
type="number"
|
||||
required="[[schema.required]]"
|
||||
auto-validate="[[schema.required]]"
|
||||
error-message='Required'
|
||||
></paper-input>
|
||||
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(schema.type, "select")]]"
|
||||
restamp=""
|
||||
>
|
||||
<paper-dropdown-menu label="[[computeLabel(schema)]]">
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
attr-for-selected="item-name"
|
||||
selected="{{data}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[schema.options]]">
|
||||
<paper-item item-name$="[[_optionValue(item)]]"
|
||||
>[[_optionLabel(item)]]</paper-item
|
||||
>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(schema.type, "float")]]" restamp="">
|
||||
<!--TODO-->
|
||||
<paper-input
|
||||
label="[[computeLabel(schema)]]"
|
||||
value="{{data}}"
|
||||
required="[[schema.required]]"
|
||||
auto-validate="[[schema.required]]"
|
||||
error-message='Required'
|
||||
></paper-input>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(schema.type, "boolean")]]" restamp="">
|
||||
<div>
|
||||
<paper-checkbox checked="{{data}}">[[computeLabel(schema)]]</paper-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(schema.type, "select")]]" restamp="">
|
||||
<paper-dropdown-menu label="[[computeLabel(schema)]]">
|
||||
<paper-listbox slot="dropdown-content" attr-for-selected="item-name" selected="{{data}}">
|
||||
<template is="dom-repeat" items="[[schema.options]]">
|
||||
<paper-item item-name$="[[_optionValue(item)]]">[[_optionLabel(item)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -5,94 +5,100 @@ import "./ha-icon";
|
||||
class HaLabelBadge extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.badge-container {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
.label-badge {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: var(--ha-label-badge-size, 2.5em);
|
||||
text-align: center;
|
||||
height: var(--ha-label-badge-size, 2.5em);
|
||||
line-height: var(--ha-label-badge-size, 2.5em);
|
||||
font-size: var(--ha-label-badge-font-size, 1.5em);
|
||||
border-radius: 50%;
|
||||
border: 0.1em solid var(--ha-label-badge-color, var(--primary-color));
|
||||
color: var(--label-badge-text-color, rgb(76, 76, 76));
|
||||
<style>
|
||||
.badge-container {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
.label-badge {
|
||||
position: relative;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: var(--ha-label-badge-size, 2.5em);
|
||||
text-align: center;
|
||||
height: var(--ha-label-badge-size, 2.5em);
|
||||
line-height: var(--ha-label-badge-size, 2.5em);
|
||||
font-size: var(--ha-label-badge-font-size, 1.5em);
|
||||
border-radius: 50%;
|
||||
border: 0.1em solid var(--ha-label-badge-color, var(--primary-color));
|
||||
color: var(--label-badge-text-color, rgb(76, 76, 76));
|
||||
|
||||
white-space: nowrap;
|
||||
background-color: var(--label-badge-background-color, white);
|
||||
background-size: cover;
|
||||
transition: border .3s ease-in-out;
|
||||
}
|
||||
.label-badge .value {
|
||||
font-size: 90%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.label-badge .value.big {
|
||||
font-size: 70%;
|
||||
}
|
||||
.label-badge .label {
|
||||
position: absolute;
|
||||
bottom: -1em;
|
||||
/* Make the label as wide as container+border. (parent_borderwidth / font-size) */
|
||||
left: -0.2em;
|
||||
right: -0.2em;
|
||||
line-height: 1em;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
.label-badge .label span {
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
background-color: var(--ha-label-badge-color, var(--primary-color));
|
||||
color: var(--ha-label-badge-label-color, white);
|
||||
border-radius: 1em;
|
||||
padding: 9% 16% 8% 16%; /* mostly apitalized text, not much descenders => bit more top margin */
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-transform: uppercase;
|
||||
text-overflow: ellipsis;
|
||||
transition: background-color .3s ease-in-out;
|
||||
text-transform: var(--ha-label-badge-label-text-transform, uppercase);
|
||||
}
|
||||
.label-badge .label.big span {
|
||||
font-size: 90%;
|
||||
padding: 10% 12% 7% 12%; /* push smaller text a bit down to center vertically */
|
||||
}
|
||||
.badge-container .title {
|
||||
margin-top: 1em;
|
||||
font-size: var(--ha-label-badge-title-font-size, .9em);
|
||||
width: var(--ha-label-badge-title-width, 5em);
|
||||
font-weight: var(--ha-label-badge-title-font-weight, 400);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: normal;
|
||||
}
|
||||
white-space: nowrap;
|
||||
background-color: var(--label-badge-background-color, white);
|
||||
background-size: cover;
|
||||
transition: border 0.3s ease-in-out;
|
||||
}
|
||||
.label-badge .value {
|
||||
font-size: 90%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.label-badge .value.big {
|
||||
font-size: 70%;
|
||||
}
|
||||
.label-badge .label {
|
||||
position: absolute;
|
||||
bottom: -1em;
|
||||
/* Make the label as wide as container+border. (parent_borderwidth / font-size) */
|
||||
left: -0.2em;
|
||||
right: -0.2em;
|
||||
line-height: 1em;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
.label-badge .label span {
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
display: inline-block;
|
||||
background-color: var(--ha-label-badge-color, var(--primary-color));
|
||||
color: var(--ha-label-badge-label-color, white);
|
||||
border-radius: 1em;
|
||||
padding: 9% 16% 8% 16%; /* mostly apitalized text, not much descenders => bit more top margin */
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
text-transform: uppercase;
|
||||
text-overflow: ellipsis;
|
||||
transition: background-color 0.3s ease-in-out;
|
||||
text-transform: var(--ha-label-badge-label-text-transform, uppercase);
|
||||
}
|
||||
.label-badge .label.big span {
|
||||
font-size: 90%;
|
||||
padding: 10% 12% 7% 12%; /* push smaller text a bit down to center vertically */
|
||||
}
|
||||
.badge-container .title {
|
||||
margin-top: 1em;
|
||||
font-size: var(--ha-label-badge-title-font-size, 0.9em);
|
||||
width: var(--ha-label-badge-title-width, 5em);
|
||||
font-weight: var(--ha-label-badge-title-font-weight, 400);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="badge-container">
|
||||
<div class="label-badge" id="badge">
|
||||
<div class$="[[computeValueClasses(value)]]">
|
||||
<ha-icon icon="[[icon]]" hidden$="[[computeHideIcon(icon, value, image)]]"></ha-icon>
|
||||
<span hidden$="[[computeHideValue(value, image)]]">[[value]]</span>
|
||||
</div>
|
||||
<div hidden$="[[computeHideLabel(label)]]" class$="[[computeLabelClasses(label)]]">
|
||||
<span>[[label]]</span>
|
||||
<div class="badge-container">
|
||||
<div class="label-badge" id="badge">
|
||||
<div class$="[[computeValueClasses(value)]]">
|
||||
<ha-icon
|
||||
icon="[[icon]]"
|
||||
hidden$="[[computeHideIcon(icon, value, image)]]"
|
||||
></ha-icon>
|
||||
<span hidden$="[[computeHideValue(value, image)]]">[[value]]</span>
|
||||
</div>
|
||||
<div
|
||||
hidden$="[[computeHideLabel(label)]]"
|
||||
class$="[[computeLabelClasses(label)]]"
|
||||
>
|
||||
<span>[[label]]</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title" hidden$="[[!description]]">[[description]]</div>
|
||||
</div>
|
||||
<div class="title" hidden$="[[!description]]">[[description]]</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,40 +7,42 @@ import "./ha-icon";
|
||||
class HaLabeledSlider extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 16px;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
.title {
|
||||
margin-bottom: 16px;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
|
||||
ha-icon {
|
||||
float: left;
|
||||
margin-top: 4px;
|
||||
opacity: var(--dark-secondary-opacity);
|
||||
}
|
||||
ha-icon {
|
||||
float: left;
|
||||
margin-top: 4px;
|
||||
opacity: var(--dark-secondary-opacity);
|
||||
}
|
||||
|
||||
ha-paper-slider {
|
||||
background-image: var(--ha-slider-background);
|
||||
}
|
||||
</style>
|
||||
ha-paper-slider {
|
||||
background-image: var(--ha-slider-background);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="title">[[caption]]</div>
|
||||
<div class="extra-container">
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<ha-icon icon="[[icon]]" hidden$="[[!icon]]"></ha-icon>
|
||||
<ha-paper-slider
|
||||
min="[[min]]" max="[[max]]" step="[[step]]"
|
||||
pin="[[pin]]" disabled="[[disabled]]" disabled="[[disabled]]"
|
||||
value="{{value}}"
|
||||
></ha-paper-slider>
|
||||
</div>
|
||||
`;
|
||||
<div class="title">[[caption]]</div>
|
||||
<div class="extra-container"><slot name="extra"></slot></div>
|
||||
<div class="slider-container">
|
||||
<ha-icon icon="[[icon]]" hidden$="[[!icon]]"></ha-icon>
|
||||
<ha-paper-slider
|
||||
min="[[min]]"
|
||||
max="[[max]]"
|
||||
step="[[step]]"
|
||||
pin="[[pin]]"
|
||||
disabled="[[disabled]]"
|
||||
disabled="[[disabled]]"
|
||||
value="{{value}}"
|
||||
></ha-paper-slider>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,11 +10,11 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaMenuButton extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<paper-icon-button
|
||||
icon="[[_getIcon(hassio)]]"
|
||||
on-click="toggleMenu"
|
||||
></paper-icon-button>
|
||||
`;
|
||||
<paper-icon-button
|
||||
icon="[[_getIcon(hassio)]]"
|
||||
on-click="toggleMenu"
|
||||
></paper-icon-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -17,11 +17,11 @@ export const pushSupported =
|
||||
class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<paper-toggle-button
|
||||
disabled="[[_compDisabled(disabled, loading)]]"
|
||||
checked="{{pushChecked}}"
|
||||
></paper-toggle-button>
|
||||
`;
|
||||
<paper-toggle-button
|
||||
disabled="[[_compDisabled(disabled, loading)]]"
|
||||
checked="{{pushChecked}}"
|
||||
></paper-toggle-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -4,8 +4,8 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HaServiceDescription extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
[[_getDescription(hass, domain, service)]]
|
||||
`;
|
||||
[[_getDescription(hass, domain, service)]]
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,8 +11,13 @@ import LocalizeMixin from "../mixins/localize-mixin";
|
||||
class HaServicePicker extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<ha-combo-box label="[[localize('ui.components.service-picker.service')]]" items="[[_services]]" value="{{value}}" allow-custom-value=""></ha-combo-box>
|
||||
`;
|
||||
<ha-combo-box
|
||||
label="[[localize('ui.components.service-picker.service')]]"
|
||||
items="[[_services]]"
|
||||
value="{{value}}"
|
||||
allow-custom-value=""
|
||||
></ha-combo-box>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,8 +12,12 @@ import isComponentLoaded from "../common/config/is_component_loaded";
|
||||
class HaStartVoiceButton extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<paper-icon-button icon="hass:microphone" hidden$="[[!canListen]]" on-click="handleListenClick"></paper-icon-button>
|
||||
`;
|
||||
<paper-icon-button
|
||||
icon="hass:microphone"
|
||||
hidden$="[[!canListen]]"
|
||||
on-click="handleListenClick"
|
||||
></paper-icon-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -21,10 +21,7 @@ class HaTextarea extends PolymerElement {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
<paper-textarea
|
||||
label='[[label]]'
|
||||
value='{{value}}'
|
||||
></paper-textarea>
|
||||
<paper-textarea label="[[label]]" value="{{value}}"></paper-textarea>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ class HaVacuumState extends LocalizeMixin(PolymerElement) {
|
||||
font-weight: 500;
|
||||
top: 3px;
|
||||
height: 37px;
|
||||
margin-right: -.57em;
|
||||
margin-right: -0.57em;
|
||||
}
|
||||
paper-button[disabled] {
|
||||
background-color: transparent;
|
||||
@ -51,10 +51,9 @@ class HaVacuumState extends LocalizeMixin(PolymerElement) {
|
||||
}
|
||||
</style>
|
||||
|
||||
<paper-button
|
||||
on-click="_callService"
|
||||
disabled="[[!_interceptable]]"
|
||||
>[[_computeLabel(stateObj.state, _interceptable)]]</paper-button>
|
||||
<paper-button on-click="_callService" disabled="[[!_interceptable]]"
|
||||
>[[_computeLabel(stateObj.state, _interceptable)]]</paper-button
|
||||
>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -11,44 +11,48 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaWaterHeaterControl extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
/* local DOM styles go here */
|
||||
:host {
|
||||
@apply --layout-flex;
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
.in-flux#target_temperature {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
#target_temperature {
|
||||
@apply --layout-self-center;
|
||||
font-size: 200%;
|
||||
}
|
||||
.control-buttons {
|
||||
font-size: 200%;
|
||||
text-align: right;
|
||||
}
|
||||
paper-icon-button {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
</style>
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
/* local DOM styles go here */
|
||||
:host {
|
||||
@apply --layout-flex;
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
.in-flux#target_temperature {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
#target_temperature {
|
||||
@apply --layout-self-center;
|
||||
font-size: 200%;
|
||||
}
|
||||
.control-buttons {
|
||||
font-size: 200%;
|
||||
text-align: right;
|
||||
}
|
||||
paper-icon-button {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- local DOM goes here -->
|
||||
<div id="target_temperature">
|
||||
[[value]] [[units]]
|
||||
</div>
|
||||
<div class="control-buttons">
|
||||
<div>
|
||||
<paper-icon-button icon="hass:chevron-up" on-click="incrementValue"></paper-icon-button>
|
||||
<!-- local DOM goes here -->
|
||||
<div id="target_temperature">[[value]] [[units]]</div>
|
||||
<div class="control-buttons">
|
||||
<div>
|
||||
<paper-icon-button
|
||||
icon="hass:chevron-up"
|
||||
on-click="incrementValue"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div>
|
||||
<paper-icon-button
|
||||
icon="hass:chevron-down"
|
||||
on-click="decrementValue"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<paper-icon-button icon="hass:chevron-down" on-click="decrementValue"></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,41 +9,39 @@ import LocalizeMixin from "../mixins/localize-mixin";
|
||||
class HaWaterHeaterState extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.target {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.target {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.current {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.current {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.state-label {
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
</style>
|
||||
.state-label {
|
||||
font-weight: bold;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="target">
|
||||
<span class="state-label">
|
||||
[[_localizeState(stateObj.state)]]
|
||||
</span>
|
||||
[[computeTarget(hass, stateObj)]]
|
||||
</div>
|
||||
|
||||
<template is="dom-if" if="[[currentStatus]]">
|
||||
<div class="current">
|
||||
[[localize('ui.card.water_heater.currently')]]: [[currentStatus]]
|
||||
<div class="target">
|
||||
<span class="state-label"> [[_localizeState(stateObj.state)]] </span>
|
||||
[[computeTarget(hass, stateObj)]]
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
|
||||
<template is="dom-if" if="[[currentStatus]]">
|
||||
<div class="current">
|
||||
[[localize('ui.card.water_heater.currently')]]: [[currentStatus]]
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -43,13 +43,11 @@ class PaperTimeInput extends PolymerElement {
|
||||
-moz-appearance: textfield;
|
||||
@apply --paper-time-input-cotnainer;
|
||||
}
|
||||
;
|
||||
--paper-input-container-input-webkit-spinner: {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
display: none;
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
paper-dropdown-menu {
|
||||
@ -57,20 +55,23 @@ class PaperTimeInput extends PolymerElement {
|
||||
padding: 0;
|
||||
/* Force ripple to use the whole container */
|
||||
--paper-dropdown-menu-ripple: {
|
||||
color: var(--paper-time-input-dropdown-ripple-color, var(--primary-color));
|
||||
};
|
||||
color: var(
|
||||
--paper-time-input-dropdown-ripple-color,
|
||||
var(--primary-color)
|
||||
);
|
||||
}
|
||||
--paper-input-container-input: {
|
||||
@apply --paper-font-button;
|
||||
text-align: center;
|
||||
padding-left: 5px;
|
||||
@apply --paper-time-dropdown-input-cotnainer;
|
||||
};
|
||||
}
|
||||
--paper-input-container-underline: {
|
||||
border-color: transparent;
|
||||
}
|
||||
--paper-input-container-underline-focus: {
|
||||
border-color: transparent;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
paper-item {
|
||||
@ -99,27 +100,58 @@ class PaperTimeInput extends PolymerElement {
|
||||
|
||||
<label hidden$="[[hideLabel]]">[[label]]</label>
|
||||
<div class="time-input-wrap">
|
||||
|
||||
<!-- Hour Input -->
|
||||
<paper-input id="hour" type="number" value="{{hour}}" on-change="_shouldFormatHour" required="" auto-validate="[[autoValidate]]"
|
||||
prevent-invalid-input="" maxlength="2" max="[[_computeHourMax(format)]]" min="0" no-label-float="" disabled="[[disabled]]">
|
||||
<paper-input
|
||||
id="hour"
|
||||
type="number"
|
||||
value="{{hour}}"
|
||||
on-change="_shouldFormatHour"
|
||||
required=""
|
||||
auto-validate="[[autoValidate]]"
|
||||
prevent-invalid-input=""
|
||||
maxlength="2"
|
||||
max="[[_computeHourMax(format)]]"
|
||||
min="0"
|
||||
no-label-float=""
|
||||
disabled="[[disabled]]"
|
||||
>
|
||||
<span suffix="" slot="suffix">:</span>
|
||||
</paper-input>
|
||||
|
||||
<!-- Min Input -->
|
||||
<paper-input id="min" type="number" value="{{min}}" on-change="_formatMin" required="" auto-validate="[[autoValidate]]" prevent-invalid-input=""
|
||||
maxlength="2" max="59" min="0" no-label-float="" disabled="[[disabled]]">
|
||||
<paper-input
|
||||
id="min"
|
||||
type="number"
|
||||
value="{{min}}"
|
||||
on-change="_formatMin"
|
||||
required=""
|
||||
auto-validate="[[autoValidate]]"
|
||||
prevent-invalid-input=""
|
||||
maxlength="2"
|
||||
max="59"
|
||||
min="0"
|
||||
no-label-float=""
|
||||
disabled="[[disabled]]"
|
||||
>
|
||||
</paper-input>
|
||||
|
||||
<!-- Dropdown Menu -->
|
||||
<paper-dropdown-menu id="dropdown" required="" hidden$="[[_equal(format, 24)]]" no-label-float="" disabled="[[disabled]]">
|
||||
|
||||
<paper-listbox attr-for-selected="name" selected="{{amPm}}" slot="dropdown-content">
|
||||
<paper-dropdown-menu
|
||||
id="dropdown"
|
||||
required=""
|
||||
hidden$="[[_equal(format, 24)]]"
|
||||
no-label-float=""
|
||||
disabled="[[disabled]]"
|
||||
>
|
||||
<paper-listbox
|
||||
attr-for-selected="name"
|
||||
selected="{{amPm}}"
|
||||
slot="dropdown-content"
|
||||
>
|
||||
<paper-item name="AM">AM</paper-item>
|
||||
<paper-item name="PM">PM</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -10,16 +10,21 @@ import formatDateTime from "../common/datetime/format_date_time";
|
||||
class StateHistoryChartLine extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
height: 0;
|
||||
transition: height 0.3s ease-in-out;
|
||||
}
|
||||
</style>
|
||||
<ha-chart-base id="chart" data="[[chartData]]" identifier="[[identifier]]" rendered="{{rendered}}"></ha-chart-base>
|
||||
`;
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
height: 0;
|
||||
transition: height 0.3s ease-in-out;
|
||||
}
|
||||
</style>
|
||||
<ha-chart-base
|
||||
id="chart"
|
||||
data="[[chartData]]"
|
||||
identifier="[[identifier]]"
|
||||
rendered="{{rendered}}"
|
||||
></ha-chart-base>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,19 +11,21 @@ import formatDateTime from "../common/datetime/format_date_time";
|
||||
class StateHistoryChartTimeline extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
}
|
||||
:host([rendered]) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
</style>
|
||||
<ha-chart-base data="[[chartData]]" rendered="{{rendered}}"></ha-chart-base>
|
||||
`;
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease-in-out;
|
||||
}
|
||||
:host([rendered]) {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
<ha-chart-base
|
||||
data="[[chartData]]"
|
||||
rendered="{{rendered}}"
|
||||
></ha-chart-base>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,48 +10,60 @@ import LocalizeMixin from "../mixins/localize-mixin";
|
||||
class StateHistoryCharts extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
/* height of single timeline chart = 58px */
|
||||
min-height: 58px;
|
||||
}
|
||||
.info {
|
||||
text-align: center;
|
||||
line-height: 58px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" class="info" if="[[_computeIsLoading(isLoadingData)]]">
|
||||
<div class="info">[[localize('ui.components.history_charts.loading_history')]]</div>
|
||||
</template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
/* height of single timeline chart = 58px */
|
||||
min-height: 58px;
|
||||
}
|
||||
.info {
|
||||
text-align: center;
|
||||
line-height: 58px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<template
|
||||
is="dom-if"
|
||||
class="info"
|
||||
if="[[_computeIsLoading(isLoadingData)]]"
|
||||
>
|
||||
<div class="info">
|
||||
[[localize('ui.components.history_charts.loading_history')]]
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" class="info" if="[[_computeIsEmpty(isLoadingData, historyData)]]">
|
||||
<div class="info">[[localize('ui.components.history_charts.no_history_found')]]</div>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
class="info"
|
||||
if="[[_computeIsEmpty(isLoadingData, historyData)]]"
|
||||
>
|
||||
<div class="info">
|
||||
[[localize('ui.components.history_charts.no_history_found')]]
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[historyData.timeline.length]]">
|
||||
<state-history-chart-timeline
|
||||
hass='[[hass]]'
|
||||
data="[[historyData.timeline]]"
|
||||
end-time="[[_computeEndTime(endTime, upToNow, historyData)]]"
|
||||
no-single="[[noSingle]]"
|
||||
names="[[names]]"
|
||||
></state-history-chart-timeline>
|
||||
</template>
|
||||
<template is="dom-if" if="[[historyData.timeline.length]]">
|
||||
<state-history-chart-timeline
|
||||
hass="[[hass]]"
|
||||
data="[[historyData.timeline]]"
|
||||
end-time="[[_computeEndTime(endTime, upToNow, historyData)]]"
|
||||
no-single="[[noSingle]]"
|
||||
names="[[names]]"
|
||||
></state-history-chart-timeline>
|
||||
</template>
|
||||
|
||||
<template is="dom-repeat" items="[[historyData.line]]">
|
||||
<state-history-chart-line
|
||||
hass='[[hass]]'
|
||||
unit="[[item.unit]]"
|
||||
data="[[item.data]]"
|
||||
identifier="[[item.identifier]]"
|
||||
is-single-device="[[_computeIsSingleLineChart(item.data, noSingle)]]"
|
||||
end-time="[[_computeEndTime(endTime, upToNow, historyData)]]"
|
||||
names="[[names]]"
|
||||
></state-history-chart-line>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-repeat" items="[[historyData.line]]">
|
||||
<state-history-chart-line
|
||||
hass="[[hass]]"
|
||||
unit="[[item.unit]]"
|
||||
data="[[item.data]]"
|
||||
identifier="[[item.identifier]]"
|
||||
is-single-device="[[_computeIsSingleLineChart(item.data, noSingle)]]"
|
||||
end-time="[[_computeEndTime(endTime, upToNow, historyData)]]"
|
||||
names="[[names]]"
|
||||
></state-history-chart-line>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -19,67 +19,82 @@ import DialogMixin from "../mixins/dialog-mixin";
|
||||
class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style-dialog paper-dialog-shared-styles">
|
||||
:host {
|
||||
font-size: 14px;
|
||||
width: 365px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
more-info-controls, more-info-settings {
|
||||
--more-info-header-background: var(--secondary-background-color);
|
||||
--more-info-header-color: var(--primary-text-color);
|
||||
--ha-more-info-app-toolbar-title: {
|
||||
/* Design guideline states 24px, changed to 16 to align with state info */
|
||||
margin-left: 16px;
|
||||
line-height: 1.3em;
|
||||
max-height: 2.6em;
|
||||
overflow: hidden;
|
||||
/* webkit and blink still support simple multiline text-overflow */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
/* overrule the ha-style-dialog max-height on small screens */
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
more-info-controls, more-info-settings {
|
||||
--more-info-header-background: var(--primary-color);
|
||||
--more-info-header-color: var(--text-primary-color);
|
||||
}
|
||||
<style include="ha-style-dialog paper-dialog-shared-styles">
|
||||
:host {
|
||||
@apply --ha-dialog-fullscreen;
|
||||
font-size: 14px;
|
||||
width: 365px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
:host::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: inherit;
|
||||
|
||||
more-info-controls,
|
||||
more-info-settings {
|
||||
--more-info-header-background: var(--secondary-background-color);
|
||||
--more-info-header-color: var(--primary-text-color);
|
||||
--ha-more-info-app-toolbar-title: {
|
||||
/* Design guideline states 24px, changed to 16 to align with state info */
|
||||
margin-left: 16px;
|
||||
line-height: 1.3em;
|
||||
max-height: 2.6em;
|
||||
overflow: hidden;
|
||||
/* webkit and blink still support simple multiline text-overflow */
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:host([data-domain=camera]) {
|
||||
width: auto;
|
||||
}
|
||||
/* overrule the ha-style-dialog max-height on small screens */
|
||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||
more-info-controls,
|
||||
more-info-settings {
|
||||
--more-info-header-background: var(--primary-color);
|
||||
--more-info-header-color: var(--text-primary-color);
|
||||
}
|
||||
:host {
|
||||
@apply --ha-dialog-fullscreen;
|
||||
}
|
||||
:host::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
:host([data-domain=history_graph]), :host([large]) {
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
:host([data-domain="camera"]) {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
<template is="dom-if" if="[[!_page]]">
|
||||
<more-info-controls class="no-padding" hass="[[hass]]" state-obj="[[stateObj]]" dialog-element="[[_dialogElement]]" can-configure="[[_registryInfo]]" large="{{large}}"></more-info-controls>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_page, "settings")]]">
|
||||
<more-info-settings class="no-padding" hass="[[hass]]" state-obj="[[stateObj]]" registry-info="{{_registryInfo}}"></more-info-settings>
|
||||
</template>
|
||||
`;
|
||||
:host([data-domain="history_graph"]),
|
||||
:host([large]) {
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[!_page]]">
|
||||
<more-info-controls
|
||||
class="no-padding"
|
||||
hass="[[hass]]"
|
||||
state-obj="[[stateObj]]"
|
||||
dialog-element="[[_dialogElement]]"
|
||||
can-configure="[[_registryInfo]]"
|
||||
large="{{large}}"
|
||||
></more-info-controls>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_page, "settings")]]">
|
||||
<more-info-settings
|
||||
class="no-padding"
|
||||
hass="[[hass]]"
|
||||
state-obj="[[stateObj]]"
|
||||
registry-info="{{_registryInfo}}"
|
||||
></more-info-settings>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,7 +10,7 @@ import "../resources/ha-style";
|
||||
class HaStoreAuth extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include='ha-style'>
|
||||
<style include="ha-style">
|
||||
paper-card {
|
||||
position: fixed;
|
||||
padding: 8px 0;
|
||||
@ -31,12 +31,14 @@ class HaStoreAuth extends LocalizeMixin(PolymerElement) {
|
||||
}
|
||||
</style>
|
||||
<paper-card elevation="4">
|
||||
<div class='card-content'>
|
||||
[[localize('ui.auth_store.ask')]]
|
||||
</div>
|
||||
<div class='card-actions'>
|
||||
<paper-button on-click='_done'>[[localize('ui.auth_store.decline')]]</paper-button>
|
||||
<paper-button primary on-click='_save'>[[localize('ui.auth_store.confirm')]]</paper-button>
|
||||
<div class="card-content">[[localize('ui.auth_store.ask')]]</div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="_done"
|
||||
>[[localize('ui.auth_store.decline')]]</paper-button
|
||||
>
|
||||
<paper-button primary on-click="_save"
|
||||
>[[localize('ui.auth_store.confirm')]]</paper-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
|
||||
@ -12,124 +12,128 @@ import DialogMixin from "../mixins/dialog-mixin";
|
||||
class HaVoiceCommandDialog extends DialogMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="paper-dialog-shared-styles">
|
||||
iron-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 450px;
|
||||
min-height: 80px;
|
||||
font-size: 18px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.messages {
|
||||
max-height: 50vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.messages::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message {
|
||||
clear: both;
|
||||
margin: 8px 0;
|
||||
padding: 8px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
margin-left: 24px;
|
||||
float: right;
|
||||
text-align: right;
|
||||
border-bottom-right-radius: 0px;
|
||||
background-color: var(--light-primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.message.hass {
|
||||
margin-right: 24px;
|
||||
float: left;
|
||||
border-bottom-left-radius: 0px;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
|
||||
.message.error {
|
||||
background-color: var(--google-red-500);
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
|
||||
.icon {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.icon paper-icon-button {
|
||||
height: 52px;
|
||||
width: 52px;
|
||||
}
|
||||
|
||||
.interimTranscript {
|
||||
color: darkgrey;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@media all and (max-width: 450px) {
|
||||
:host {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
max-height: calc(100% - 64px);
|
||||
|
||||
position: fixed !important;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
overflow: scroll;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
<style include="paper-dialog-shared-styles">
|
||||
iron-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: auto;
|
||||
width: 450px;
|
||||
min-height: 80px;
|
||||
font-size: 18px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.messages {
|
||||
max-height: 68vh;
|
||||
max-height: 50vh;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="content">
|
||||
<div class="messages" id="messages">
|
||||
<template is="dom-repeat" items="[[_conversation]]" as="message">
|
||||
<div class$="[[_computeMessageClasses(message)]]">[[message.text]]</div>
|
||||
</template>
|
||||
</div>
|
||||
<template is="dom-if" if="[[results]]">
|
||||
<div class="messages">
|
||||
<div class="message user">
|
||||
<span>{{results.final}}</span>
|
||||
<span class="interimTranscript">[[results.interim]]</span>
|
||||
…
|
||||
</div>
|
||||
.messages::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message {
|
||||
clear: both;
|
||||
margin: 8px 0;
|
||||
padding: 8px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
margin-left: 24px;
|
||||
float: right;
|
||||
text-align: right;
|
||||
border-bottom-right-radius: 0px;
|
||||
background-color: var(--light-primary-color);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.message.hass {
|
||||
margin-right: 24px;
|
||||
float: left;
|
||||
border-bottom-left-radius: 0px;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
|
||||
.message.error {
|
||||
background-color: var(--google-red-500);
|
||||
color: var(--text-primary-color);
|
||||
}
|
||||
|
||||
.icon {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.icon paper-icon-button {
|
||||
height: 52px;
|
||||
width: 52px;
|
||||
}
|
||||
|
||||
.interimTranscript {
|
||||
color: darkgrey;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:host {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@media all and (max-width: 450px) {
|
||||
:host {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
max-height: calc(100% - 64px);
|
||||
|
||||
position: fixed !important;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
overflow: scroll;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.messages {
|
||||
max-height: 68vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="content">
|
||||
<div class="messages" id="messages">
|
||||
<template is="dom-repeat" items="[[_conversation]]" as="message">
|
||||
<div class$="[[_computeMessageClasses(message)]]">
|
||||
[[message.text]]
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<template is="dom-if" if="[[results]]">
|
||||
<div class="messages">
|
||||
<div class="message user">
|
||||
<span>{{results.final}}</span>
|
||||
<span class="interimTranscript">[[results.interim]]</span> …
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="icon" hidden$="[[results]]">
|
||||
<paper-icon-button
|
||||
icon="hass:text-to-speech"
|
||||
on-click="startListening"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="icon" hidden$="[[results]]">
|
||||
<paper-icon-button icon="hass:text-to-speech" on-click="startListening"></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -51,21 +51,85 @@ class MoreInfoAlarmControlPanel extends LocalizeMixin(
|
||||
<template is="dom-if" if="[[_isNumber(_codeFormat)]]">
|
||||
<div class="pad">
|
||||
<div>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="1" raised>1</paper-button>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="4" raised>4</paper-button>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="7" raised>7</paper-button>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="1"
|
||||
raised
|
||||
>1</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="4"
|
||||
raised
|
||||
>4</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="7"
|
||||
raised
|
||||
>7</paper-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="2" raised>2</paper-button>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="5" raised>5</paper-button>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="8" raised>8</paper-button>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="0" raised>0</paper-button>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="2"
|
||||
raised
|
||||
>2</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="5"
|
||||
raised
|
||||
>5</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="8"
|
||||
raised
|
||||
>8</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="0"
|
||||
raised
|
||||
>0</paper-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="3" raised>3</paper-button>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="6" raised>6</paper-button>
|
||||
<paper-button on-click='_digitClicked' disabled='[[!_inputEnabled]]' data-digit="9" raised>9</paper-button>
|
||||
<paper-button on-click='_clearEnteredCode' disabled='[[!_inputEnabled]]' raised>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="3"
|
||||
raised
|
||||
>3</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="6"
|
||||
raised
|
||||
>6</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_digitClicked"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
data-digit="9"
|
||||
raised
|
||||
>9</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="_clearEnteredCode"
|
||||
disabled="[[!_inputEnabled]]"
|
||||
raised
|
||||
>
|
||||
[[localize('ui.card.alarm_control_panel.clear_code')]]
|
||||
</paper-button>
|
||||
</div>
|
||||
@ -75,15 +139,31 @@ class MoreInfoAlarmControlPanel extends LocalizeMixin(
|
||||
|
||||
<div class="layout horizontal center-justified actions">
|
||||
<template is="dom-if" if="[[_disarmVisible]]">
|
||||
<paper-button raised class="disarm" on-click="_callService" data-service="alarm_disarm" disabled="[[!_codeValid]]">
|
||||
<paper-button
|
||||
raised
|
||||
class="disarm"
|
||||
on-click="_callService"
|
||||
data-service="alarm_disarm"
|
||||
disabled="[[!_codeValid]]"
|
||||
>
|
||||
[[localize('ui.card.alarm_control_panel.disarm')]]
|
||||
</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_armVisible]]">
|
||||
<paper-button raised on-click="_callService" data-service="alarm_arm_home" disabled="[[!_codeValid]]">
|
||||
<paper-button
|
||||
raised
|
||||
on-click="_callService"
|
||||
data-service="alarm_arm_home"
|
||||
disabled="[[!_codeValid]]"
|
||||
>
|
||||
[[localize('ui.card.alarm_control_panel.arm_home')]]
|
||||
</paper-button>
|
||||
<paper-button raised on-click="_callService" data-service="alarm_arm_away" disabled="[[!_codeValid]]">
|
||||
<paper-button
|
||||
raised
|
||||
on-click="_callService"
|
||||
data-service="alarm_arm_away"
|
||||
disabled="[[!_codeValid]]"
|
||||
>
|
||||
[[localize('ui.card.alarm_control_panel.arm_away')]]
|
||||
</paper-button>
|
||||
</template>
|
||||
|
||||
@ -25,10 +25,11 @@ class MoreInfoAutomation extends LocalizeMixin(PolymerElement) {
|
||||
</style>
|
||||
|
||||
<div class="flex">
|
||||
<div>
|
||||
[[localize('ui.card.automation.last_triggered')]]:
|
||||
</div>
|
||||
<ha-relative-time hass="[[hass]]" datetime="[[stateObj.attributes.last_triggered]]"></ha-relative-time>
|
||||
<div>[[localize('ui.card.automation.last_triggered')]]:</div>
|
||||
<ha-relative-time
|
||||
hass="[[hass]]"
|
||||
datetime="[[stateObj.attributes.last_triggered]]"
|
||||
></ha-relative-time>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
|
||||
@ -11,18 +11,23 @@ import EventsMixin from "../../../mixins/events-mixin";
|
||||
class MoreInfoCamera extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
max-width:640px;
|
||||
}
|
||||
<style>
|
||||
:host {
|
||||
max-width: 640px;
|
||||
}
|
||||
|
||||
.camera-image {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
.camera-image {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<img class="camera-image" src="[[computeCameraImageUrl(hass, stateObj, isVisible)]]" on-load="imageLoaded" alt="[[_computeStateName(stateObj)]]">
|
||||
`;
|
||||
<img
|
||||
class="camera-image"
|
||||
src="[[computeCameraImageUrl(hass, stateObj, isVisible)]]"
|
||||
on-load="imageLoaded"
|
||||
alt="[[_computeStateName(stateObj)]]"
|
||||
/>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -24,188 +24,262 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class MoreInfoClimate extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.container-on,
|
||||
.container-away_mode,
|
||||
.container-aux_heat,
|
||||
.container-temperature,
|
||||
.container-humidity,
|
||||
.container-operation_list,
|
||||
.container-fan_list,
|
||||
.container-swing_list {
|
||||
display: none;
|
||||
}
|
||||
.container-on,
|
||||
.container-away_mode,
|
||||
.container-aux_heat,
|
||||
.container-temperature,
|
||||
.container-humidity,
|
||||
.container-operation_list,
|
||||
.container-fan_list,
|
||||
.container-swing_list {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.has-on .container-on,
|
||||
.has-away_mode .container-away_mode,
|
||||
.has-aux_heat .container-aux_heat,
|
||||
.has-target_temperature .container-temperature,
|
||||
.has-target_temperature_low .container-temperature,
|
||||
.has-target_temperature_high .container-temperature,
|
||||
.has-target_humidity .container-humidity,
|
||||
.has-operation_mode .container-operation_list,
|
||||
.has-fan_mode .container-fan_list,
|
||||
.has-swing_list .container-swing_list,
|
||||
.has-swing_mode .container-swing_list {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.has-on .container-on,
|
||||
.has-away_mode .container-away_mode,
|
||||
.has-aux_heat .container-aux_heat,
|
||||
.has-target_temperature .container-temperature,
|
||||
.has-target_temperature_low .container-temperature,
|
||||
.has-target_temperature_high .container-temperature,
|
||||
.has-target_humidity .container-humidity,
|
||||
.has-operation_mode .container-operation_list,
|
||||
.has-fan_mode .container-fan_list,
|
||||
.has-swing_list .container-swing_list,
|
||||
.has-swing_mode .container-swing_list {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.container-operation_list iron-icon,
|
||||
.container-fan_list iron-icon,
|
||||
.container-swing_list iron-icon {
|
||||
margin: 22px 16px 0 0;
|
||||
}
|
||||
.container-operation_list iron-icon,
|
||||
.container-fan_list iron-icon,
|
||||
.container-swing_list iron-icon {
|
||||
margin: 22px 16px 0 0;
|
||||
}
|
||||
|
||||
paper-dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
paper-dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ha-paper-slider {
|
||||
width: 100%;
|
||||
}
|
||||
ha-paper-slider {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container-humidity .single-row {
|
||||
display: flex;
|
||||
height: 50px;
|
||||
}
|
||||
.container-humidity .single-row {
|
||||
display: flex;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.target-humidity {
|
||||
width: 90px;
|
||||
font-size: 200%;
|
||||
margin: auto;
|
||||
}
|
||||
.target-humidity {
|
||||
width: 90px;
|
||||
font-size: 200%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
ha-climate-control.range-control-left,
|
||||
ha-climate-control.range-control-right {
|
||||
float: left;
|
||||
width: 46%;
|
||||
}
|
||||
ha-climate-control.range-control-left {
|
||||
margin-right: 4%;
|
||||
}
|
||||
ha-climate-control.range-control-right {
|
||||
margin-left: 4%;
|
||||
}
|
||||
ha-climate-control.range-control-left,
|
||||
ha-climate-control.range-control-right {
|
||||
float: left;
|
||||
width: 46%;
|
||||
}
|
||||
ha-climate-control.range-control-left {
|
||||
margin-right: 4%;
|
||||
}
|
||||
ha-climate-control.range-control-right {
|
||||
margin-left: 4%;
|
||||
}
|
||||
|
||||
.humidity {
|
||||
--paper-slider-active-color: var(--paper-blue-400);
|
||||
--paper-slider-secondary-color: var(--paper-blue-400);
|
||||
}
|
||||
.humidity {
|
||||
--paper-slider-active-color: var(--paper-blue-400);
|
||||
--paper-slider-secondary-color: var(--paper-blue-400);
|
||||
}
|
||||
|
||||
.single-row {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.single-row {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<template is="dom-if" if="[[supportsOn(stateObj)]]">
|
||||
<div class="container-on">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.climate.on_off')]]</div>
|
||||
<paper-toggle-button
|
||||
checked="[[onToggleChecked]]"
|
||||
on-change="onToggleChanged"
|
||||
>
|
||||
</paper-toggle-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsOn(stateObj)]]">
|
||||
<div class="container-on">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.climate.on_off')]]</div>
|
||||
<paper-toggle-button checked="[[onToggleChecked]]" on-change="onToggleChanged">
|
||||
</paper-toggle-button>
|
||||
<div class="container-temperature">
|
||||
<div class$="[[stateObj.attributes.operation_mode]]">
|
||||
<div hidden$="[[!supportsTemperatureControls(stateObj)]]">
|
||||
[[localize('ui.card.climate.target_temperature')]]
|
||||
</div>
|
||||
<template is="dom-if" if="[[supportsTemperature(stateObj)]]">
|
||||
<ha-climate-control
|
||||
value="[[stateObj.attributes.temperature]]"
|
||||
units="[[hass.config.unit_system.temperature]]"
|
||||
step="[[computeTemperatureStepSize(hass, stateObj)]]"
|
||||
min="[[stateObj.attributes.min_temp]]"
|
||||
max="[[stateObj.attributes.max_temp]]"
|
||||
on-change="targetTemperatureChanged"
|
||||
>
|
||||
</ha-climate-control>
|
||||
</template>
|
||||
<template is="dom-if" if="[[supportsTemperatureRange(stateObj)]]">
|
||||
<ha-climate-control
|
||||
value="[[stateObj.attributes.target_temp_low]]"
|
||||
units="[[hass.config.unit_system.temperature]]"
|
||||
step="[[computeTemperatureStepSize(hass, stateObj)]]"
|
||||
min="[[stateObj.attributes.min_temp]]"
|
||||
max="[[stateObj.attributes.target_temp_high]]"
|
||||
class="range-control-left"
|
||||
on-change="targetTemperatureLowChanged"
|
||||
>
|
||||
</ha-climate-control>
|
||||
<ha-climate-control
|
||||
value="[[stateObj.attributes.target_temp_high]]"
|
||||
units="[[hass.config.unit_system.temperature]]"
|
||||
step="[[computeTemperatureStepSize(hass, stateObj)]]"
|
||||
min="[[stateObj.attributes.target_temp_low]]"
|
||||
max="[[stateObj.attributes.max_temp]]"
|
||||
class="range-control-right"
|
||||
on-change="targetTemperatureHighChanged"
|
||||
>
|
||||
</ha-climate-control>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="container-temperature">
|
||||
<div class$="[[stateObj.attributes.operation_mode]]">
|
||||
<div hidden$="[[!supportsTemperatureControls(stateObj)]]">[[localize('ui.card.climate.target_temperature')]]</div>
|
||||
<template is="dom-if" if="[[supportsTemperature(stateObj)]]">
|
||||
<ha-climate-control value="[[stateObj.attributes.temperature]]" units="[[hass.config.unit_system.temperature]]" step="[[computeTemperatureStepSize(hass, stateObj)]]" min="[[stateObj.attributes.min_temp]]" max="[[stateObj.attributes.max_temp]]" on-change="targetTemperatureChanged">
|
||||
</ha-climate-control>
|
||||
</template>
|
||||
<template is="dom-if" if="[[supportsTemperatureRange(stateObj)]]">
|
||||
<ha-climate-control value="[[stateObj.attributes.target_temp_low]]" units="[[hass.config.unit_system.temperature]]" step="[[computeTemperatureStepSize(hass, stateObj)]]" min="[[stateObj.attributes.min_temp]]" max="[[stateObj.attributes.target_temp_high]]" class="range-control-left" on-change="targetTemperatureLowChanged">
|
||||
</ha-climate-control>
|
||||
<ha-climate-control value="[[stateObj.attributes.target_temp_high]]" units="[[hass.config.unit_system.temperature]]" step="[[computeTemperatureStepSize(hass, stateObj)]]" min="[[stateObj.attributes.target_temp_low]]" max="[[stateObj.attributes.max_temp]]" class="range-control-right" on-change="targetTemperatureHighChanged">
|
||||
</ha-climate-control>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template is="dom-if" if="[[supportsHumidity(stateObj)]]">
|
||||
<div class="container-humidity">
|
||||
<div>[[localize('ui.card.climate.target_humidity')]]</div>
|
||||
<template is="dom-if" if="[[supportsHumidity(stateObj)]]">
|
||||
<div class="container-humidity">
|
||||
<div>[[localize('ui.card.climate.target_humidity')]]</div>
|
||||
<div class="single-row">
|
||||
<div class="target-humidity">[[stateObj.attributes.humidity]] %</div>
|
||||
<ha-paper-slider class="humidity" min="[[stateObj.attributes.min_humidity]]" max="[[stateObj.attributes.max_humidity]]" secondary-progress="[[stateObj.attributes.max_humidity]]" step="1" pin="" value="[[stateObj.attributes.humidity]]" on-change="targetHumiditySliderChanged" ignore-bar-touch="">
|
||||
<div class="target-humidity">
|
||||
[[stateObj.attributes.humidity]] %
|
||||
</div>
|
||||
<ha-paper-slider
|
||||
class="humidity"
|
||||
min="[[stateObj.attributes.min_humidity]]"
|
||||
max="[[stateObj.attributes.max_humidity]]"
|
||||
secondary-progress="[[stateObj.attributes.max_humidity]]"
|
||||
step="1"
|
||||
pin=""
|
||||
value="[[stateObj.attributes.humidity]]"
|
||||
on-change="targetHumiditySliderChanged"
|
||||
ignore-bar-touch=""
|
||||
>
|
||||
</ha-paper-slider>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsOperationMode(stateObj)]]">
|
||||
<div class="container-operation_list">
|
||||
<div class="controls">
|
||||
<paper-dropdown-menu label-float="" dynamic-align="" label="[[localize('ui.card.climate.operation')]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{operationIndex}}">
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.operation_list]]" on-dom-change="handleOperationListUpdate">
|
||||
<paper-item>[[_localizeOperationMode(localize, item)]]</paper-item>
|
||||
<template is="dom-if" if="[[supportsOperationMode(stateObj)]]">
|
||||
<div class="container-operation_list">
|
||||
<div class="controls">
|
||||
<paper-dropdown-menu
|
||||
label-float=""
|
||||
dynamic-align=""
|
||||
label="[[localize('ui.card.climate.operation')]]"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{operationIndex}}"
|
||||
>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[stateObj.attributes.operation_list]]"
|
||||
on-dom-change="handleOperationListUpdate"
|
||||
>
|
||||
<paper-item
|
||||
>[[_localizeOperationMode(localize, item)]]</paper-item
|
||||
>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsFanMode(stateObj)]]">
|
||||
<div class="container-fan_list">
|
||||
<paper-dropdown-menu
|
||||
label-float=""
|
||||
dynamic-align=""
|
||||
label="[[localize('ui.card.climate.fan_mode')]]"
|
||||
>
|
||||
<paper-listbox slot="dropdown-content" selected="{{fanIndex}}">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[stateObj.attributes.fan_list]]"
|
||||
on-dom-change="handleFanListUpdate"
|
||||
>
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsFanMode(stateObj)]]">
|
||||
<div class="container-fan_list">
|
||||
<paper-dropdown-menu label-float="" dynamic-align="" label="[[localize('ui.card.climate.fan_mode')]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{fanIndex}}">
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.fan_list]]" on-dom-change="handleFanListUpdate">
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsSwingMode(stateObj)]]">
|
||||
<div class="container-swing_list">
|
||||
<paper-dropdown-menu label-float="" dynamic-align="" label="[[localize('ui.card.climate.swing_mode')]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{swingIndex}}">
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.swing_list]]" on-dom-change="handleSwingListUpdate">
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsAwayMode(stateObj)]]">
|
||||
<div class="container-away_mode">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.climate.away_mode')]]</div>
|
||||
<paper-toggle-button checked="[[awayToggleChecked]]" on-change="awayToggleChanged">
|
||||
</paper-toggle-button>
|
||||
<template is="dom-if" if="[[supportsSwingMode(stateObj)]]">
|
||||
<div class="container-swing_list">
|
||||
<paper-dropdown-menu
|
||||
label-float=""
|
||||
dynamic-align=""
|
||||
label="[[localize('ui.card.climate.swing_mode')]]"
|
||||
>
|
||||
<paper-listbox slot="dropdown-content" selected="{{swingIndex}}">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[stateObj.attributes.swing_list]]"
|
||||
on-dom-change="handleSwingListUpdate"
|
||||
>
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsAuxHeat(stateObj)]]">
|
||||
<div class="container-aux_heat">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.climate.aux_heat')]]</div>
|
||||
<paper-toggle-button checked="[[auxToggleChecked]]" on-change="auxToggleChanged">
|
||||
</paper-toggle-button>
|
||||
<template is="dom-if" if="[[supportsAwayMode(stateObj)]]">
|
||||
<div class="container-away_mode">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.climate.away_mode')]]</div>
|
||||
<paper-toggle-button
|
||||
checked="[[awayToggleChecked]]"
|
||||
on-change="awayToggleChanged"
|
||||
>
|
||||
</paper-toggle-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsAuxHeat(stateObj)]]">
|
||||
<div class="container-aux_heat">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.climate.aux_heat')]]</div>
|
||||
<paper-toggle-button
|
||||
checked="[[auxToggleChecked]]"
|
||||
on-change="auxToggleChanged"
|
||||
>
|
||||
</paper-toggle-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,67 +11,80 @@ import "../../../components/ha-markdown";
|
||||
class MoreInfoConfigurator extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
p > img {
|
||||
max-width: 100%;
|
||||
}
|
||||
p > img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
p.center {
|
||||
text-align: center;
|
||||
}
|
||||
p.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
p.error {
|
||||
color: #C62828;
|
||||
}
|
||||
p.error {
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
p.submit {
|
||||
text-align: center;
|
||||
height: 41px;
|
||||
}
|
||||
p.submit {
|
||||
text-align: center;
|
||||
height: 41px;
|
||||
}
|
||||
|
||||
paper-spinner {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
paper-spinner {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layout vertical">
|
||||
<template is="dom-if" if="[[isConfigurable]]">
|
||||
<ha-markdown content="[[stateObj.attributes.description]]"></ha-markdown>
|
||||
<div class="layout vertical">
|
||||
<template is="dom-if" if="[[isConfigurable]]">
|
||||
<ha-markdown
|
||||
content="[[stateObj.attributes.description]]"
|
||||
></ha-markdown>
|
||||
|
||||
<p class="error" hidden$="[[!stateObj.attributes.errors]]">
|
||||
[[stateObj.attributes.errors]]
|
||||
</p>
|
||||
<p class="error" hidden$="[[!stateObj.attributes.errors]]">
|
||||
[[stateObj.attributes.errors]]
|
||||
</p>
|
||||
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.fields]]">
|
||||
<paper-input label="[[item.name]]" name="[[item.id]]" type="[[item.type]]" on-change="fieldChanged"></paper-input>
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.fields]]">
|
||||
<paper-input
|
||||
label="[[item.name]]"
|
||||
name="[[item.id]]"
|
||||
type="[[item.type]]"
|
||||
on-change="fieldChanged"
|
||||
></paper-input>
|
||||
</template>
|
||||
|
||||
<p class="submit" hidden$="[[!stateObj.attributes.submit_caption]]">
|
||||
<paper-button
|
||||
raised=""
|
||||
disabled="[[isConfiguring]]"
|
||||
on-click="submitClicked"
|
||||
>
|
||||
<paper-spinner
|
||||
active="[[isConfiguring]]"
|
||||
hidden="[[!isConfiguring]]"
|
||||
alt="Configuring"
|
||||
></paper-spinner>
|
||||
[[stateObj.attributes.submit_caption]]
|
||||
</paper-button>
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<p class="submit" hidden$="[[!stateObj.attributes.submit_caption]]">
|
||||
<paper-button raised="" disabled="[[isConfiguring]]" on-click="submitClicked">
|
||||
<paper-spinner active="[[isConfiguring]]" hidden="[[!isConfiguring]]" alt="Configuring"></paper-spinner>
|
||||
[[stateObj.attributes.submit_caption]]
|
||||
</paper-button>
|
||||
|
||||
</p>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,52 +18,54 @@ const FEATURE_CLASS_NAMES = {
|
||||
class MoreInfoCover extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
.current_position, .tilt {
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
.current_position,
|
||||
.tilt {
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.has-current_position .current_position,
|
||||
.has-set_tilt_position .tilt,
|
||||
.has-current_tilt_position .tilt
|
||||
{
|
||||
max-height: 208px;
|
||||
}
|
||||
.has-current_position .current_position,
|
||||
.has-set_tilt_position .tilt,
|
||||
.has-current_tilt_position .tilt {
|
||||
max-height: 208px;
|
||||
}
|
||||
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
[invisible] {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
</style>
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="current_position">
|
||||
<ha-labeled-slider
|
||||
caption="[[localize('ui.card.cover.position')]]"
|
||||
pin=""
|
||||
value="{{coverPositionSliderValue}}"
|
||||
disabled="[[!entityObj.supportsSetPosition]]"
|
||||
on-change="coverPositionSliderChanged"
|
||||
></ha-labeled-slider>
|
||||
</div>
|
||||
|
||||
<div class="current_position">
|
||||
<ha-labeled-slider
|
||||
caption="[[localize('ui.card.cover.position')]]" pin=""
|
||||
value="{{coverPositionSliderValue}}"
|
||||
disabled="[[!entityObj.supportsSetPosition]]"
|
||||
on-change="coverPositionSliderChanged"
|
||||
></ha-labeled-slider>
|
||||
</div>
|
||||
|
||||
<div class="tilt">
|
||||
<ha-labeled-slider
|
||||
caption="[[localize('ui.card.cover.tilt_position')]]" pin="" extra=""
|
||||
value="{{coverTiltPositionSliderValue}}"
|
||||
disabled="[[!entityObj.supportsSetTiltPosition]]"
|
||||
on-change="coverTiltPositionSliderChanged">
|
||||
|
||||
<ha-cover-tilt-controls
|
||||
slot="extra" hidden$="[[entityObj.isTiltOnly]]"
|
||||
hass="[[hass]]" state-obj="[[stateObj]]"
|
||||
></ha-cover-tilt-controls>
|
||||
|
||||
</ha-labeled-slider>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
<div class="tilt">
|
||||
<ha-labeled-slider
|
||||
caption="[[localize('ui.card.cover.tilt_position')]]"
|
||||
pin=""
|
||||
extra=""
|
||||
value="{{coverTiltPositionSliderValue}}"
|
||||
disabled="[[!entityObj.supportsSetTiltPosition]]"
|
||||
on-change="coverTiltPositionSliderChanged"
|
||||
>
|
||||
<ha-cover-tilt-controls
|
||||
slot="extra"
|
||||
hidden$="[[entityObj.isTiltOnly]]"
|
||||
hass="[[hass]]"
|
||||
state-obj="[[stateObj]]"
|
||||
></ha-cover-tilt-controls>
|
||||
</ha-labeled-slider>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,8 +6,8 @@ import "../../../components/ha-attributes";
|
||||
class MoreInfoDefault extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<ha-attributes state-obj="[[stateObj]]"></ha-attributes>
|
||||
`;
|
||||
<ha-attributes state-obj="[[stateObj]]"></ha-attributes>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -19,60 +19,82 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class MoreInfoFan extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
.container-speed_list,
|
||||
.container-direction,
|
||||
.container-oscillating {
|
||||
display: none;
|
||||
}
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
.container-speed_list,
|
||||
.container-direction,
|
||||
.container-oscillating {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.has-speed_list .container-speed_list,
|
||||
.has-direction .container-direction,
|
||||
.has-oscillating .container-oscillating {
|
||||
display: block;
|
||||
}
|
||||
.has-speed_list .container-speed_list,
|
||||
.has-direction .container-direction,
|
||||
.has-oscillating .container-oscillating {
|
||||
display: block;
|
||||
}
|
||||
|
||||
paper-dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
paper-dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="container-speed_list">
|
||||
<paper-dropdown-menu
|
||||
label-float=""
|
||||
dynamic-align=""
|
||||
label="[[localize('ui.card.fan.speed')]]"
|
||||
>
|
||||
<paper-listbox slot="dropdown-content" selected="{{speedIndex}}">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[stateObj.attributes.speed_list]]"
|
||||
>
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
<div class="container-speed_list">
|
||||
<paper-dropdown-menu label-float="" dynamic-align="" label="[[localize('ui.card.fan.speed')]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{speedIndex}}">
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.speed_list]]">
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<div class="container-oscillating">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.fan.oscillate')]]</div>
|
||||
<paper-toggle-button
|
||||
checked="[[oscillationToggleChecked]]"
|
||||
on-change="oscillationToggleChanged"
|
||||
>
|
||||
</paper-toggle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-oscillating">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.fan.oscillate')]]</div>
|
||||
<paper-toggle-button checked="[[oscillationToggleChecked]]" on-change="oscillationToggleChanged">
|
||||
</paper-toggle-button>
|
||||
<div class="container-direction">
|
||||
<div class="direction">
|
||||
<div>[[localize('ui.card.fan.direction')]]</div>
|
||||
<paper-icon-button
|
||||
icon="hass:rotate-left"
|
||||
on-click="onDirectionLeft"
|
||||
title="Left"
|
||||
disabled="[[computeIsRotatingLeft(stateObj)]]"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:rotate-right"
|
||||
on-click="onDirectionRight"
|
||||
title="Right"
|
||||
disabled="[[computeIsRotatingRight(stateObj)]]"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-direction">
|
||||
<div class="direction">
|
||||
<div>[[localize('ui.card.fan.direction')]]</div>
|
||||
<paper-icon-button icon="hass:rotate-left" on-click="onDirectionLeft" title="Left" disabled="[[computeIsRotatingLeft(stateObj)]]"></paper-icon-button>
|
||||
<paper-icon-button icon="hass:rotate-right" on-click="onDirectionRight" title="Right" disabled="[[computeIsRotatingRight(stateObj)]]"></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ha-attributes state-obj="[[stateObj]]" extra-filters="speed,speed_list,oscillating,direction"></ha-attributes>
|
||||
`;
|
||||
<ha-attributes
|
||||
state-obj="[[stateObj]]"
|
||||
extra-filters="speed,speed_list,oscillating,direction"
|
||||
></ha-attributes>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,23 +10,26 @@ import dynamicContentUpdater from "../../../common/dom/dynamic_content_updater";
|
||||
class MoreInfoGroup extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.child-card {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
<style>
|
||||
.child-card {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.child-card:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
.child-card:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="groupedControlDetails"></div>
|
||||
<template is="dom-repeat" items="[[states]]" as="state">
|
||||
<div class="child-card">
|
||||
<state-card-content state-obj="[[state]]" hass="[[hass]]"></state-card-content>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
<div id="groupedControlDetails"></div>
|
||||
<template is="dom-repeat" items="[[states]]" as="state">
|
||||
<div class="child-card">
|
||||
<state-card-content
|
||||
state-obj="[[state]]"
|
||||
hass="[[hass]]"
|
||||
></state-card-content>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,16 +7,20 @@ import "../../../components/ha-attributes";
|
||||
class MoreInfoHistoryGraph extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
<ha-history_graph-card hass="[[hass]]" state-obj="[[stateObj]]" in-dialog="">
|
||||
<ha-attributes state-obj="[[stateObj]]"></ha-attributes>
|
||||
</ha-history_graph-card>
|
||||
`;
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
</style>
|
||||
<ha-history_graph-card
|
||||
hass="[[hass]]"
|
||||
state-obj="[[stateObj]]"
|
||||
in-dialog=""
|
||||
>
|
||||
<ha-attributes state-obj="[[stateObj]]"></ha-attributes>
|
||||
</ha-history_graph-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -13,19 +13,28 @@ import attributeClassNames from "../../../common/entity/attribute_class_names";
|
||||
class DatetimeInput extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<template is="dom-if" if="[[doesHaveDate(stateObj)]]" restamp="">
|
||||
<div>
|
||||
<vaadin-date-picker id="dateInput" on-value-changed="dateTimeChanged" label="Date" value="{{selectedDate}}"></vaadin-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[doesHaveTime(stateObj)]]" restamp="">
|
||||
<div>
|
||||
<paper-time-input hour="{{selectedHour}}" min="{{selectedMinute}}" format="24"></paper-time-input>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<template is="dom-if" if="[[doesHaveDate(stateObj)]]" restamp="">
|
||||
<div>
|
||||
<vaadin-date-picker
|
||||
id="dateInput"
|
||||
on-value-changed="dateTimeChanged"
|
||||
label="Date"
|
||||
value="{{selectedDate}}"
|
||||
></vaadin-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[doesHaveTime(stateObj)]]" restamp="">
|
||||
<div>
|
||||
<paper-time-input
|
||||
hour="{{selectedHour}}"
|
||||
min="{{selectedMinute}}"
|
||||
format="24"
|
||||
></paper-time-input>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
|
||||
@ -26,99 +26,140 @@ const FEATURE_CLASS_NAMES = {
|
||||
class MoreInfoLight extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
.effect_list,
|
||||
.brightness,
|
||||
.color_temp,
|
||||
.white_value {
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.5s ease-in;
|
||||
}
|
||||
|
||||
.effect_list, .brightness, .color_temp, .white_value {
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height .5s ease-in;
|
||||
}
|
||||
.color_temp {
|
||||
--ha-slider-background: -webkit-linear-gradient(
|
||||
right,
|
||||
rgb(255, 160, 0) 0%,
|
||||
white 50%,
|
||||
rgb(166, 209, 255) 100%
|
||||
);
|
||||
/* The color temp minimum value shouldn't be rendered differently. It's not "off". */
|
||||
--paper-slider-knob-start-border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.color_temp {
|
||||
--ha-slider-background: -webkit-linear-gradient(right, rgb(255, 160, 0) 0%, white 50%, rgb(166, 209, 255) 100%);
|
||||
/* The color temp minimum value shouldn't be rendered differently. It's not "off". */
|
||||
--paper-slider-knob-start-border-color: var(--primary-color);
|
||||
}
|
||||
ha-color-picker {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
ha-color-picker {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.5s ease-in;
|
||||
}
|
||||
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height .5s ease-in;
|
||||
}
|
||||
.has-effect_list.is-on .effect_list,
|
||||
.has-brightness .brightness,
|
||||
.has-color_temp.is-on .color_temp,
|
||||
.has-white_value.is-on .white_value {
|
||||
max-height: 84px;
|
||||
}
|
||||
|
||||
.has-effect_list.is-on .effect_list,
|
||||
.has-brightness .brightness,
|
||||
.has-color_temp.is-on .color_temp,
|
||||
.has-white_value.is-on .white_value {
|
||||
max-height: 84px;
|
||||
}
|
||||
.has-brightness .has-color_temp.is-on,
|
||||
.has-white_value.is-on {
|
||||
margin-top: -16px;
|
||||
}
|
||||
|
||||
.has-brightness
|
||||
.has-color_temp.is-on,
|
||||
.has-white_value.is-on {
|
||||
margin-top: -16px;
|
||||
}
|
||||
.has-brightness .brightness,
|
||||
.has-color_temp.is-on .color_temp,
|
||||
.has-white_value.is-on .white_value {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.has-brightness .brightness,
|
||||
.has-color_temp.is-on .color_temp,
|
||||
.has-white_value.is-on .white_value {
|
||||
padding-top: 16px;
|
||||
}
|
||||
.has-color.is-on ha-color-picker {
|
||||
max-height: 500px;
|
||||
overflow: visible;
|
||||
--ha-color-picker-wheel-borderwidth: 5;
|
||||
--ha-color-picker-wheel-bordercolor: white;
|
||||
--ha-color-picker-wheel-shadow: none;
|
||||
--ha-color-picker-marker-borderwidth: 2;
|
||||
--ha-color-picker-marker-bordercolor: white;
|
||||
}
|
||||
|
||||
.has-color.is-on ha-color-picker {
|
||||
max-height: 500px;
|
||||
overflow: visible;
|
||||
--ha-color-picker-wheel-borderwidth: 5;
|
||||
--ha-color-picker-wheel-bordercolor: white;
|
||||
--ha-color-picker-wheel-shadow: none;
|
||||
--ha-color-picker-marker-borderwidth: 2;
|
||||
--ha-color-picker-marker-bordercolor: white;
|
||||
}
|
||||
.is-unavailable .control {
|
||||
max-height: 0px;
|
||||
}
|
||||
|
||||
.is-unavailable .control {
|
||||
max-height: 0px;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="control brightness">
|
||||
<ha-labeled-slider
|
||||
caption="[[localize('ui.card.light.brightness')]]"
|
||||
icon="hass:brightness-5"
|
||||
min="1"
|
||||
max="255"
|
||||
value="{{brightnessSliderValue}}"
|
||||
on-change="brightnessSliderChanged"
|
||||
></ha-labeled-slider>
|
||||
</div>
|
||||
|
||||
</style>
|
||||
<div class="control color_temp">
|
||||
<ha-labeled-slider
|
||||
caption="[[localize('ui.card.light.color_temperature')]]"
|
||||
icon="hass:thermometer"
|
||||
min="[[stateObj.attributes.min_mireds]]"
|
||||
max="[[stateObj.attributes.max_mireds]]"
|
||||
value="{{ctSliderValue}}"
|
||||
on-change="ctSliderChanged"
|
||||
></ha-labeled-slider>
|
||||
</div>
|
||||
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="control white_value">
|
||||
<ha-labeled-slider
|
||||
caption="[[localize('ui.card.light.white_value')]]"
|
||||
icon="hass:file-word-box"
|
||||
max="255"
|
||||
value="{{wvSliderValue}}"
|
||||
on-change="wvSliderChanged"
|
||||
></ha-labeled-slider>
|
||||
</div>
|
||||
|
||||
<div class="control brightness">
|
||||
<ha-labeled-slider caption="[[localize('ui.card.light.brightness')]]" icon="hass:brightness-5" min="1" max="255" value="{{brightnessSliderValue}}" on-change="brightnessSliderChanged"></ha-labeled-slider>
|
||||
</div>
|
||||
<ha-color-picker
|
||||
class="control color"
|
||||
on-colorselected="colorPicked"
|
||||
desired-hs-color="{{colorPickerColor}}"
|
||||
throttle="500"
|
||||
hue-segments="24"
|
||||
saturation-segments="8"
|
||||
>
|
||||
</ha-color-picker>
|
||||
|
||||
<div class="control color_temp">
|
||||
<ha-labeled-slider caption="[[localize('ui.card.light.color_temperature')]]" icon="hass:thermometer" min="[[stateObj.attributes.min_mireds]]" max="[[stateObj.attributes.max_mireds]]" value="{{ctSliderValue}}" on-change="ctSliderChanged"></ha-labeled-slider>
|
||||
</div>
|
||||
<div class="control effect_list">
|
||||
<paper-dropdown-menu
|
||||
label-float=""
|
||||
dynamic-align=""
|
||||
label="[[localize('ui.card.light.effect')]]"
|
||||
>
|
||||
<paper-listbox slot="dropdown-content" selected="{{effectIndex}}">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[stateObj.attributes.effect_list]]"
|
||||
>
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
<div class="control white_value">
|
||||
<ha-labeled-slider caption="[[localize('ui.card.light.white_value')]]" icon="hass:file-word-box" max="255" value="{{wvSliderValue}}" on-change="wvSliderChanged"></ha-labeled-slider>
|
||||
</div>
|
||||
|
||||
<ha-color-picker class="control color" on-colorselected="colorPicked" desired-hs-color="{{colorPickerColor}}" throttle="500" hue-segments="24" saturation-segments="8">
|
||||
</ha-color-picker>
|
||||
|
||||
<div class="control effect_list">
|
||||
<paper-dropdown-menu label-float="" dynamic-align="" label="[[localize('ui.card.light.effect')]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{effectIndex}}">
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.effect_list]]">
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
<ha-attributes state-obj="[[stateObj]]" extra-filters="brightness,color_temp,white_value,effect_list,effect,hs_color,rgb_color,xy_color,min_mireds,max_mireds"></ha-attributes>
|
||||
</div>
|
||||
`;
|
||||
<ha-attributes
|
||||
state-obj="[[stateObj]]"
|
||||
extra-filters="brightness,color_temp,white_value,effect_list,effect,hs_color,rgb_color,xy_color,min_mireds,max_mireds"
|
||||
></ha-attributes>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -20,11 +20,29 @@ class MoreInfoLock extends LocalizeMixin(PolymerElement) {
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[stateObj.attributes.code_format]]">
|
||||
<paper-input label="[[localize('ui.card.lock.code')]]" value="{{enteredCode}}" pattern="[[stateObj.attributes.code_format]]" type="password"></paper-input>
|
||||
<paper-button on-click="callService" data-service="unlock" hidden$="[[!isLocked]]">[[localize('ui.card.lock.unlock')]]</paper-button>
|
||||
<paper-button on-click="callService" data-service="lock" hidden$="[[isLocked]]">[[localize('ui.card.lock.lock')]]</paper-button>
|
||||
<paper-input
|
||||
label="[[localize('ui.card.lock.code')]]"
|
||||
value="{{enteredCode}}"
|
||||
pattern="[[stateObj.attributes.code_format]]"
|
||||
type="password"
|
||||
></paper-input>
|
||||
<paper-button
|
||||
on-click="callService"
|
||||
data-service="unlock"
|
||||
hidden$="[[!isLocked]]"
|
||||
>[[localize('ui.card.lock.unlock')]]</paper-button
|
||||
>
|
||||
<paper-button
|
||||
on-click="callService"
|
||||
data-service="lock"
|
||||
hidden$="[[isLocked]]"
|
||||
>[[localize('ui.card.lock.lock')]]</paper-button
|
||||
>
|
||||
</template>
|
||||
<ha-attributes state-obj="[[stateObj]]" extra-filters="code_format"></ha-attributes>
|
||||
<ha-attributes
|
||||
state-obj="[[stateObj]]"
|
||||
extra-filters="code_format"
|
||||
></ha-attributes>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -22,101 +22,184 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class MoreInfoMediaPlayer extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
.media-state {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
.media-state {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
paper-icon-button[highlight] {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
paper-icon-button[highlight] {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.volume {
|
||||
margin-bottom: 8px;
|
||||
.volume {
|
||||
margin-bottom: 8px;
|
||||
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height .5s ease-in;
|
||||
}
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.5s ease-in;
|
||||
}
|
||||
|
||||
.has-volume_level .volume {
|
||||
max-height: 40px;
|
||||
}
|
||||
.has-volume_level .volume {
|
||||
max-height: 40px;
|
||||
}
|
||||
|
||||
iron-icon.source-input {
|
||||
padding: 7px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
iron-icon.source-input {
|
||||
padding: 7px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
paper-dropdown-menu.source-input {
|
||||
margin-left: 10px;
|
||||
}
|
||||
paper-dropdown-menu.source-input {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="layout horizontal">
|
||||
<div class="flex">
|
||||
<paper-icon-button icon="hass:power" highlight$="[[playerObj.isOff]]" on-click="handleTogglePower" hidden$="[[computeHidePowerButton(playerObj)]]"></paper-icon-button>
|
||||
</div>
|
||||
<div>
|
||||
<template is="dom-if" if="[[computeShowPlaybackControls(playerObj)]]">
|
||||
<paper-icon-button icon="hass:skip-previous" on-click="handlePrevious" hidden$="[[!playerObj.supportsPreviousTrack]]"></paper-icon-button>
|
||||
<paper-icon-button icon="[[computePlaybackControlIcon(playerObj)]]" on-click="handlePlaybackControl" hidden$="[[!computePlaybackControlIcon(playerObj)]]" highlight=""></paper-icon-button>
|
||||
<paper-icon-button icon="hass:skip-next" on-click="handleNext" hidden$="[[!playerObj.supportsNextTrack]]"></paper-icon-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- VOLUME -->
|
||||
<div class="volume_buttons center horizontal layout" hidden$="[[computeHideVolumeButtons(playerObj)]]">
|
||||
<paper-icon-button on-click="handleVolumeTap" icon="hass:volume-off"></paper-icon-button>
|
||||
<paper-icon-button id="volumeDown" disabled$="[[playerObj.isMuted]]" on-mousedown="handleVolumeDown" on-touchstart="handleVolumeDown" icon="hass:volume-medium"></paper-icon-button>
|
||||
<paper-icon-button id="volumeUp" disabled$="[[playerObj.isMuted]]" on-mousedown="handleVolumeUp" on-touchstart="handleVolumeUp" icon="hass:volume-high"></paper-icon-button>
|
||||
</div>
|
||||
<div class="volume center horizontal layout" hidden$="[[!playerObj.supportsVolumeSet]]">
|
||||
<paper-icon-button on-click="handleVolumeTap" hidden$="[[playerObj.supportsVolumeButtons]]" icon="[[computeMuteVolumeIcon(playerObj)]]"></paper-icon-button>
|
||||
<ha-paper-slider disabled$="[[playerObj.isMuted]]" min="0" max="100" value="[[playerObj.volumeSliderValue]]" on-change="volumeSliderChanged" class="flex" ignore-bar-touch="">
|
||||
</ha-paper-slider>
|
||||
</div>
|
||||
<!-- SOURCE PICKER -->
|
||||
<div class="controls layout horizontal justified" hidden$="[[computeHideSelectSource(playerObj)]]">
|
||||
<iron-icon class="source-input" icon="hass:login-variant"></iron-icon>
|
||||
<paper-dropdown-menu class="flex source-input" dynamic-align="" label-float="" label="[[localize('ui.card.media_player.source')]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{sourceIndex}}">
|
||||
<template is="dom-repeat" items="[[playerObj.sourceList]]">
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<!-- SOUND MODE PICKER -->
|
||||
<template is='dom-if' if='[[!computeHideSelectSoundMode(playerObj)]]'>
|
||||
<div class="controls layout horizontal justified">
|
||||
<iron-icon class="source-input" icon="hass:music-note"></iron-icon>
|
||||
<paper-dropdown-menu class="flex source-input" dynamic-align label-float label="[[localize('ui.card.media_player.sound_mode')]]">
|
||||
<paper-listbox slot="dropdown-content" attr-for-selected="item-name" selected="{{SoundModeInput}}">
|
||||
<template is='dom-repeat' items='[[playerObj.soundModeList]]'>
|
||||
<paper-item item-name$="[[item]]">[[item]]</paper-item>
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="layout horizontal">
|
||||
<div class="flex">
|
||||
<paper-icon-button
|
||||
icon="hass:power"
|
||||
highlight$="[[playerObj.isOff]]"
|
||||
on-click="handleTogglePower"
|
||||
hidden$="[[computeHidePowerButton(playerObj)]]"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[computeShowPlaybackControls(playerObj)]]"
|
||||
>
|
||||
<paper-icon-button
|
||||
icon="hass:skip-previous"
|
||||
on-click="handlePrevious"
|
||||
hidden$="[[!playerObj.supportsPreviousTrack]]"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="[[computePlaybackControlIcon(playerObj)]]"
|
||||
on-click="handlePlaybackControl"
|
||||
hidden$="[[!computePlaybackControlIcon(playerObj)]]"
|
||||
highlight=""
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
icon="hass:skip-next"
|
||||
on-click="handleNext"
|
||||
hidden$="[[!playerObj.supportsNextTrack]]"
|
||||
></paper-icon-button>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</div>
|
||||
<!-- VOLUME -->
|
||||
<div
|
||||
class="volume_buttons center horizontal layout"
|
||||
hidden$="[[computeHideVolumeButtons(playerObj)]]"
|
||||
>
|
||||
<paper-icon-button
|
||||
on-click="handleVolumeTap"
|
||||
icon="hass:volume-off"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
id="volumeDown"
|
||||
disabled$="[[playerObj.isMuted]]"
|
||||
on-mousedown="handleVolumeDown"
|
||||
on-touchstart="handleVolumeDown"
|
||||
icon="hass:volume-medium"
|
||||
></paper-icon-button>
|
||||
<paper-icon-button
|
||||
id="volumeUp"
|
||||
disabled$="[[playerObj.isMuted]]"
|
||||
on-mousedown="handleVolumeUp"
|
||||
on-touchstart="handleVolumeUp"
|
||||
icon="hass:volume-high"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div
|
||||
class="volume center horizontal layout"
|
||||
hidden$="[[!playerObj.supportsVolumeSet]]"
|
||||
>
|
||||
<paper-icon-button
|
||||
on-click="handleVolumeTap"
|
||||
hidden$="[[playerObj.supportsVolumeButtons]]"
|
||||
icon="[[computeMuteVolumeIcon(playerObj)]]"
|
||||
></paper-icon-button>
|
||||
<ha-paper-slider
|
||||
disabled$="[[playerObj.isMuted]]"
|
||||
min="0"
|
||||
max="100"
|
||||
value="[[playerObj.volumeSliderValue]]"
|
||||
on-change="volumeSliderChanged"
|
||||
class="flex"
|
||||
ignore-bar-touch=""
|
||||
>
|
||||
</ha-paper-slider>
|
||||
</div>
|
||||
<!-- SOURCE PICKER -->
|
||||
<div
|
||||
class="controls layout horizontal justified"
|
||||
hidden$="[[computeHideSelectSource(playerObj)]]"
|
||||
>
|
||||
<iron-icon class="source-input" icon="hass:login-variant"></iron-icon>
|
||||
<paper-dropdown-menu
|
||||
class="flex source-input"
|
||||
dynamic-align=""
|
||||
label-float=""
|
||||
label="[[localize('ui.card.media_player.source')]]"
|
||||
>
|
||||
<paper-listbox slot="dropdown-content" selected="{{sourceIndex}}">
|
||||
<template is="dom-repeat" items="[[playerObj.sourceList]]">
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<!-- SOUND MODE PICKER -->
|
||||
<template is="dom-if" if="[[!computeHideSelectSoundMode(playerObj)]]">
|
||||
<div class="controls layout horizontal justified">
|
||||
<iron-icon class="source-input" icon="hass:music-note"></iron-icon>
|
||||
<paper-dropdown-menu
|
||||
class="flex source-input"
|
||||
dynamic-align
|
||||
label-float
|
||||
label="[[localize('ui.card.media_player.sound_mode')]]"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
attr-for-selected="item-name"
|
||||
selected="{{SoundModeInput}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[playerObj.soundModeList]]">
|
||||
<paper-item item-name$="[[item]]">[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
<!-- TTS -->
|
||||
<div
|
||||
hidden$="[[computeHideTTS(ttsLoaded, playerObj)]]"
|
||||
class="layout horizontal end"
|
||||
>
|
||||
<paper-input
|
||||
id="ttsInput"
|
||||
label="[[localize('ui.card.media_player.text_to_speak')]]"
|
||||
class="flex"
|
||||
value="{{ttsMessage}}"
|
||||
on-keydown="ttsCheckForEnter"
|
||||
></paper-input>
|
||||
<paper-icon-button
|
||||
icon="hass:send"
|
||||
on-click="sendTTS"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- TTS -->
|
||||
<div hidden$="[[computeHideTTS(ttsLoaded, playerObj)]]" class="layout horizontal end">
|
||||
<paper-input id="ttsInput" label="[[localize('ui.card.media_player.text_to_speak')]]" class="flex" value="{{ttsMessage}}" on-keydown="ttsCheckForEnter"></paper-input>
|
||||
<paper-icon-button icon="hass:send" on-click="sendTTS"></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -5,15 +5,15 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class MoreInfoScript extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
|
||||
<div class="layout vertical">
|
||||
<div class="data-entry layout justified horizontal">
|
||||
<div class="key">Last Action</div>
|
||||
<div class="value">[[stateObj.attributes.last_action]]</div>
|
||||
<div class="layout vertical">
|
||||
<div class="data-entry layout justified horizontal">
|
||||
<div class="key">Last Action</div>
|
||||
<div class="value">[[stateObj.attributes.last_action]]</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,22 +10,28 @@ import formatTime from "../../../common/datetime/format_time";
|
||||
class MoreInfoSun extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
|
||||
<template is="dom-repeat" items="[[computeOrder(risingDate, settingDate)]]">
|
||||
<div class="data-entry layout justified horizontal">
|
||||
<div class="key">
|
||||
<span>[[itemCaption(item)]]</span>
|
||||
<ha-relative-time hass="[[hass]]" datetime-obj="[[itemDate(item)]]"></ha-relative-time>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[computeOrder(risingDate, settingDate)]]"
|
||||
>
|
||||
<div class="data-entry layout justified horizontal">
|
||||
<div class="key">
|
||||
<span>[[itemCaption(item)]]</span>
|
||||
<ha-relative-time
|
||||
hass="[[hass]]"
|
||||
datetime-obj="[[itemDate(item)]]"
|
||||
></ha-relative-time>
|
||||
</div>
|
||||
<div class="value">[[itemValue(item)]]</div>
|
||||
</div>
|
||||
<div class="value">[[itemValue(item)]]</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<div class="data-entry layout justified horizontal">
|
||||
<div class="key">Elevation</div>
|
||||
<div class="value">[[stateObj.attributes.elevation]]</div>
|
||||
</div>
|
||||
`;
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -4,16 +4,21 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class MoreInfoUpdater extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.link {
|
||||
color: #03A9F4;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.link {
|
||||
color: #03a9f4;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>
|
||||
<a class="link" href="https://www.home-assistant.io/docs/installation/updating/" target="_blank">Update Instructions</a>
|
||||
</div>
|
||||
`;
|
||||
<div>
|
||||
<a
|
||||
class="link"
|
||||
href="https://www.home-assistant.io/docs/installation/updating/"
|
||||
target="_blank"
|
||||
>Update Instructions</a
|
||||
>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,81 +12,127 @@ import "../../../components/ha-attributes";
|
||||
class MoreInfoVacuum extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
:host {
|
||||
@apply --paper-font-body1;
|
||||
line-height: 1.5;
|
||||
}
|
||||
<style include="iron-flex iron-flex-alignment"></style>
|
||||
<style>
|
||||
:host {
|
||||
@apply --paper-font-body1;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.status-subtitle {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.status-subtitle {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
</style>
|
||||
|
||||
<div class="horizontal justified layout">
|
||||
<div hidden$="[[!supportsStatus(stateObj)]]">
|
||||
<span class="status-subtitle">Status: </span><span><strong>[[stateObj.attributes.status]]</strong></span>
|
||||
</div>
|
||||
<div hidden$="[[!supportsBattery(stateObj)]]">
|
||||
<span><iron-icon icon="[[stateObj.attributes.battery_icon]]"></iron-icon> [[stateObj.attributes.battery_level]] %</span>
|
||||
</div>
|
||||
</div>
|
||||
<div hidden$="[[!supportsCommandBar(stateObj)]]">
|
||||
<p></p>
|
||||
<div class="status-subtitle">Vacuum cleaner commands:</div>
|
||||
<div class="horizontal justified layout">
|
||||
<template is="dom-if" if="[[supportsStart(stateObj)]]">
|
||||
<div>
|
||||
<paper-icon-button icon="hass:play" on-click="onStart" title="Start"></paper-icon-button>
|
||||
</div>
|
||||
<div hidden$="[[!supportsPause(stateObj)]]">
|
||||
<paper-icon-button icon="hass:pause" on-click="onPause" title="Pause"></paper-icon-button>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!supportsStart(stateObj)]]">
|
||||
<div hidden$="[[!supportsPause(stateObj)]]">
|
||||
<paper-icon-button icon="hass:play-pause" on-click="onPlayPause" title="Pause"></paper-icon-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div hidden$="[[!supportsStop(stateObj)]]">
|
||||
<paper-icon-button icon="hass:stop" on-click="onStop" title="Stop"></paper-icon-button>
|
||||
<div hidden$="[[!supportsStatus(stateObj)]]">
|
||||
<span class="status-subtitle">Status: </span
|
||||
><span><strong>[[stateObj.attributes.status]]</strong></span>
|
||||
</div>
|
||||
<div hidden$="[[!supportsCleanSpot(stateObj)]]">
|
||||
<paper-icon-button icon="hass:broom" on-click="onCleanSpot" title="Clean spot"></paper-icon-button>
|
||||
</div>
|
||||
<div hidden$="[[!supportsLocate(stateObj)]]">
|
||||
<paper-icon-button icon="hass:map-marker" on-click="onLocate" title="Locate"></paper-icon-button>
|
||||
</div>
|
||||
<div hidden$="[[!supportsReturnHome(stateObj)]]">
|
||||
<paper-icon-button icon="hass:home-map-marker" on-click="onReturnHome" title="Return home"></paper-icon-button>
|
||||
<div hidden$="[[!supportsBattery(stateObj)]]">
|
||||
<span
|
||||
><iron-icon icon="[[stateObj.attributes.battery_icon]]"></iron-icon>
|
||||
[[stateObj.attributes.battery_level]] %</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div hidden$="[[!supportsCommandBar(stateObj)]]">
|
||||
<p></p>
|
||||
<div class="status-subtitle">Vacuum cleaner commands:</div>
|
||||
<div class="horizontal justified layout">
|
||||
<template is="dom-if" if="[[supportsStart(stateObj)]]">
|
||||
<div>
|
||||
<paper-icon-button
|
||||
icon="hass:play"
|
||||
on-click="onStart"
|
||||
title="Start"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div hidden$="[[!supportsPause(stateObj)]]">
|
||||
<paper-icon-button
|
||||
icon="hass:pause"
|
||||
on-click="onPause"
|
||||
title="Pause"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!supportsStart(stateObj)]]">
|
||||
<div hidden$="[[!supportsPause(stateObj)]]">
|
||||
<paper-icon-button
|
||||
icon="hass:play-pause"
|
||||
on-click="onPlayPause"
|
||||
title="Pause"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div hidden$="[[!supportsFanSpeed(stateObj)]]">
|
||||
<div class="horizontal justified layout">
|
||||
<paper-dropdown-menu label-float="" dynamic-align="" label="Fan speed">
|
||||
<paper-listbox slot="dropdown-content" selected="{{fanSpeedIndex}}">
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.fan_speed_list]]">
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<div style="justify-content: center; align-self: center; padding-top: 1.3em">
|
||||
<span><iron-icon icon="hass:fan"></iron-icon> [[stateObj.attributes.fan_speed]]</span>
|
||||
<div hidden$="[[!supportsStop(stateObj)]]">
|
||||
<paper-icon-button
|
||||
icon="hass:stop"
|
||||
on-click="onStop"
|
||||
title="Stop"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div hidden$="[[!supportsCleanSpot(stateObj)]]">
|
||||
<paper-icon-button
|
||||
icon="hass:broom"
|
||||
on-click="onCleanSpot"
|
||||
title="Clean spot"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div hidden$="[[!supportsLocate(stateObj)]]">
|
||||
<paper-icon-button
|
||||
icon="hass:map-marker"
|
||||
on-click="onLocate"
|
||||
title="Locate"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div hidden$="[[!supportsReturnHome(stateObj)]]">
|
||||
<paper-icon-button
|
||||
icon="hass:home-map-marker"
|
||||
on-click="onReturnHome"
|
||||
title="Return home"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p></p>
|
||||
</div>
|
||||
<ha-attributes state-obj="[[stateObj]]" extra-filters="fan_speed,fan_speed_list,status,battery_level,battery_icon"></ha-attributes>
|
||||
`;
|
||||
|
||||
<div hidden$="[[!supportsFanSpeed(stateObj)]]">
|
||||
<div class="horizontal justified layout">
|
||||
<paper-dropdown-menu
|
||||
label-float=""
|
||||
dynamic-align=""
|
||||
label="Fan speed"
|
||||
>
|
||||
<paper-listbox slot="dropdown-content" selected="{{fanSpeedIndex}}">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[stateObj.attributes.fan_speed_list]]"
|
||||
>
|
||||
<paper-item>[[item]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<div
|
||||
style="justify-content: center; align-self: center; padding-top: 1.3em"
|
||||
>
|
||||
<span
|
||||
><iron-icon icon="hass:fan"></iron-icon>
|
||||
[[stateObj.attributes.fan_speed]]</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<p></p>
|
||||
</div>
|
||||
<ha-attributes
|
||||
state-obj="[[stateObj]]"
|
||||
extra-filters="fan_speed,fan_speed_list,status,battery_level,battery_icon"
|
||||
></ha-attributes>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -23,89 +23,115 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class MoreInfoWaterHeater extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.container-away_mode,
|
||||
.container-temperature,
|
||||
.container-operation_list,
|
||||
.container-away_mode,
|
||||
.container-temperature,
|
||||
.container-operation_list,
|
||||
|
||||
.has-away_mode .container-away_mode,
|
||||
.has-target_temperature .container-temperature,
|
||||
.has-operation_mode .container-operation_list,
|
||||
.has-away_mode .container-away_mode,
|
||||
.has-target_temperature .container-temperature,
|
||||
.has-operation_mode .container-operation_list,
|
||||
|
||||
.container-operation_list iron-icon,
|
||||
.container-operation_list iron-icon,
|
||||
|
||||
paper-dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
paper-dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ha-paper-slider {
|
||||
width: 100%;
|
||||
}
|
||||
ha-paper-slider {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
ha-water_heater-control.range-control-left,
|
||||
ha-water_heater-control.range-control-right {
|
||||
float: left;
|
||||
width: 46%;
|
||||
}
|
||||
ha-water_heater-control.range-control-left {
|
||||
margin-right: 4%;
|
||||
}
|
||||
ha-water_heater-control.range-control-right {
|
||||
margin-left: 4%;
|
||||
}
|
||||
ha-water_heater-control.range-control-left,
|
||||
ha-water_heater-control.range-control-right {
|
||||
float: left;
|
||||
width: 46%;
|
||||
}
|
||||
ha-water_heater-control.range-control-left {
|
||||
margin-right: 4%;
|
||||
}
|
||||
ha-water_heater-control.range-control-right {
|
||||
margin-left: 4%;
|
||||
}
|
||||
|
||||
.single-row {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
.single-row {
|
||||
padding: 8px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
|
||||
<div class="container-temperature">
|
||||
<div class$="[[stateObj.attributes.operation_mode]]">
|
||||
<div hidden$="[[!supportsTemperatureControls(stateObj)]]">[[localize('ui.card.water_heater.target_temperature')]]</div>
|
||||
<template is="dom-if" if="[[supportsTemperature(stateObj)]]">
|
||||
<ha-water_heater-control value="[[stateObj.attributes.temperature]]" units="[[hass.config.unit_system.temperature]]" step="[[computeTemperatureStepSize(hass, stateObj)]]" min="[[stateObj.attributes.min_temp]]" max="[[stateObj.attributes.max_temp]]" on-change="targetTemperatureChanged">
|
||||
</ha-water_heater-control>
|
||||
</template>
|
||||
<div class$="[[computeClassNames(stateObj)]]">
|
||||
<div class="container-temperature">
|
||||
<div class$="[[stateObj.attributes.operation_mode]]">
|
||||
<div hidden$="[[!supportsTemperatureControls(stateObj)]]">
|
||||
[[localize('ui.card.water_heater.target_temperature')]]
|
||||
</div>
|
||||
<template is="dom-if" if="[[supportsTemperature(stateObj)]]">
|
||||
<ha-water_heater-control
|
||||
value="[[stateObj.attributes.temperature]]"
|
||||
units="[[hass.config.unit_system.temperature]]"
|
||||
step="[[computeTemperatureStepSize(hass, stateObj)]]"
|
||||
min="[[stateObj.attributes.min_temp]]"
|
||||
max="[[stateObj.attributes.max_temp]]"
|
||||
on-change="targetTemperatureChanged"
|
||||
>
|
||||
</ha-water_heater-control>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template is="dom-if" if="[[supportsOperationMode(stateObj)]]">
|
||||
<div class="container-operation_list">
|
||||
<div class="controls">
|
||||
<paper-dropdown-menu
|
||||
label-float=""
|
||||
dynamic-align=""
|
||||
label="[[localize('ui.card.water_heater.operation')]]"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{operationIndex}}"
|
||||
>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[stateObj.attributes.operation_list]]"
|
||||
on-dom-change="handleOperationListUpdate"
|
||||
>
|
||||
<paper-item
|
||||
>[[_localizeOperationMode(localize, item)]]</paper-item
|
||||
>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsAwayMode(stateObj)]]">
|
||||
<div class="container-away_mode">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">
|
||||
[[localize('ui.card.water_heater.away_mode')]]
|
||||
</div>
|
||||
<paper-toggle-button
|
||||
checked="[[awayToggleChecked]]"
|
||||
on-change="awayToggleChanged"
|
||||
>
|
||||
</paper-toggle-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template is="dom-if" if="[[supportsOperationMode(stateObj)]]">
|
||||
<div class="container-operation_list">
|
||||
<div class="controls">
|
||||
<paper-dropdown-menu label-float="" dynamic-align="" label="[[localize('ui.card.water_heater.operation')]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{operationIndex}}">
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.operation_list]]" on-dom-change="handleOperationListUpdate">
|
||||
<paper-item>[[_localizeOperationMode(localize, item)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[supportsAwayMode(stateObj)]]">
|
||||
<div class="container-away_mode">
|
||||
<div class="center horizontal layout single-row">
|
||||
<div class="flex">[[localize('ui.card.water_heater.away_mode')]]</div>
|
||||
<paper-toggle-button checked="[[awayToggleChecked]]" on-change="awayToggleChanged">
|
||||
</paper-toggle-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,97 +10,118 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class MoreInfoWeather extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
iron-icon {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
.section {
|
||||
margin: 16px 0 8px 0;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
<style>
|
||||
iron-icon {
|
||||
color: var(--paper-item-icon-color);
|
||||
}
|
||||
.section {
|
||||
margin: 16px 0 8px 0;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
margin-left: 24px;
|
||||
}
|
||||
.main {
|
||||
flex: 1;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.temp,
|
||||
.templow {
|
||||
min-width: 48px;
|
||||
text-align: right;
|
||||
}
|
||||
.temp,
|
||||
.templow {
|
||||
min-width: 48px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.templow {
|
||||
margin: 0 16px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.templow {
|
||||
margin: 0 16px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.attribution {
|
||||
color: var(--secondary-text-color);
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
.attribution {
|
||||
color: var(--secondary-text-color);
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:thermometer"></iron-icon>
|
||||
<div class="main">[[localize('ui.card.weather.attributes.temperature')]]</div>
|
||||
<div>[[stateObj.attributes.temperature]] [[getUnit('temperature')]]</div>
|
||||
</div>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.pressure)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:gauge"></iron-icon>
|
||||
<div class="main">[[localize('ui.card.weather.attributes.air_pressure')]]</div>
|
||||
<div>[[stateObj.attributes.pressure]] [[getUnit('air_pressure')]]</div>
|
||||
<iron-icon icon="hass:thermometer"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.temperature')]]
|
||||
</div>
|
||||
<div>
|
||||
[[stateObj.attributes.temperature]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.humidity)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:water-percent"></iron-icon>
|
||||
<div class="main">[[localize('ui.card.weather.attributes.humidity')]]</div>
|
||||
<div>[[stateObj.attributes.humidity]] %</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.wind_speed)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:weather-windy"></iron-icon>
|
||||
<div class="main">[[localize('ui.card.weather.attributes.wind_speed')]]</div>
|
||||
<div>[[getWind(stateObj.attributes.wind_speed, stateObj.attributes.wind_bearing, localize)]]</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.visibility)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:eye"></iron-icon>
|
||||
<div class="main">[[localize('ui.card.weather.attributes.visibility')]]</div>
|
||||
<div>[[stateObj.attributes.visibility]] [[getUnit('length')]]</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[stateObj.attributes.forecast]]">
|
||||
<div class="section">[[localize('ui.card.weather.forecast')]]:</div>
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.forecast]]">
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.pressure)]]">
|
||||
<div class="flex">
|
||||
<template is="dom-if" if="[[_showValue(item.condition)]]">
|
||||
<iron-icon icon="[[getWeatherIcon(item.condition)]]"></iron-icon>
|
||||
</template>
|
||||
<div class="main">[[computeDateTime(item.datetime)]]</div>
|
||||
<template is="dom-if" if="[[_showValue(item.templow)]]">
|
||||
<div class="templow">[[item.templow]] [[getUnit('temperature')]]</div>
|
||||
</template>
|
||||
<div class="temp">[[item.temperature]] [[getUnit('temperature')]]</div>
|
||||
<iron-icon icon="hass:gauge"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.air_pressure')]]
|
||||
</div>
|
||||
<div>
|
||||
[[stateObj.attributes.pressure]] [[getUnit('air_pressure')]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.humidity)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:water-percent"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.humidity')]]
|
||||
</div>
|
||||
<div>[[stateObj.attributes.humidity]] %</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.wind_speed)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:weather-windy"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.wind_speed')]]
|
||||
</div>
|
||||
<div>
|
||||
[[getWind(stateObj.attributes.wind_speed,
|
||||
stateObj.attributes.wind_bearing, localize)]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showValue(stateObj.attributes.visibility)]]">
|
||||
<div class="flex">
|
||||
<iron-icon icon="hass:eye"></iron-icon>
|
||||
<div class="main">
|
||||
[[localize('ui.card.weather.attributes.visibility')]]
|
||||
</div>
|
||||
<div>[[stateObj.attributes.visibility]] [[getUnit('length')]]</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="stateObj.attributes.attribution">
|
||||
<div class="attribution">[[stateObj.attributes.attribution]]</div>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[stateObj.attributes.forecast]]">
|
||||
<div class="section">[[localize('ui.card.weather.forecast')]]:</div>
|
||||
<template is="dom-repeat" items="[[stateObj.attributes.forecast]]">
|
||||
<div class="flex">
|
||||
<template is="dom-if" if="[[_showValue(item.condition)]]">
|
||||
<iron-icon icon="[[getWeatherIcon(item.condition)]]"></iron-icon>
|
||||
</template>
|
||||
<div class="main">[[computeDateTime(item.datetime)]]</div>
|
||||
<template is="dom-if" if="[[_showValue(item.templow)]]">
|
||||
<div class="templow">
|
||||
[[item.templow]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
</template>
|
||||
<div class="temp">
|
||||
[[item.temperature]] [[getUnit('temperature')]]
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="stateObj.attributes.attribution">
|
||||
<div class="attribution">[[stateObj.attributes.attribution]]</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -24,61 +24,92 @@ const DOMAINS_NO_INFO = ["camera", "configurator", "history_graph"];
|
||||
class MoreInfoControls extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style-dialog">
|
||||
app-toolbar {
|
||||
color: var(--more-info-header-color);
|
||||
background-color: var(--more-info-header-background);
|
||||
}
|
||||
<style include="ha-style-dialog">
|
||||
app-toolbar {
|
||||
color: var(--more-info-header-color);
|
||||
background-color: var(--more-info-header-background);
|
||||
}
|
||||
|
||||
app-toolbar [main-title] {
|
||||
@apply --ha-more-info-app-toolbar-title;
|
||||
}
|
||||
app-toolbar [main-title] {
|
||||
@apply --ha-more-info-app-toolbar-title;
|
||||
}
|
||||
|
||||
state-card-content {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
}
|
||||
state-card-content {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
state-history-charts {
|
||||
max-width: 100%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
state-history-charts {
|
||||
max-width: 100%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@media all and (min-width: 451px) and (min-height: 501px) {
|
||||
.main-title {
|
||||
pointer-events: auto;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
@media all and (min-width: 451px) and (min-height: 501px) {
|
||||
.main-title {
|
||||
pointer-events: auto;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
paper-dialog-scrollable {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
paper-dialog-scrollable {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
:host([domain=camera]) paper-dialog-scrollable {
|
||||
margin: 0 -24px -21px;
|
||||
}
|
||||
</style>
|
||||
:host([domain="camera"]) paper-dialog-scrollable {
|
||||
margin: 0 -24px -21px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:close" dialog-dismiss=""></paper-icon-button>
|
||||
<div class="main-title" main-title="" on-click="enlarge">[[_computeStateName(stateObj)]]</div>
|
||||
<template is="dom-if" if="[[canConfigure]]">
|
||||
<paper-icon-button icon="hass:settings" on-click="_gotoSettings"></paper-icon-button>
|
||||
</template>
|
||||
</app-toolbar>
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:close"
|
||||
dialog-dismiss=""
|
||||
></paper-icon-button>
|
||||
<div class="main-title" main-title="" on-click="enlarge">
|
||||
[[_computeStateName(stateObj)]]
|
||||
</div>
|
||||
<template is="dom-if" if="[[canConfigure]]">
|
||||
<paper-icon-button
|
||||
icon="hass:settings"
|
||||
on-click="_gotoSettings"
|
||||
></paper-icon-button>
|
||||
</template>
|
||||
</app-toolbar>
|
||||
|
||||
<template is="dom-if" if="[[_computeShowStateInfo(stateObj)]]" restamp="">
|
||||
<state-card-content state-obj="[[stateObj]]" hass="[[hass]]" in-dialog=""></state-card-content>
|
||||
</template>
|
||||
<paper-dialog-scrollable dialog-element="[[dialogElement]]">
|
||||
<template is="dom-if" if="[[_computeShowHistoryComponent(hass, stateObj)]]" restamp="">
|
||||
<ha-state-history-data hass="[[hass]]" filter-type="recent-entity" entity-id="[[stateObj.entity_id]]" data="{{_stateHistory}}" is-loading="{{_stateHistoryLoading}}" cache-config="[[_cacheConfig]]"></ha-state-history-data>
|
||||
<state-history-charts hass="[[hass]]" history-data="[[_stateHistory]]" is-loading-data="[[_stateHistoryLoading]]" up-to-now></state-history-charts>
|
||||
</template>
|
||||
<more-info-content state-obj="[[stateObj]]" hass="[[hass]]"></more-info-content>
|
||||
</paper-dialog-scrollable>
|
||||
`;
|
||||
<template is="dom-if" if="[[_computeShowStateInfo(stateObj)]]" restamp="">
|
||||
<state-card-content
|
||||
state-obj="[[stateObj]]"
|
||||
hass="[[hass]]"
|
||||
in-dialog=""
|
||||
></state-card-content>
|
||||
</template>
|
||||
<paper-dialog-scrollable dialog-element="[[dialogElement]]">
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_computeShowHistoryComponent(hass, stateObj)]]"
|
||||
restamp=""
|
||||
>
|
||||
<ha-state-history-data
|
||||
hass="[[hass]]"
|
||||
filter-type="recent-entity"
|
||||
entity-id="[[stateObj.entity_id]]"
|
||||
data="{{_stateHistory}}"
|
||||
is-loading="{{_stateHistoryLoading}}"
|
||||
cache-config="[[_cacheConfig]]"
|
||||
></ha-state-history-data>
|
||||
<state-history-charts
|
||||
hass="[[hass]]"
|
||||
history-data="[[_stateHistory]]"
|
||||
is-loading-data="[[_stateHistoryLoading]]"
|
||||
up-to-now
|
||||
></state-history-charts>
|
||||
</template>
|
||||
<more-info-content
|
||||
state-obj="[[stateObj]]"
|
||||
hass="[[hass]]"
|
||||
></more-info-content>
|
||||
</paper-dialog-scrollable>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -19,51 +19,53 @@ import isComponentLoaded from "../../common/config/is_component_loaded";
|
||||
class MoreInfoSettings extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
app-toolbar {
|
||||
color: var(--more-info-header-color);
|
||||
background-color: var(--more-info-header-background);
|
||||
<style>
|
||||
app-toolbar {
|
||||
color: var(--more-info-header-color);
|
||||
background-color: var(--more-info-header-background);
|
||||
|
||||
/* to fit save button */
|
||||
padding-right: 0;
|
||||
}
|
||||
/* to fit save button */
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
app-toolbar [main-title] {
|
||||
@apply --ha-more-info-app-toolbar-title;
|
||||
}
|
||||
app-toolbar [main-title] {
|
||||
@apply --ha-more-info-app-toolbar-title;
|
||||
}
|
||||
|
||||
app-toolbar paper-button {
|
||||
font-size: .8em;
|
||||
margin: 0;
|
||||
}
|
||||
app-toolbar paper-button {
|
||||
font-size: 0.8em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.form {
|
||||
padding: 0 24px 24px;
|
||||
}
|
||||
</style>
|
||||
.form {
|
||||
padding: 0 24px 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="_backTapped"></paper-icon-button>
|
||||
<div main-title="">[[_computeStateName(stateObj)]]</div>
|
||||
<paper-button
|
||||
on-click="_save"
|
||||
disabled='[[_computeInvalid(_entityId)]]'
|
||||
>[[localize('ui.dialogs.more_info_settings.save')]]</paper-button>
|
||||
</app-toolbar>
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="_backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">[[_computeStateName(stateObj)]]</div>
|
||||
<paper-button on-click="_save" disabled="[[_computeInvalid(_entityId)]]"
|
||||
>[[localize('ui.dialogs.more_info_settings.save')]]</paper-button
|
||||
>
|
||||
</app-toolbar>
|
||||
|
||||
<div class="form">
|
||||
<paper-input
|
||||
value="{{_name}}"
|
||||
label="[[localize('ui.dialogs.more_info_settings.name')]]"
|
||||
></paper-input>
|
||||
<paper-input
|
||||
value="{{_entityId}}"
|
||||
label="[[localize('ui.dialogs.more_info_settings.entity_id')]]"
|
||||
error-message="Domain needs to stay the same"
|
||||
invalid='[[_computeInvalid(_entityId)]]'
|
||||
></paper-input>
|
||||
</div>
|
||||
`;
|
||||
<div class="form">
|
||||
<paper-input
|
||||
value="{{_name}}"
|
||||
label="[[localize('ui.dialogs.more_info_settings.name')]]"
|
||||
></paper-input>
|
||||
<paper-input
|
||||
value="{{_entityId}}"
|
||||
label="[[localize('ui.dialogs.more_info_settings.entity_id')]]"
|
||||
error-message="Domain needs to stay the same"
|
||||
invalid="[[_computeInvalid(_entityId)]]"
|
||||
></paper-input>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -38,23 +38,23 @@ class HomeAssistant extends ext(PolymerElement, [
|
||||
]) {
|
||||
static get template() {
|
||||
return html`
|
||||
<app-location route="{{route}}"></app-location>
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
pattern="/:panel"
|
||||
data="{{routeData}}"
|
||||
></app-route>
|
||||
<template is="dom-if" if="[[showMain]]" restamp>
|
||||
<home-assistant-main
|
||||
hass="[[hass]]"
|
||||
<app-location route="{{route}}"></app-location>
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
></home-assistant-main>
|
||||
</template>
|
||||
pattern="/:panel"
|
||||
data="{{routeData}}"
|
||||
></app-route>
|
||||
<template is="dom-if" if="[[showMain]]" restamp>
|
||||
<home-assistant-main
|
||||
hass="[[hass]]"
|
||||
route="{{route}}"
|
||||
></home-assistant-main>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[!showMain]]" restamp>
|
||||
<ha-init-page error='[[_error]]'></ha-init-page>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[!showMain]]" restamp>
|
||||
<ha-init-page error="[[_error]]"></ha-init-page>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -24,76 +24,75 @@ import "@polymer/polymer/polymer-element";
|
||||
class HaAppLayout extends customElements.get("app-header-layout") {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
/**
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
/**
|
||||
* Force app-header-layout to have its own stacking context so that its parent can
|
||||
* control the stacking of it relative to other elements (e.g. app-drawer-layout).
|
||||
* This could be done using \`isolation: isolate\`, but that's not well supported
|
||||
* across browsers.
|
||||
*/
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#wrapper ::slotted([slot=header]) {
|
||||
@apply --layout-fixed-top;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#wrapper.initializing ::slotted([slot=header]) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) #wrapper ::slotted([slot=header]) {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) #wrapper.initializing ::slotted([slot=header]) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) #wrapper #contentContainer {
|
||||
@apply --layout-fit;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) #wrapper.initializing #contentContainer {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#contentContainer {
|
||||
/* Create a stacking context here so that all children appear below the header. */
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
/* Using 'transform' will cause 'position: fixed' elements to behave like
|
||||
'position: absolute' relative to this element. */
|
||||
transform: translate(0);
|
||||
}
|
||||
|
||||
@media print {
|
||||
:host([has-scrolling-region]) #wrapper #contentContainer {
|
||||
overflow-y: visible;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
#wrapper ::slotted([slot="header"]) {
|
||||
@apply --layout-fixed-top;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
<div id="wrapper" class="initializing">
|
||||
<slot id="headerSlot" name="header"></slot>
|
||||
#wrapper.initializing ::slotted([slot="header"]) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
<div id="contentContainer">
|
||||
<slot></slot>
|
||||
:host([has-scrolling-region]) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) #wrapper ::slotted([slot="header"]) {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region])
|
||||
#wrapper.initializing
|
||||
::slotted([slot="header"]) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) #wrapper #contentContainer {
|
||||
@apply --layout-fit;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
:host([has-scrolling-region]) #wrapper.initializing #contentContainer {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#contentContainer {
|
||||
/* Create a stacking context here so that all children appear below the header. */
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
/* Using 'transform' will cause 'position: fixed' elements to behave like
|
||||
'position: absolute' relative to this element. */
|
||||
transform: translate(0);
|
||||
}
|
||||
|
||||
@media print {
|
||||
:host([has-scrolling-region]) #wrapper #contentContainer {
|
||||
overflow-y: visible;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="wrapper" class="initializing">
|
||||
<slot id="headerSlot" name="header"></slot>
|
||||
|
||||
<div id="contentContainer"><slot></slot></div>
|
||||
<slot id="fab" name="fab"></slot>
|
||||
</div>
|
||||
<slot id="fab" name="fab"></slot>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define("ha-app-layout", HaAppLayout);
|
||||
|
||||
@ -13,25 +13,25 @@ import EventsMixin from "../mixins/events-mixin";
|
||||
class HaInitPage extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-positioning"></style>
|
||||
<style>
|
||||
paper-spinner {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
<style include="iron-flex iron-positioning"></style>
|
||||
<style>
|
||||
paper-spinner {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="layout vertical center center-center fit">
|
||||
<img src="/static/icons/favicon-192x192.png" height="192">
|
||||
<paper-spinner active="[[!error]]"></paper-spinner>
|
||||
<template is='dom-if' if='[[error]]'>
|
||||
Unable to connect to Home Assistant.
|
||||
<paper-button on-click='_retry'>Retry</paper-button>
|
||||
</template>
|
||||
<template is='dom-if' if='[[!error]]'>
|
||||
Loading data
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
<div class="layout vertical center center-center fit">
|
||||
<img src="/static/icons/favicon-192x192.png" height="192" />
|
||||
<paper-spinner active="[[!error]]"></paper-spinner>
|
||||
<template is="dom-if" if="[[error]]">
|
||||
Unable to connect to Home Assistant.
|
||||
<paper-button on-click="_retry">Retry</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!error]]">
|
||||
Loading data
|
||||
</template>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,31 +7,31 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HassErrorScreen extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.placeholder {
|
||||
height: 100%;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.placeholder {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.layout {
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
.layout {
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
|
||||
paper-button {
|
||||
font-weight: bold;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
paper-button {
|
||||
font-weight: bold;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="placeholder">
|
||||
<app-toolbar>
|
||||
<div main-title="">[[title]]</div>
|
||||
</app-toolbar>
|
||||
<div class="layout vertical center-center">
|
||||
<h3>[[error]]</h3>
|
||||
<slot><paper-button on-click="backTapped">go back</paper-button></slot>
|
||||
<div class="placeholder">
|
||||
<app-toolbar> <div main-title="">[[title]]</div> </app-toolbar>
|
||||
<div class="layout vertical center-center">
|
||||
<h3>[[error]]</h3>
|
||||
<slot
|
||||
><paper-button on-click="backTapped">go back</paper-button></slot
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,26 +9,29 @@ import "../components/ha-menu-button";
|
||||
class HassLoadingScreen extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.placeholder {
|
||||
height: 100%;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.placeholder {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.layout {
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
</style>
|
||||
.layout {
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="placeholder">
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow="[[narrow]]" show-menu="[[showMenu]]"></ha-menu-button>
|
||||
<div main-title="">[[title]]</div>
|
||||
</app-toolbar>
|
||||
<div class="layout horizontal center-center">
|
||||
<paper-spinner active=""></paper-spinner>
|
||||
<div class="placeholder">
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title="">[[title]]</div>
|
||||
</app-toolbar>
|
||||
<div class="layout horizontal center-center">
|
||||
<paper-spinner active=""></paper-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -8,19 +8,22 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HassSubpage extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style"></style>
|
||||
<app-header-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="_backTapped"></paper-icon-button>
|
||||
<div main-title="">[[header]]</div>
|
||||
<slot name="toolbar-icon"></slot>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<style include="ha-style"></style>
|
||||
<app-header-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="_backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">[[header]]</div>
|
||||
<slot name="toolbar-icon"></slot>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<slot></slot>
|
||||
</app-header-layout>
|
||||
`;
|
||||
<slot></slot>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -21,39 +21,78 @@ const NON_SWIPABLE_PANELS = ["kiosk", "map"];
|
||||
class HomeAssistantMain extends NavigateMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
/* remove the grey tap highlights in iOS on the fullscreen touch targets */
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
iron-pages, ha-sidebar {
|
||||
/* allow a light tap highlight on the actual interface elements */
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0.1);
|
||||
}
|
||||
iron-pages {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<ha-url-sync hass="[[hass]]"></ha-url-sync>
|
||||
<app-route route="{{route}}" pattern="/states" tail="{{statesRouteTail}}"></app-route>
|
||||
<ha-voice-command-dialog hass="[[hass]]" id="voiceDialog"></ha-voice-command-dialog>
|
||||
<iron-media-query query="(max-width: 870px)" query-matches="{{narrow}}">
|
||||
</iron-media-query>
|
||||
<style>
|
||||
:host {
|
||||
color: var(--primary-text-color);
|
||||
/* remove the grey tap highlights in iOS on the fullscreen touch targets */
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
iron-pages,
|
||||
ha-sidebar {
|
||||
/* allow a light tap highlight on the actual interface elements */
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
iron-pages {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<ha-url-sync hass="[[hass]]"></ha-url-sync>
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
pattern="/states"
|
||||
tail="{{statesRouteTail}}"
|
||||
></app-route>
|
||||
<ha-voice-command-dialog
|
||||
hass="[[hass]]"
|
||||
id="voiceDialog"
|
||||
></ha-voice-command-dialog>
|
||||
<iron-media-query query="(max-width: 870px)" query-matches="{{narrow}}">
|
||||
</iron-media-query>
|
||||
|
||||
<app-drawer-layout fullbleed="" force-narrow="[[computeForceNarrow(narrow, dockedSidebar)]]" responsive-width="0">
|
||||
<app-drawer id="drawer" slot="drawer" disable-swipe="[[_computeDisableSwipe(hass)]]" swipe-open="[[!_computeDisableSwipe(hass)]]" persistent="[[dockedSidebar]]">
|
||||
<ha-sidebar narrow="[[narrow]]" hass="[[hass]]" default-page="[[_defaultPage]]"></ha-sidebar>
|
||||
</app-drawer>
|
||||
<app-drawer-layout
|
||||
fullbleed=""
|
||||
force-narrow="[[computeForceNarrow(narrow, dockedSidebar)]]"
|
||||
responsive-width="0"
|
||||
>
|
||||
<app-drawer
|
||||
id="drawer"
|
||||
slot="drawer"
|
||||
disable-swipe="[[_computeDisableSwipe(hass)]]"
|
||||
swipe-open="[[!_computeDisableSwipe(hass)]]"
|
||||
persistent="[[dockedSidebar]]"
|
||||
>
|
||||
<ha-sidebar
|
||||
narrow="[[narrow]]"
|
||||
hass="[[hass]]"
|
||||
default-page="[[_defaultPage]]"
|
||||
></ha-sidebar>
|
||||
</app-drawer>
|
||||
|
||||
<iron-pages attr-for-selected="id" fallback-selection="panel-resolver" selected="[[hass.panelUrl]]" selected-attribute="panel-visible">
|
||||
<partial-cards id="states" narrow="[[narrow]]" hass="[[hass]]" show-menu="[[dockedSidebar]]" route="[[statesRouteTail]]" show-tabs=""></partial-cards>
|
||||
<iron-pages
|
||||
attr-for-selected="id"
|
||||
fallback-selection="panel-resolver"
|
||||
selected="[[hass.panelUrl]]"
|
||||
selected-attribute="panel-visible"
|
||||
>
|
||||
<partial-cards
|
||||
id="states"
|
||||
narrow="[[narrow]]"
|
||||
hass="[[hass]]"
|
||||
show-menu="[[dockedSidebar]]"
|
||||
route="[[statesRouteTail]]"
|
||||
show-tabs=""
|
||||
></partial-cards>
|
||||
|
||||
<partial-panel-resolver id="panel-resolver" narrow="[[narrow]]" hass="[[hass]]" route="[[route]]" show-menu="[[dockedSidebar]]"></partial-panel-resolver>
|
||||
|
||||
</iron-pages>
|
||||
</app-drawer-layout>
|
||||
`;
|
||||
<partial-panel-resolver
|
||||
id="panel-resolver"
|
||||
narrow="[[narrow]]"
|
||||
hass="[[hass]]"
|
||||
route="[[route]]"
|
||||
show-menu="[[dockedSidebar]]"
|
||||
></partial-panel-resolver>
|
||||
</iron-pages>
|
||||
</app-drawer-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -34,72 +34,113 @@ const ALWAYS_SHOW_DOMAIN = ["persistent_notification", "configurator"];
|
||||
class PartialCards extends EventsMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex iron-positioning ha-style">
|
||||
:host {
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
<style include="iron-flex iron-positioning ha-style">
|
||||
:host {
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
ha-app-layout {
|
||||
min-height: 100%;
|
||||
background-color: var(--secondary-background-color, #E5E5E5);
|
||||
}
|
||||
ha-app-layout {
|
||||
min-height: 100%;
|
||||
background-color: var(--secondary-background-color, #e5e5e5);
|
||||
}
|
||||
|
||||
paper-tabs {
|
||||
margin-left: 12px;
|
||||
--paper-tabs-selection-bar-color: var(--text-primary-color, #FFF);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
<app-route route="{{route}}" pattern="/:view" data="{{routeData}}" active="{{routeMatch}}"></app-route>
|
||||
<ha-app-layout id="layout">
|
||||
<app-header effects="waterfall" condenses="" fixed="" slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow="[[narrow]]" show-menu="[[showMenu]]"></ha-menu-button>
|
||||
<div main-title="">[[computeTitle(views, defaultView, locationName)]]</div>
|
||||
<ha-start-voice-button hass="[[hass]]"></ha-start-voice-button>
|
||||
</app-toolbar>
|
||||
paper-tabs {
|
||||
margin-left: 12px;
|
||||
--paper-tabs-selection-bar-color: var(--text-primary-color, #fff);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
pattern="/:view"
|
||||
data="{{routeData}}"
|
||||
active="{{routeMatch}}"
|
||||
></app-route>
|
||||
<ha-app-layout id="layout">
|
||||
<app-header effects="waterfall" condenses="" fixed="" slot="header">
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title="">
|
||||
[[computeTitle(views, defaultView, locationName)]]
|
||||
</div>
|
||||
<ha-start-voice-button hass="[[hass]]"></ha-start-voice-button>
|
||||
</app-toolbar>
|
||||
|
||||
<div sticky="" hidden$="[[areTabsHidden(views, showTabs)]]">
|
||||
<paper-tabs scrollable="" selected="[[currentView]]" attr-for-selected="data-entity" on-iron-activate="handleViewSelected">
|
||||
<paper-tab data-entity="" on-click="scrollToTop">
|
||||
<template is="dom-if" if="[[!defaultView]]">
|
||||
Home
|
||||
</template>
|
||||
<template is="dom-if" if="[[defaultView]]">
|
||||
<template is="dom-if" if="[[defaultView.attributes.icon]]">
|
||||
<ha-icon title$="[[_computeStateName(defaultView)]]" icon="[[defaultView.attributes.icon]]"></ha-icon>
|
||||
<div sticky="" hidden$="[[areTabsHidden(views, showTabs)]]">
|
||||
<paper-tabs
|
||||
scrollable=""
|
||||
selected="[[currentView]]"
|
||||
attr-for-selected="data-entity"
|
||||
on-iron-activate="handleViewSelected"
|
||||
>
|
||||
<paper-tab data-entity="" on-click="scrollToTop">
|
||||
<template is="dom-if" if="[[!defaultView]]">
|
||||
Home
|
||||
</template>
|
||||
<template is="dom-if" if="[[defaultView]]">
|
||||
<template is="dom-if" if="[[defaultView.attributes.icon]]">
|
||||
<ha-icon
|
||||
title$="[[_computeStateName(defaultView)]]"
|
||||
icon="[[defaultView.attributes.icon]]"
|
||||
></ha-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!defaultView.attributes.icon]]">
|
||||
[[_computeStateName(defaultView)]]
|
||||
</template>
|
||||
</template>
|
||||
</paper-tab>
|
||||
<template is="dom-repeat" items="[[views]]">
|
||||
<paper-tab
|
||||
data-entity$="[[item.entity_id]]"
|
||||
on-click="scrollToTop"
|
||||
>
|
||||
<template is="dom-if" if="[[item.attributes.icon]]">
|
||||
<ha-icon
|
||||
title$="[[_computeStateName(item)]]"
|
||||
icon="[[item.attributes.icon]]"
|
||||
></ha-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!item.attributes.icon]]">
|
||||
[[_computeStateName(item)]]
|
||||
</template>
|
||||
</paper-tab>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!defaultView.attributes.icon]]">
|
||||
[[_computeStateName(defaultView)]]
|
||||
</template>
|
||||
</template>
|
||||
</paper-tab>
|
||||
</paper-tabs>
|
||||
</div>
|
||||
</app-header>
|
||||
|
||||
<iron-pages
|
||||
attr-for-selected="data-view"
|
||||
selected="[[currentView]]"
|
||||
selected-attribute="view-visible"
|
||||
>
|
||||
<ha-cards
|
||||
data-view=""
|
||||
states="[[viewStates]]"
|
||||
columns="[[_columns]]"
|
||||
hass="[[hass]]"
|
||||
panel-visible="[[panelVisible]]"
|
||||
ordered-group-entities="[[orderedGroupEntities]]"
|
||||
></ha-cards>
|
||||
|
||||
<template is="dom-repeat" items="[[views]]">
|
||||
<paper-tab data-entity$="[[item.entity_id]]" on-click="scrollToTop">
|
||||
<template is="dom-if" if="[[item.attributes.icon]]">
|
||||
<ha-icon title$="[[_computeStateName(item)]]" icon="[[item.attributes.icon]]"></ha-icon>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!item.attributes.icon]]">
|
||||
[[_computeStateName(item)]]
|
||||
</template>
|
||||
</paper-tab>
|
||||
<ha-cards
|
||||
data-view$="[[item.entity_id]]"
|
||||
states="[[viewStates]]"
|
||||
columns="[[_columns]]"
|
||||
hass="[[hass]]"
|
||||
panel-visible="[[panelVisible]]"
|
||||
ordered-group-entities="[[orderedGroupEntities]]"
|
||||
></ha-cards>
|
||||
</template>
|
||||
</paper-tabs>
|
||||
</div>
|
||||
</app-header>
|
||||
|
||||
<iron-pages attr-for-selected="data-view" selected="[[currentView]]" selected-attribute="view-visible">
|
||||
<ha-cards data-view="" states="[[viewStates]]" columns="[[_columns]]" hass="[[hass]]" panel-visible="[[panelVisible]]" ordered-group-entities="[[orderedGroupEntities]]"></ha-cards>
|
||||
|
||||
<template is="dom-repeat" items="[[views]]">
|
||||
<ha-cards data-view$="[[item.entity_id]]" states="[[viewStates]]" columns="[[_columns]]" hass="[[hass]]" panel-visible="[[panelVisible]]" ordered-group-entities="[[orderedGroupEntities]]"></ha-cards>
|
||||
</template>
|
||||
|
||||
</iron-pages>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
</iron-pages>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -107,27 +107,35 @@ function ensureLoaded(panel) {
|
||||
class PartialPanelResolver extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<app-route route="{{route}}" pattern="/:panel" data="{{routeData}}" tail="{{routeTail}}"></app-route>
|
||||
<style>
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<app-route
|
||||
route="{{route}}"
|
||||
pattern="/:panel"
|
||||
data="{{routeData}}"
|
||||
tail="{{routeTail}}"
|
||||
></app-route>
|
||||
|
||||
<template is="dom-if" if="[[_equal(_state, 'loading')]]">
|
||||
<hass-loading-screen narrow="[[narrow]]" show-menu="[[showMenu]]"></hass-loading-screen>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equal(_state, 'error')]]">
|
||||
<hass-error-screen
|
||||
title=''
|
||||
error="Error while loading this panel."
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></hass-error-screen>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equal(_state, 'loading')]]">
|
||||
<hass-loading-screen
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></hass-loading-screen>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equal(_state, 'error')]]">
|
||||
<hass-error-screen
|
||||
title=""
|
||||
error="Error while loading this panel."
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></hass-error-screen>
|
||||
</template>
|
||||
|
||||
<span id="panel" hidden$="[[!_equal(_state, 'loaded')]]"></span>
|
||||
`;
|
||||
<span id="panel" hidden$="[[!_equal(_state, 'loaded')]]"></span>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,17 +6,17 @@ import LocalizeMixin from "../mixins/localize-mixin";
|
||||
class NotificationManager extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-toast {
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
paper-toast {
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-toast
|
||||
id="toast"
|
||||
no-cancel-on-outside-click="[[_cancelOnOutsideClick]]"
|
||||
></ha-toast>
|
||||
`;
|
||||
<ha-toast
|
||||
id="toast"
|
||||
no-cancel-on-outside-click="[[_cancelOnOutsideClick]]"
|
||||
></ha-toast>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,14 +18,18 @@ const DEFAULT_VIEW = "month";
|
||||
class HaBigCalendar extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<link rel="stylesheet" href="/static/panels/calendar/react-big-calendar.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/static/panels/calendar/react-big-calendar.css"
|
||||
/>
|
||||
<style>
|
||||
div#root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<div id="root"></div>`;
|
||||
<div id="root"></div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -46,8 +46,8 @@ class HaPanelCalendar extends LocalizeMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
div.all_calendars {
|
||||
 height: 20px;
|
||||
 text-align: center;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.iron-selected {
|
||||
@ -67,7 +67,10 @@ class HaPanelCalendar extends LocalizeMixin(PolymerElement) {
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>[[localize('panel.calendar')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
@ -84,9 +87,11 @@ class HaPanelCalendar extends LocalizeMixin(PolymerElement) {
|
||||
>
|
||||
<template is="dom-repeat" items="[[calendars]]">
|
||||
<paper-item item-name="[[item.entity_id]]">
|
||||
<span class="calendar_color" style$="background-color: [[item.color]]"></span>
|
||||
<span class="calendar_color_spacer"></span>
|
||||
[[item.name]]
|
||||
<span
|
||||
class="calendar_color"
|
||||
style$="background-color: [[item.color]]"
|
||||
></span>
|
||||
<span class="calendar_color_spacer"></span> [[item.name]]
|
||||
</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
@ -96,13 +101,15 @@ class HaPanelCalendar extends LocalizeMixin(PolymerElement) {
|
||||
<ha-big-calendar
|
||||
default-date="[[currentDate]]"
|
||||
default-view="[[currentView]]"
|
||||
on-navigate='_handleNavigate'
|
||||
on-view='_handleViewChanged'
|
||||
events="[[events]]">
|
||||
on-navigate="_handleNavigate"
|
||||
on-view="_handleViewChanged"
|
||||
events="[[events]]"
|
||||
>
|
||||
</ha-big-calendar>
|
||||
</div>
|
||||
</div>
|
||||
</app-header-layout>`;
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -26,79 +26,89 @@ function AutomationEditor(mountEl, props, mergeEl) {
|
||||
class HaAutomationEditor extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
.errors {
|
||||
padding: 20px;
|
||||
font-weight: bold;
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.triggers,
|
||||
.script {
|
||||
margin-top: -16px;
|
||||
}
|
||||
.triggers paper-card,
|
||||
.script paper-card {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.add-card paper-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.card-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.card-menu paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
span[slot=introduction] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
margin-bottom: -80px;
|
||||
transition: margin-bottom .3s;
|
||||
}
|
||||
<style include="ha-style">
|
||||
.errors {
|
||||
padding: 20px;
|
||||
font-weight: bold;
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.triggers,
|
||||
.script {
|
||||
margin-top: -16px;
|
||||
}
|
||||
.triggers paper-card,
|
||||
.script paper-card {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.add-card paper-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.card-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.card-menu paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
span[slot="introduction"] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
margin-bottom: -80px;
|
||||
transition: margin-bottom 0.3s;
|
||||
}
|
||||
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
paper-fab[dirty] {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
paper-fab[dirty] {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="backTapped"></paper-icon-button>
|
||||
<div main-title="">[[computeName(automation, localize)]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">[[computeName(automation, localize)]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<div class="content">
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">[[errors]]</div>
|
||||
</template>
|
||||
<div id="root"></div>
|
||||
</div>
|
||||
<paper-fab slot="fab" is-wide$="[[isWide]]" dirty$="[[dirty]]" icon="hass:content-save" title="[[localize('ui.panel.config.automation.editor.save')]]" on-click="saveAutomation"></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
<div class="content">
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">[[errors]]</div>
|
||||
</template>
|
||||
<div id="root"></div>
|
||||
</div>
|
||||
<paper-fab
|
||||
slot="fab"
|
||||
is-wide$="[[isWide]]"
|
||||
dirty$="[[dirty]]"
|
||||
icon="hass:content-save"
|
||||
title="[[localize('ui.panel.config.automation.editor.save')]]"
|
||||
on-click="saveAutomation"
|
||||
></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -23,71 +23,90 @@ import computeStateName from "../../../common/entity/compute_state_name";
|
||||
class HaAutomationPicker extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
ha-markdown p {
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
ha-markdown p {
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="_backTapped"></paper-icon-button>
|
||||
<div main-title="">[[localize('ui.panel.config.automation.caption')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div slot="header">[[localize('ui.panel.config.automation.picker.header')]]</div>
|
||||
<div slot="introduction">
|
||||
<ha-markdown content="[[localize('ui.panel.config.automation.picker.introduction')]]"></ha-markdown>
|
||||
</div>
|
||||
|
||||
<paper-card heading="[[localize('ui.panel.config.automation.picker.pick_automation')]]">
|
||||
<template is="dom-if" if="[[!automations.length]]">
|
||||
<div class="card-content">
|
||||
<p>[[localize('ui.panel.config.automation.picker.no_automations')]]</p>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="_backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">
|
||||
[[localize('ui.panel.config.automation.caption')]]
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[automations]]" as="automation">
|
||||
<paper-item>
|
||||
<paper-item-body two-line="" on-click="automationTapped">
|
||||
<div>[[computeName(automation)]]</div>
|
||||
<div secondary="">[[computeDescription(automation)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<paper-fab slot="fab" is-wide$="[[isWide]]" icon="hass:plus" title="[[localize('ui.panel.config.automation.picker.add_automation')]]" on-click="addAutomation"></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div slot="header">
|
||||
[[localize('ui.panel.config.automation.picker.header')]]
|
||||
</div>
|
||||
<div slot="introduction">
|
||||
<ha-markdown
|
||||
content="[[localize('ui.panel.config.automation.picker.introduction')]]"
|
||||
></ha-markdown>
|
||||
</div>
|
||||
|
||||
<paper-card
|
||||
heading="[[localize('ui.panel.config.automation.picker.pick_automation')]]"
|
||||
>
|
||||
<template is="dom-if" if="[[!automations.length]]">
|
||||
<div class="card-content">
|
||||
<p>
|
||||
[[localize('ui.panel.config.automation.picker.no_automations')]]
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[automations]]" as="automation">
|
||||
<paper-item>
|
||||
<paper-item-body two-line="" on-click="automationTapped">
|
||||
<div>[[computeName(automation)]]</div>
|
||||
<div secondary="">[[computeDescription(automation)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
|
||||
<paper-fab
|
||||
slot="fab"
|
||||
is-wide$="[[isWide]]"
|
||||
icon="hass:plus"
|
||||
title="[[localize('ui.panel.config.automation.picker.add_automation')]]"
|
||||
on-click="addAutomation"
|
||||
></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,23 +10,43 @@ import computeStateDomain from "../../../common/entity/compute_state_domain";
|
||||
class HaConfigAutomation extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
ha-automation-picker,
|
||||
ha-automation-editor {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<app-route route="[[route]]" pattern="/automation/edit/:automation" data="{{_routeData}}" active="{{_edittingAutomation}}"></app-route>
|
||||
<app-route route="[[route]]" pattern="/automation/new" active="{{_creatingNew}}"></app-route>
|
||||
<style>
|
||||
ha-automation-picker,
|
||||
ha-automation-editor {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/automation/edit/:automation"
|
||||
data="{{_routeData}}"
|
||||
active="{{_edittingAutomation}}"
|
||||
></app-route>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/automation/new"
|
||||
active="{{_creatingNew}}"
|
||||
></app-route>
|
||||
|
||||
<template is="dom-if" if="[[!showEditor]]">
|
||||
<ha-automation-picker hass="[[hass]]" narrow="[[narrow]]" show-menu="[[showMenu]]" automations="[[automations]]" is-wide="[[isWide]]"></ha-automation-picker>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!showEditor]]">
|
||||
<ha-automation-picker
|
||||
hass="[[hass]]"
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
automations="[[automations]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-automation-picker>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[showEditor]]" restamp="">
|
||||
<ha-automation-editor hass="[[hass]]" automation="[[automation]]" is-wide="[[isWide]]" creating-new="[[_creatingNew]]"></ha-automation-editor>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[showEditor]]" restamp="">
|
||||
<ha-automation-editor
|
||||
hass="[[hass]]"
|
||||
automation="[[automation]]"
|
||||
is-wide="[[isWide]]"
|
||||
creating-new="[[_creatingNew]]"
|
||||
></ha-automation-editor>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -34,28 +34,36 @@ export class CloudAlexaPref extends LitElement {
|
||||
@change="${this._toggleChanged}"
|
||||
></paper-toggle-button>
|
||||
<div class="card-content">
|
||||
With the Alexa integration for Home Assistant Cloud you'll be able to control all your Home Assistant devices via any Alexa-enabled device.
|
||||
With the Alexa integration for Home Assistant Cloud you'll be able to
|
||||
control all your Home Assistant devices via any Alexa-enabled device.
|
||||
<ul>
|
||||
<li>
|
||||
To activate, search in the Alexa app for the Home Assistant Smart Home skill.
|
||||
To activate, search in the Alexa app for the Home Assistant Smart
|
||||
Home skill.
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.home-assistant.io/cloud/alexa/" target="_blank">
|
||||
<a
|
||||
href="https://www.home-assistant.io/cloud/alexa/"
|
||||
target="_blank"
|
||||
>
|
||||
Config documentation
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<em>This integration requires an Alexa-enabled device like the Amazon Echo.</em>
|
||||
<em
|
||||
>This integration requires an Alexa-enabled device like the Amazon
|
||||
Echo.</em
|
||||
>
|
||||
${
|
||||
enabled
|
||||
? html`
|
||||
<p>Exposed entities:</p>
|
||||
<cloud-exposed-entities
|
||||
.hass="${this.hass}"
|
||||
.filter="${this.cloudStatus!.alexa_entities}"
|
||||
.supportedDomains="${this.cloudStatus!.alexa_domains}"
|
||||
></cloud-exposed-entities>
|
||||
`
|
||||
<p>Exposed entities:</p>
|
||||
<cloud-exposed-entities
|
||||
.hass="${this.hass}"
|
||||
.filter="${this.cloudStatus!.alexa_entities}"
|
||||
.supportedDomains="${this.cloudStatus!.alexa_domains}"
|
||||
></cloud-exposed-entities>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -51,21 +51,21 @@ export class CloudExposedEntities extends LitElement {
|
||||
|
||||
return html`
|
||||
${this.renderStyle()}
|
||||
${repeat(
|
||||
states!,
|
||||
(stateInfo) => stateInfo[1].entity_id,
|
||||
(stateInfo) => html`
|
||||
<span>
|
||||
<ha-state-icon
|
||||
.stateObj='${stateInfo[1]}'
|
||||
@click='${this._handleMoreInfo}'
|
||||
></ha-state-icon>
|
||||
<paper-tooltip
|
||||
position="bottom"
|
||||
>${stateInfo[0]}</paper-tooltip>
|
||||
</span>
|
||||
`
|
||||
)}
|
||||
${
|
||||
repeat(
|
||||
states!,
|
||||
(stateInfo) => stateInfo[1].entity_id,
|
||||
(stateInfo) => html`
|
||||
<span>
|
||||
<ha-state-icon
|
||||
.stateObj="${stateInfo[1]}"
|
||||
@click="${this._handleMoreInfo}"
|
||||
></ha-state-icon>
|
||||
<paper-tooltip position="bottom">${stateInfo[0]}</paper-tooltip>
|
||||
</span>
|
||||
`
|
||||
)
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -35,30 +35,41 @@ export class CloudGooglePref extends LitElement {
|
||||
@change="${this._toggleChanged}"
|
||||
></paper-toggle-button>
|
||||
<div class="card-content">
|
||||
With the Google Assistant integration for Home Assistant Cloud you'll be able to control all your Home Assistant devices via any Google Assistant-enabled device.
|
||||
With the Google Assistant integration for Home Assistant Cloud you'll
|
||||
be able to control all your Home Assistant devices via any Google
|
||||
Assistant-enabled device.
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://assistant.google.com/services/a/uid/00000091fd5fb875" target="_blank">
|
||||
<a
|
||||
href="https://assistant.google.com/services/a/uid/00000091fd5fb875"
|
||||
target="_blank"
|
||||
>
|
||||
Activate the Home Assistant skill for Google Assistant
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.home-assistant.io/cloud/google_assistant/" target="_blank">
|
||||
<a
|
||||
href="https://www.home-assistant.io/cloud/google_assistant/"
|
||||
target="_blank"
|
||||
>
|
||||
Config documentation
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<em>This integration requires a Google Assistant-enabled device like the Google Home or Android phone.</em>
|
||||
<em
|
||||
>This integration requires a Google Assistant-enabled device like
|
||||
the Google Home or Android phone.</em
|
||||
>
|
||||
${
|
||||
enabled
|
||||
? html`
|
||||
<p>Exposed entities:</p>
|
||||
<cloud-exposed-entities
|
||||
.hass="${this.hass}"
|
||||
.filter="${this.cloudStatus!.google_entities}"
|
||||
.supportedDomains="${this.cloudStatus!.google_domains}"
|
||||
></cloud-exposed-entities>
|
||||
`
|
||||
<p>Exposed entities:</p>
|
||||
<cloud-exposed-entities
|
||||
.hass="${this.hass}"
|
||||
.filter="${this.cloudStatus!.google_entities}"
|
||||
.supportedDomains="${this.cloudStatus!.google_domains}"
|
||||
></cloud-exposed-entities>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
@ -67,7 +78,8 @@ export class CloudGooglePref extends LitElement {
|
||||
.hass="${this.hass}"
|
||||
.disabled="${!enabled}"
|
||||
path="cloud/google_actions/sync"
|
||||
>Sync devices</ha-call-api-button>
|
||||
>Sync devices</ha-call-api-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
|
||||
@ -26,104 +26,113 @@ import "./cloud-google-pref";
|
||||
class HaConfigCloudAccount extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
[slot=introduction] {
|
||||
margin: -1em 0;
|
||||
}
|
||||
[slot=introduction] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.content {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.account-row {
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
}
|
||||
paper-button {
|
||||
align-self: center;
|
||||
}
|
||||
.soon {
|
||||
font-style: italic;
|
||||
margin-top: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.nowrap {
|
||||
white-space: nowrap;;
|
||||
}
|
||||
.wrap {
|
||||
white-space: normal;
|
||||
}
|
||||
.status {
|
||||
text-transform: capitalize;
|
||||
padding: 16px;
|
||||
}
|
||||
paper-button {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header="Home Assistant Cloud">
|
||||
<div class="content">
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Home Assistant Cloud</span>
|
||||
<div slot="introduction">
|
||||
<p>
|
||||
Thank you for being part of Home Assistant Cloud. It's because of people like you that we are able to make a great home automation experience for everyone. Thank you!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<paper-card heading="Nabu Casa Account">
|
||||
<div class="account-row">
|
||||
<paper-item-body two-line="">
|
||||
[[cloudStatus.email]]
|
||||
<div secondary="" class="wrap">
|
||||
[[_formatSubscription(_subscription)]]
|
||||
</div>
|
||||
</paper-item-body>
|
||||
<style include="iron-flex ha-style">
|
||||
[slot="introduction"] {
|
||||
margin: -1em 0;
|
||||
}
|
||||
[slot="introduction"] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.content {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.account-row {
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
}
|
||||
paper-button {
|
||||
align-self: center;
|
||||
}
|
||||
.soon {
|
||||
font-style: italic;
|
||||
margin-top: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.wrap {
|
||||
white-space: normal;
|
||||
}
|
||||
.status {
|
||||
text-transform: capitalize;
|
||||
padding: 16px;
|
||||
}
|
||||
paper-button {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header="Home Assistant Cloud">
|
||||
<div class="content">
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Home Assistant Cloud</span>
|
||||
<div slot="introduction">
|
||||
<p>
|
||||
Thank you for being part of Home Assistant Cloud. It's because
|
||||
of people like you that we are able to make a great home
|
||||
automation experience for everyone. Thank you!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="account-row">
|
||||
<paper-item-body>
|
||||
Cloud connection status
|
||||
</paper-item-body>
|
||||
<div class="status">[[cloudStatus.cloud]]</div>
|
||||
<paper-card heading="Nabu Casa Account">
|
||||
<div class="account-row">
|
||||
<paper-item-body two-line="">
|
||||
[[cloudStatus.email]]
|
||||
<div secondary="" class="wrap">
|
||||
[[_formatSubscription(_subscription)]]
|
||||
</div>
|
||||
</paper-item-body>
|
||||
</div>
|
||||
|
||||
<div class="account-row">
|
||||
<paper-item-body> Cloud connection status </paper-item-body>
|
||||
<div class="status">[[cloudStatus.cloud]]</div>
|
||||
</div>
|
||||
|
||||
<div class="card-actions">
|
||||
<a href="https://account.nabucasa.com" target="_blank"
|
||||
><paper-button>Manage Account</paper-button></a
|
||||
>
|
||||
<paper-button style="float: right" on-click="handleLogout"
|
||||
>Sign out</paper-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Integrations</span>
|
||||
<div slot="introduction">
|
||||
<p>
|
||||
Integrations for Home Assistant Cloud allow you to connect with
|
||||
services in the cloud without having to expose your Home
|
||||
Assistant instance publicly on the internet.
|
||||
</p>
|
||||
<p>
|
||||
Check the website for
|
||||
<a href="https://www.nabucasa.com" target="_blank"
|
||||
>all available features</a
|
||||
>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class='card-actions'>
|
||||
<a href='https://account.nabucasa.com' target='_blank'><paper-button>Manage Account</paper-button></a>
|
||||
<paper-button style='float: right' on-click="handleLogout">Sign out</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
<cloud-alexa-pref
|
||||
hass="[[hass]]"
|
||||
cloud-status="[[cloudStatus]]"
|
||||
></cloud-alexa-pref>
|
||||
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Integrations</span>
|
||||
<div slot="introduction">
|
||||
<p>
|
||||
Integrations for Home Assistant Cloud allow you to connect with services in the cloud without having to expose your Home Assistant instance publicly on the internet.
|
||||
</p>
|
||||
<p>
|
||||
Check the website for <a href='https://www.nabucasa.com' target='_blank'>all available features</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<cloud-alexa-pref
|
||||
hass="[[hass]]"
|
||||
cloud-status="[[cloudStatus]]"
|
||||
></cloud-alexa-pref>
|
||||
|
||||
<cloud-google-pref
|
||||
hass="[[hass]]"
|
||||
cloud-status="[[cloudStatus]]"
|
||||
></cloud-google-pref>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
<cloud-google-pref
|
||||
hass="[[hass]]"
|
||||
cloud-status="[[cloudStatus]]"
|
||||
></cloud-google-pref>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,54 +14,67 @@ import EventsMixin from "../../../mixins/events-mixin";
|
||||
class HaConfigCloudForgotPassword extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
margin-top: 24px;
|
||||
}
|
||||
h1 {
|
||||
@apply --paper-font-headline;
|
||||
margin: 0;
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.card-actions a {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header="Forgot Password">
|
||||
<div class="content">
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h1>Forgot your password?</h1>
|
||||
<p>
|
||||
Enter your email address and we will send you a link to reset your password.
|
||||
</p>
|
||||
<div class="error" hidden$="[[!_error]]">[[_error]]</div>
|
||||
<paper-input autofocus="" id="email" label="E-mail" value="{{email}}" type="email" on-keydown="_keyDown" error-message="Invalid email"></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-progress-button on-click="_handleEmailPasswordReset" progress="[[_requestInProgress]]">Send reset email</ha-progress-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
paper-card {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
margin-top: 24px;
|
||||
}
|
||||
h1 {
|
||||
@apply --paper-font-headline;
|
||||
margin: 0;
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.card-actions a {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header="Forgot Password">
|
||||
<div class="content">
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h1>Forgot your password?</h1>
|
||||
<p>
|
||||
Enter your email address and we will send you a link to reset
|
||||
your password.
|
||||
</p>
|
||||
<div class="error" hidden$="[[!_error]]">[[_error]]</div>
|
||||
<paper-input
|
||||
autofocus=""
|
||||
id="email"
|
||||
label="E-mail"
|
||||
value="{{email}}"
|
||||
type="email"
|
||||
on-keydown="_keyDown"
|
||||
error-message="Invalid email"
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-progress-button
|
||||
on-click="_handleEmailPasswordReset"
|
||||
progress="[[_requestInProgress]]"
|
||||
>Send reset email</ha-progress-button
|
||||
>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -23,101 +23,137 @@ import NavigateMixin from "../../../mixins/navigate-mixin";
|
||||
class HaConfigCloudLogin extends NavigateMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
[slot=introduction] {
|
||||
margin: -1em 0;
|
||||
}
|
||||
[slot=introduction] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-card:last-child {
|
||||
margin-top: 24px;
|
||||
}
|
||||
h1 {
|
||||
@apply --paper-font-headline;
|
||||
margin: 0;
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
.flash-msg {
|
||||
padding-right: 44px;
|
||||
}
|
||||
.flash-msg paper-icon-button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header="Cloud Login">
|
||||
<div class="content">
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Home Assistant Cloud</span>
|
||||
<div slot="introduction">
|
||||
<p>
|
||||
Home Assistant Cloud connects your local instance securely to cloud-only services Amazon Alexa and Google Assistant.
|
||||
</p>
|
||||
<p>
|
||||
This service is run by our partner <a href='https://www.nabucasa.com' target='_blank'>Nabu Casa, Inc</a>, a company founded by the founders of Home Assistant and Hass.io.
|
||||
</p>
|
||||
<p>
|
||||
Home Assistant Cloud is a subscription service with a free one month trial. No payment information necessary.
|
||||
</p>
|
||||
<p><a href="https://www.nabucasa.com" target="_blank">Learn more about Home Assistant Cloud</a></p>
|
||||
</div>
|
||||
|
||||
<paper-card hidden$="[[!flashMessage]]">
|
||||
<div class="card-content flash-msg">
|
||||
[[flashMessage]]
|
||||
<paper-icon-button icon="hass:close" on-click="_dismissFlash">Dismiss</paper-icon-button>
|
||||
<paper-ripple id="flashRipple" noink=""></paper-ripple>
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
[slot="introduction"] {
|
||||
margin: -1em 0;
|
||||
}
|
||||
[slot="introduction"] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-card:last-child {
|
||||
margin-top: 24px;
|
||||
}
|
||||
h1 {
|
||||
@apply --paper-font-headline;
|
||||
margin: 0;
|
||||
}
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
.flash-msg {
|
||||
padding-right: 44px;
|
||||
}
|
||||
.flash-msg paper-icon-button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header="Cloud Login">
|
||||
<div class="content">
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Home Assistant Cloud</span>
|
||||
<div slot="introduction">
|
||||
<p>
|
||||
Home Assistant Cloud connects your local instance securely to
|
||||
cloud-only services Amazon Alexa and Google Assistant.
|
||||
</p>
|
||||
<p>
|
||||
This service is run by our partner
|
||||
<a href="https://www.nabucasa.com" target="_blank"
|
||||
>Nabu Casa, Inc</a
|
||||
>, a company founded by the founders of Home Assistant and
|
||||
Hass.io.
|
||||
</p>
|
||||
<p>
|
||||
Home Assistant Cloud is a subscription service with a free one
|
||||
month trial. No payment information necessary.
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://www.nabucasa.com" target="_blank"
|
||||
>Learn more about Home Assistant Cloud</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h1>Sign In</h1>
|
||||
<div class="error" hidden$="[[!_error]]">[[_error]]</div>
|
||||
<paper-input label="Email" id="email" type="email" value="{{email}}" on-keydown="_keyDown" error-message="Invalid email"></paper-input>
|
||||
<paper-input id="password" label="Password" value="{{_password}}" type="password" on-keydown="_keyDown" error-message="Passwords are at least 8 characters"></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-progress-button on-click="_handleLogin" progress="[[_requestInProgress]]">Sign in</ha-progress-button>
|
||||
<button class="link" hidden="[[_requestInProgress]]" on-click="_handleForgotPassword">forgot password?</button>
|
||||
</div>
|
||||
</paper-card>
|
||||
<paper-card hidden$="[[!flashMessage]]">
|
||||
<div class="card-content flash-msg">
|
||||
[[flashMessage]]
|
||||
<paper-icon-button icon="hass:close" on-click="_dismissFlash"
|
||||
>Dismiss</paper-icon-button
|
||||
>
|
||||
<paper-ripple id="flashRipple" noink=""></paper-ripple>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<paper-card>
|
||||
<paper-item on-click="_handleRegister">
|
||||
<paper-item-body two-line="">
|
||||
Start your free 1 month trial
|
||||
<div secondary="">No payment information necessary</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<h1>Sign In</h1>
|
||||
<div class="error" hidden$="[[!_error]]">[[_error]]</div>
|
||||
<paper-input
|
||||
label="Email"
|
||||
id="email"
|
||||
type="email"
|
||||
value="{{email}}"
|
||||
on-keydown="_keyDown"
|
||||
error-message="Invalid email"
|
||||
></paper-input>
|
||||
<paper-input
|
||||
id="password"
|
||||
label="Password"
|
||||
value="{{_password}}"
|
||||
type="password"
|
||||
on-keydown="_keyDown"
|
||||
error-message="Passwords are at least 8 characters"
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-progress-button
|
||||
on-click="_handleLogin"
|
||||
progress="[[_requestInProgress]]"
|
||||
>Sign in</ha-progress-button
|
||||
>
|
||||
<button
|
||||
class="link"
|
||||
hidden="[[_requestInProgress]]"
|
||||
on-click="_handleForgotPassword"
|
||||
>
|
||||
forgot password?
|
||||
</button>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<paper-card>
|
||||
<paper-item on-click="_handleRegister">
|
||||
<paper-item-body two-line="">
|
||||
Start your free 1 month trial
|
||||
<div secondary="">No payment information necessary</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -24,43 +24,64 @@ const NOT_LOGGED_IN_URLS = [
|
||||
class HaConfigCloud extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<app-route route="[[route]]" pattern="/cloud/:page" data="{{_routeData}}" tail="{{_routeTail}}"></app-route>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/cloud/:page"
|
||||
data="{{_routeData}}"
|
||||
tail="{{_routeTail}}"
|
||||
></app-route>
|
||||
|
||||
<template is="dom-if" if="[[_equals(_routeData.page, "account")]]" restamp="">
|
||||
<ha-config-cloud-account
|
||||
hass="[[hass]]"
|
||||
cloud-status="[[cloudStatus]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-cloud-account>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "account")]]"
|
||||
restamp=""
|
||||
>
|
||||
<ha-config-cloud-account
|
||||
hass="[[hass]]"
|
||||
cloud-status="[[cloudStatus]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-cloud-account>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(_routeData.page, "login")]]" restamp="">
|
||||
<ha-config-cloud-login
|
||||
page-name="login"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
email="{{_loginEmail}}"
|
||||
flash-message="{{_flashMessage}}"
|
||||
></ha-config-cloud-login>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "login")]]"
|
||||
restamp=""
|
||||
>
|
||||
<ha-config-cloud-login
|
||||
page-name="login"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
email="{{_loginEmail}}"
|
||||
flash-message="{{_flashMessage}}"
|
||||
></ha-config-cloud-login>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(_routeData.page, "register")]]" restamp="">
|
||||
<ha-config-cloud-register
|
||||
page-name="register"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
email="{{_loginEmail}}"
|
||||
></ha-config-cloud-register>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "register")]]"
|
||||
restamp=""
|
||||
>
|
||||
<ha-config-cloud-register
|
||||
page-name="register"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
email="{{_loginEmail}}"
|
||||
></ha-config-cloud-register>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(_routeData.page, "forgot-password")]]" restamp="">
|
||||
<ha-config-cloud-forgot-password
|
||||
page-name="forgot-password"
|
||||
hass="[[hass]]"
|
||||
email="{{_loginEmail}}"
|
||||
></ha-config-cloud-forgot-password>
|
||||
</template>
|
||||
`;
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "forgot-password")]]"
|
||||
restamp=""
|
||||
>
|
||||
<ha-config-cloud-forgot-password
|
||||
page-name="forgot-password"
|
||||
hass="[[hass]]"
|
||||
email="{{_loginEmail}}"
|
||||
></ha-config-cloud-forgot-password>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -24,31 +24,31 @@ function computeEntityName(hass, entity) {
|
||||
class HaCeEntitiesCard extends LocalizeMixIn(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-card {
|
||||
flex: 1 0 100%;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
paper-icon-item {
|
||||
cursor: pointer;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading='[[heading]]'>
|
||||
<template is='dom-repeat' items='[[entities]]' as='entity'>
|
||||
<paper-icon-item on-click='_openMoreInfo'>
|
||||
<state-badge
|
||||
state-obj="[[_computeStateObj(entity, hass)]]"
|
||||
slot='item-icon'
|
||||
></state-badge>
|
||||
<paper-item-body>
|
||||
<div class='name'>[[_computeEntityName(entity, hass)]]</div>
|
||||
<div class='secondary entity-id'>[[entity.entity_id]]</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
</template>
|
||||
</paper-card>
|
||||
<style>
|
||||
paper-card {
|
||||
flex: 1 0 100%;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
paper-icon-item {
|
||||
cursor: pointer;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="[[heading]]">
|
||||
<template is="dom-repeat" items="[[entities]]" as="entity">
|
||||
<paper-icon-item on-click="_openMoreInfo">
|
||||
<state-badge
|
||||
state-obj="[[_computeStateObj(entity, hass)]]"
|
||||
slot="item-icon"
|
||||
></state-badge>
|
||||
<paper-item-body>
|
||||
<div class="name">[[_computeEntityName(entity, hass)]]</div>
|
||||
<div class="secondary entity-id">[[entity.entity_id]]</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
</template>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -28,96 +28,115 @@ class HaConfigManagerDashboard extends LocalizeMixin(
|
||||
) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
paper-button {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
top: 3px;
|
||||
margin-right: -.57em;
|
||||
}
|
||||
paper-card:last-child {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.config-entry-row {
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
}
|
||||
ha-state-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
.configured a {
|
||||
color: var(--primary-text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<style include="iron-flex ha-style">
|
||||
paper-button {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
top: 3px;
|
||||
margin-right: -0.57em;
|
||||
}
|
||||
paper-card:last-child {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.config-entry-row {
|
||||
display: flex;
|
||||
padding: 0 16px;
|
||||
}
|
||||
ha-state-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
.configured a {
|
||||
color: var(--primary-text-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<hass-subpage header="[[localize('ui.panel.config.integrations.caption')]]">
|
||||
<template is="dom-if" if="[[progress.length]]">
|
||||
<ha-config-section>
|
||||
<span slot="header">[[localize('ui.panel.config.integrations.discovered')]]</span>
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[progress]]">
|
||||
<div class="config-entry-row">
|
||||
<paper-item-body>
|
||||
[[_computeIntegrationTitle(localize, item.handler)]]
|
||||
</paper-item-body>
|
||||
<paper-button
|
||||
on-click="_continueFlow"
|
||||
>[[localize('ui.panel.config.integrations.configure')]]</paper-button>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</template>
|
||||
|
||||
<ha-config-section class='configured'>
|
||||
<span slot="header">[[localize('ui.panel.config.integrations.configured')]]</span>
|
||||
<paper-card>
|
||||
<template is="dom-if" if="[[!entries.length]]">
|
||||
<div class="config-entry-row">
|
||||
<paper-item-body two-line>
|
||||
<div>[[localize('ui.panel.config.integrations.none')]]</div>
|
||||
</paper-item-body>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[entries]]">
|
||||
<a href='/config/integrations/[[item.entry_id]]'>
|
||||
<paper-item>
|
||||
<paper-item-body two-line>
|
||||
<div>[[_computeIntegrationTitle(localize, item.domain)]]: [[item.title]]</div>
|
||||
<div secondary>
|
||||
<template is='dom-repeat' items='[[_computeConfigEntryEntities(hass, item, entities)]]'>
|
||||
<span>
|
||||
<ha-state-icon state-obj='[[item]]' on-click='_handleMoreInfo'></ha-state-icon>
|
||||
<paper-tooltip position="bottom">[[_computeStateName(item)]]</paper-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<hass-subpage
|
||||
header="[[localize('ui.panel.config.integrations.caption')]]"
|
||||
>
|
||||
<template is="dom-if" if="[[progress.length]]">
|
||||
<ha-config-section>
|
||||
<span slot="header"
|
||||
>[[localize('ui.panel.config.integrations.discovered')]]</span
|
||||
>
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[progress]]">
|
||||
<div class="config-entry-row">
|
||||
<paper-item-body>
|
||||
[[_computeIntegrationTitle(localize, item.handler)]]
|
||||
</paper-item-body>
|
||||
<paper-button on-click="_continueFlow"
|
||||
>[[localize('ui.panel.config.integrations.configure')]]</paper-button
|
||||
>
|
||||
</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon='hass:chevron-right'></iron-icon>
|
||||
</paper-item>
|
||||
</a>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
|
||||
<ha-config-section>
|
||||
<span slot="header">[[localize('ui.panel.config.integrations.new')]]</span>
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[handlers]]">
|
||||
<div class="config-entry-row">
|
||||
<paper-item-body>
|
||||
[[_computeIntegrationTitle(localize, item)]]
|
||||
</paper-item-body>
|
||||
<paper-button
|
||||
on-click="_createFlow"
|
||||
>[[localize('ui.panel.config.integrations.configure')]]</paper-button>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</hass-subpage>
|
||||
`;
|
||||
<ha-config-section class="configured">
|
||||
<span slot="header"
|
||||
>[[localize('ui.panel.config.integrations.configured')]]</span
|
||||
>
|
||||
<paper-card>
|
||||
<template is="dom-if" if="[[!entries.length]]">
|
||||
<div class="config-entry-row">
|
||||
<paper-item-body two-line>
|
||||
<div>[[localize('ui.panel.config.integrations.none')]]</div>
|
||||
</paper-item-body>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[entries]]">
|
||||
<a href="/config/integrations/[[item.entry_id]]">
|
||||
<paper-item>
|
||||
<paper-item-body two-line>
|
||||
<div>
|
||||
[[_computeIntegrationTitle(localize, item.domain)]]:
|
||||
[[item.title]]
|
||||
</div>
|
||||
<div secondary>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[_computeConfigEntryEntities(hass, item, entities)]]"
|
||||
>
|
||||
<span>
|
||||
<ha-state-icon
|
||||
state-obj="[[item]]"
|
||||
on-click="_handleMoreInfo"
|
||||
></ha-state-icon>
|
||||
<paper-tooltip position="bottom"
|
||||
>[[_computeStateName(item)]]</paper-tooltip
|
||||
>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</a>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
|
||||
<ha-config-section>
|
||||
<span slot="header"
|
||||
>[[localize('ui.panel.config.integrations.new')]]</span
|
||||
>
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[handlers]]">
|
||||
<div class="config-entry-row">
|
||||
<paper-item-body>
|
||||
[[_computeIntegrationTitle(localize, item)]]
|
||||
</paper-item-body>
|
||||
<paper-button on-click="_createFlow"
|
||||
>[[localize('ui.panel.config.integrations.configure')]]</paper-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,28 +12,33 @@ import compare from "../../../common/string/compare";
|
||||
class HaConfigEntries extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<app-route route="[[route]]" pattern="/integrations/:page" data="{{_routeData}}" tail="{{_routeTail}}"></app-route>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/integrations/:page"
|
||||
data="{{_routeData}}"
|
||||
tail="{{_routeTail}}"
|
||||
></app-route>
|
||||
|
||||
<template is='dom-if' if='[[_configEntry]]'>
|
||||
<ha-config-entry-page
|
||||
hass='[[hass]]'
|
||||
config-entry='[[_configEntry]]'
|
||||
entries='[[_entries]]'
|
||||
entities='[[_entities]]'
|
||||
devices='[[_devices]]'
|
||||
narrow='[[narrow]]'
|
||||
></ha-config-entry-page>
|
||||
</template>
|
||||
<template is='dom-if' if='[[!_configEntry]]'>
|
||||
<ha-config-entries-dashboard
|
||||
hass='[[hass]]'
|
||||
entries='[[_entries]]'
|
||||
entities='[[_entities]]'
|
||||
handlers='[[_handlers]]'
|
||||
progress='[[_progress]]'
|
||||
></ha-config-entries-dashboard>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[_configEntry]]">
|
||||
<ha-config-entry-page
|
||||
hass="[[hass]]"
|
||||
config-entry="[[_configEntry]]"
|
||||
entries="[[_entries]]"
|
||||
entities="[[_entities]]"
|
||||
devices="[[_devices]]"
|
||||
narrow="[[narrow]]"
|
||||
></ha-config-entry-page>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_configEntry]]">
|
||||
<ha-config-entries-dashboard
|
||||
hass="[[hass]]"
|
||||
entries="[[_entries]]"
|
||||
entities="[[_entities]]"
|
||||
handlers="[[_handlers]]"
|
||||
progress="[[_progress]]"
|
||||
></ha-config-entries-dashboard>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,54 +18,59 @@ class HaConfigEntryPage extends NavigateMixin(
|
||||
) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
.content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 4px;
|
||||
justify-content: center;
|
||||
}
|
||||
.card {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 1 0 300px;
|
||||
min-width: 0;
|
||||
max-width: 500px;
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header='[[configEntry.title]]'>
|
||||
<paper-icon-button
|
||||
slot='toolbar-icon'
|
||||
icon='hass:delete'
|
||||
on-click='_removeEntry'
|
||||
></paper-icon-button>
|
||||
<div class='content'>
|
||||
<template is='dom-if' if='[[_computeIsEmpty(_configEntryDevices, _noDeviceEntities)]]'>
|
||||
<p>[[localize('ui.panel.config.integrations.config_entry.no_devices')]]</p>
|
||||
</template>
|
||||
<template is='dom-repeat' items='[[_configEntryDevices]]' as='device'>
|
||||
<ha-device-card
|
||||
class="card"
|
||||
hass='[[hass]]'
|
||||
devices='[[devices]]'
|
||||
device='[[device]]'
|
||||
entities='[[entities]]'
|
||||
narrow='[[narrow]]'
|
||||
></ha-device-card>
|
||||
</template>
|
||||
<template is='dom-if' if='[[_noDeviceEntities.length]]'>
|
||||
<ha-ce-entities-card
|
||||
class="card"
|
||||
heading="[[localize('ui.panel.config.integrations.config_entry.no_device')]]"
|
||||
entities='[[_noDeviceEntities]]'
|
||||
hass='[[hass]]'
|
||||
narrow='[[narrow]]'
|
||||
></ha-ce-entities-card>
|
||||
</template>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
<style>
|
||||
.content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 4px;
|
||||
justify-content: center;
|
||||
}
|
||||
.card {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 1 0 300px;
|
||||
min-width: 0;
|
||||
max-width: 500px;
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
<hass-subpage header="[[configEntry.title]]">
|
||||
<paper-icon-button
|
||||
slot="toolbar-icon"
|
||||
icon="hass:delete"
|
||||
on-click="_removeEntry"
|
||||
></paper-icon-button>
|
||||
<div class="content">
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_computeIsEmpty(_configEntryDevices, _noDeviceEntities)]]"
|
||||
>
|
||||
<p>
|
||||
[[localize('ui.panel.config.integrations.config_entry.no_devices')]]
|
||||
</p>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[_configEntryDevices]]" as="device">
|
||||
<ha-device-card
|
||||
class="card"
|
||||
hass="[[hass]]"
|
||||
devices="[[devices]]"
|
||||
device="[[device]]"
|
||||
entities="[[entities]]"
|
||||
narrow="[[narrow]]"
|
||||
></ha-device-card>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_noDeviceEntities.length]]">
|
||||
<ha-ce-entities-card
|
||||
class="card"
|
||||
heading="[[localize('ui.panel.config.integrations.config_entry.no_device')]]"
|
||||
entities="[[_noDeviceEntities]]"
|
||||
hass="[[hass]]"
|
||||
narrow="[[narrow]]"
|
||||
></ha-ce-entities-card>
|
||||
</template>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -22,99 +22,113 @@ let instance = 0;
|
||||
class HaConfigFlow extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style-dialog">
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
paper-dialog {
|
||||
max-width: 500px;
|
||||
}
|
||||
ha-markdown {
|
||||
word-break: break-word;
|
||||
}
|
||||
ha-markdown a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
ha-markdown img:first-child:last-child {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.init-spinner {
|
||||
padding: 10px 100px 34px;
|
||||
text-align: center;
|
||||
}
|
||||
.submit-spinner {
|
||||
margin-right: 16px;
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" with-backdrop="" opened="{{_opened}}" on-opened-changed="_openedChanged">
|
||||
<h2>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'abort')]]">
|
||||
Aborted
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'create_entry')]]">
|
||||
Success!
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'form')]]">
|
||||
[[_computeStepTitle(localize, _step)]]
|
||||
</template>
|
||||
</h2>
|
||||
<paper-dialog-scrollable>
|
||||
<template is="dom-if" if="[[_errorMsg]]">
|
||||
<div class='error'>[[_errorMsg]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_step]]">
|
||||
<div class='init-spinner'><paper-spinner active></paper-spinner></div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_step]]">
|
||||
<style include="ha-style-dialog">
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
paper-dialog {
|
||||
max-width: 500px;
|
||||
}
|
||||
ha-markdown {
|
||||
word-break: break-word;
|
||||
}
|
||||
ha-markdown a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
ha-markdown img:first-child:last-child {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.init-spinner {
|
||||
padding: 10px 100px 34px;
|
||||
text-align: center;
|
||||
}
|
||||
.submit-spinner {
|
||||
margin-right: 16px;
|
||||
}
|
||||
</style>
|
||||
<paper-dialog
|
||||
id="dialog"
|
||||
with-backdrop=""
|
||||
opened="{{_opened}}"
|
||||
on-opened-changed="_openedChanged"
|
||||
>
|
||||
<h2>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'abort')]]">
|
||||
Aborted
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'create_entry')]]">
|
||||
<p>Created config for [[_step.title]]</p>
|
||||
Success!
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_computeStepDescription(localize, _step)]]">
|
||||
<ha-markdown content="[[_computeStepDescription(localize, _step)]]" allow-svg></ha-markdown>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'form')]]">
|
||||
<ha-form
|
||||
data="{{_stepData}}"
|
||||
on-data-changed='_increaseCounter'
|
||||
schema="[[_step.data_schema]]"
|
||||
error="[[_step.errors]]"
|
||||
compute-label="[[_computeLabelCallback(localize, _step)]]"
|
||||
compute-error="[[_computeErrorCallback(localize, _step)]]"
|
||||
></ha-form>
|
||||
[[_computeStepTitle(localize, _step)]]
|
||||
</template>
|
||||
</template>
|
||||
</paper-dialog-scrollable>
|
||||
<div class="buttons">
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'abort')]]">
|
||||
<paper-button on-click="_flowDone">Close</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'create_entry')]]">
|
||||
<paper-button on-click="_flowDone">Close</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'form')]]">
|
||||
<template is="dom-if" if="[[_loading]]">
|
||||
<div class='submit-spinner'><paper-spinner active></paper-spinner></div>
|
||||
</h2>
|
||||
<paper-dialog-scrollable>
|
||||
<template is="dom-if" if="[[_errorMsg]]">
|
||||
<div class="error">[[_errorMsg]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_loading]]">
|
||||
<div>
|
||||
<paper-button
|
||||
on-click="_submitStep"
|
||||
disabled='[[!_canSubmit]]'
|
||||
>Submit</paper-button>
|
||||
<template is='dom-if' if='[[!_canSubmit]]'>
|
||||
<paper-tooltip position="left">
|
||||
Not all required fields are filled in.
|
||||
</paper-tooltip>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_step]]">
|
||||
<div class="init-spinner">
|
||||
<paper-spinner active></paper-spinner>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
`;
|
||||
<template is="dom-if" if="[[_step]]">
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'create_entry')]]">
|
||||
<p>Created config for [[_step.title]]</p>
|
||||
</template>
|
||||
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_computeStepDescription(localize, _step)]]"
|
||||
>
|
||||
<ha-markdown
|
||||
content="[[_computeStepDescription(localize, _step)]]"
|
||||
allow-svg
|
||||
></ha-markdown>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'form')]]">
|
||||
<ha-form
|
||||
data="{{_stepData}}"
|
||||
on-data-changed="_increaseCounter"
|
||||
schema="[[_step.data_schema]]"
|
||||
error="[[_step.errors]]"
|
||||
compute-label="[[_computeLabelCallback(localize, _step)]]"
|
||||
compute-error="[[_computeErrorCallback(localize, _step)]]"
|
||||
></ha-form>
|
||||
</template>
|
||||
</template>
|
||||
</paper-dialog-scrollable>
|
||||
<div class="buttons">
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'abort')]]">
|
||||
<paper-button on-click="_flowDone">Close</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'create_entry')]]">
|
||||
<paper-button on-click="_flowDone">Close</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_equals(_step.type, 'form')]]">
|
||||
<template is="dom-if" if="[[_loading]]">
|
||||
<div class="submit-spinner">
|
||||
<paper-spinner active></paper-spinner>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_loading]]">
|
||||
<div>
|
||||
<paper-button on-click="_submitStep" disabled="[[!_canSubmit]]"
|
||||
>Submit</paper-button
|
||||
>
|
||||
<template is="dom-if" if="[[!_canSubmit]]">
|
||||
<paper-tooltip position="left">
|
||||
Not all required fields are filled in.
|
||||
</paper-tooltip>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -24,77 +24,86 @@ function computeEntityName(hass, entity) {
|
||||
class HaDeviceCard extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host(:not([narrow])) .device-entities {
|
||||
max-height: 225px;
|
||||
overflow: auto;
|
||||
}
|
||||
paper-card {
|
||||
flex: 1 0 100%;
|
||||
padding-bottom: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
.device {
|
||||
width: 30%;
|
||||
}
|
||||
.device .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.device .model,
|
||||
.device .manuf {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.extra-info {
|
||||
margin-top: 8px;
|
||||
}
|
||||
paper-icon-item {
|
||||
cursor: pointer;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.manuf,
|
||||
.entity-id {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<paper-card heading='[[device.name]]'>
|
||||
<div class='card-content'>
|
||||
<!-- <h1>[[configEntry.title]] ([[_computeIntegrationTitle(localize, configEntry.domain)]])</h1> -->
|
||||
<div class='info'>
|
||||
<div class='model'>[[device.model]]</div>
|
||||
<div class='manuf'>
|
||||
[[localize('ui.panel.config.integrations.config_entry.manuf', 'manufacturer', device.manufacturer)]]
|
||||
<style>
|
||||
:host(:not([narrow])) .device-entities {
|
||||
max-height: 225px;
|
||||
overflow: auto;
|
||||
}
|
||||
paper-card {
|
||||
flex: 1 0 100%;
|
||||
padding-bottom: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
.device {
|
||||
width: 30%;
|
||||
}
|
||||
.device .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.device .model,
|
||||
.device .manuf {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.extra-info {
|
||||
margin-top: 8px;
|
||||
}
|
||||
paper-icon-item {
|
||||
cursor: pointer;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.manuf,
|
||||
.entity-id {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
</style>
|
||||
<paper-card heading="[[device.name]]">
|
||||
<div class="card-content">
|
||||
<!--
|
||||
<h1>[[configEntry.title]] ([[_computeIntegrationTitle(localize, configEntry.domain)]])</h1>
|
||||
-->
|
||||
<div class="info">
|
||||
<div class="model">[[device.model]]</div>
|
||||
<div class="manuf">
|
||||
[[localize('ui.panel.config.integrations.config_entry.manuf',
|
||||
'manufacturer', device.manufacturer)]]
|
||||
</div>
|
||||
</div>
|
||||
<template is="dom-if" if="[[device.hub_device_id]]">
|
||||
<div class="extra-info">
|
||||
[[localize('ui.panel.config.integrations.config_entry.hub')]]
|
||||
<span class="hub"
|
||||
>[[_computeDeviceName(devices, device.hub_device_id)]]</span
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[device.sw_version]]">
|
||||
<div class="extra-info">
|
||||
[[localize('ui.panel.config.integrations.config_entry.firmware',
|
||||
'version', device.sw_version)]]
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<template is='dom-if' if='[[device.hub_device_id]]'>
|
||||
<div class='extra-info'>
|
||||
[[localize('ui.panel.config.integrations.config_entry.hub')]]
|
||||
<span class='hub'>[[_computeDeviceName(devices, device.hub_device_id)]]</span>
|
||||
</div>
|
||||
</template>
|
||||
<template is='dom-if' if='[[device.sw_version]]'>
|
||||
<div class='extra-info'>
|
||||
[[localize('ui.panel.config.integrations.config_entry.firmware', 'version', device.sw_version)]]
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class='device-entities'>
|
||||
<template is='dom-repeat' items='[[_computeDeviceEntities(hass, device, entities)]]' as='entity'>
|
||||
<paper-icon-item on-click='_openMoreInfo'>
|
||||
<state-badge
|
||||
state-obj="[[_computeStateObj(entity, hass)]]"
|
||||
slot='item-icon'
|
||||
></state-badge>
|
||||
<paper-item-body>
|
||||
<div class='name'>[[_computeEntityName(entity, hass)]]</div>
|
||||
<div class='secondary entity-id'>[[entity.entity_id]]</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<div class="device-entities">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[_computeDeviceEntities(hass, device, entities)]]"
|
||||
as="entity"
|
||||
>
|
||||
<paper-icon-item on-click="_openMoreInfo">
|
||||
<state-badge
|
||||
state-obj="[[_computeStateObj(entity, hass)]]"
|
||||
slot="item-icon"
|
||||
></state-badge>
|
||||
<paper-item-body>
|
||||
<div class="name">[[_computeEntityName(entity, hass)]]</div>
|
||||
<div class="secondary entity-id">[[entity.entity_id]]</div>
|
||||
</paper-item-body>
|
||||
</paper-icon-item>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -17,28 +17,31 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class HaConfigCore extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.border {
|
||||
margin: 32px auto 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
max-width: 1040px;
|
||||
}
|
||||
.border {
|
||||
margin: 32px auto 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
max-width: 1040px;
|
||||
}
|
||||
|
||||
.narrow .border {
|
||||
max-width: 640px;
|
||||
}
|
||||
</style>
|
||||
.narrow .border {
|
||||
max-width: 640px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<hass-subpage header="[[localize('ui.panel.config.core.caption')]]">
|
||||
<div class$="[[computeClasses(isWide)]]">
|
||||
<ha-config-section-core is-wide="[[isWide]]" hass="[[hass]]"></ha-config-section-core>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
<hass-subpage header="[[localize('ui.panel.config.core.caption')]]">
|
||||
<div class$="[[computeClasses(isWide)]]">
|
||||
<ha-config-section-core
|
||||
is-wide="[[isWide]]"
|
||||
hass="[[hass]]"
|
||||
></ha-config-section-core>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,104 +18,142 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class HaConfigSectionCore extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.validate-container {
|
||||
@apply --layout-vertical;
|
||||
@apply --layout-center-center;
|
||||
height: 140px;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.validate-container {
|
||||
@apply --layout-vertical;
|
||||
@apply --layout-center-center;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.validate-result {
|
||||
color: var(--google-green-500);
|
||||
font-weight: 500;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.validate-result {
|
||||
color: var(--google-green-500);
|
||||
font-weight: 500;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.config-invalid {
|
||||
margin: 1em 0;
|
||||
}
|
||||
.config-invalid {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.config-invalid .text {
|
||||
color: var(--google-red-500);
|
||||
font-weight: 500;
|
||||
}
|
||||
.config-invalid .text {
|
||||
color: var(--google-red-500);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.config-invalid paper-button {
|
||||
float: right;
|
||||
}
|
||||
.config-invalid paper-button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.validate-log {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">[[localize('ui.panel.config.core.section.core.header')]]</span>
|
||||
<span slot="introduction">[[localize('ui.panel.config.core.section.core.introduction')]]</span>
|
||||
.validate-log {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header"
|
||||
>[[localize('ui.panel.config.core.section.core.header')]]</span
|
||||
>
|
||||
<span slot="introduction"
|
||||
>[[localize('ui.panel.config.core.section.core.introduction')]]</span
|
||||
>
|
||||
|
||||
<paper-card heading="[[localize('ui.panel.config.core.section.core.validation.heading')]]">
|
||||
<div class="card-content">
|
||||
[[localize('ui.panel.config.core.section.core.validation.introduction')]]
|
||||
<template is="dom-if" if="[[!validateLog]]">
|
||||
<div class="validate-container">
|
||||
<template is="dom-if" if="[[!validating]]">
|
||||
<template is="dom-if" if="[[isValid]]">
|
||||
<div class="validate-result" id="result">
|
||||
[[localize('ui.panel.config.core.section.core.validation.valid')]]
|
||||
</div>
|
||||
<paper-card
|
||||
heading="[[localize('ui.panel.config.core.section.core.validation.heading')]]"
|
||||
>
|
||||
<div class="card-content">
|
||||
[[localize('ui.panel.config.core.section.core.validation.introduction')]]
|
||||
<template is="dom-if" if="[[!validateLog]]">
|
||||
<div class="validate-container">
|
||||
<template is="dom-if" if="[[!validating]]">
|
||||
<template is="dom-if" if="[[isValid]]">
|
||||
<div class="validate-result" id="result">
|
||||
[[localize('ui.panel.config.core.section.core.validation.valid')]]
|
||||
</div>
|
||||
</template>
|
||||
<paper-button raised="" on-click="validateConfig">
|
||||
[[localize('ui.panel.config.core.section.core.validation.check_config')]]
|
||||
</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[validating]]">
|
||||
<paper-spinner active=""></paper-spinner>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[validateLog]]">
|
||||
<div class="config-invalid">
|
||||
<span class="text">
|
||||
[[localize('ui.panel.config.core.section.core.validation.invalid')]]
|
||||
</span>
|
||||
<paper-button raised="" on-click="validateConfig">
|
||||
[[localize('ui.panel.config.core.section.core.validation.check_config')]]
|
||||
</paper-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[validating]]">
|
||||
<paper-spinner active=""></paper-spinner>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[validateLog]]">
|
||||
<div class="config-invalid">
|
||||
<span class="text">
|
||||
[[localize('ui.panel.config.core.section.core.validation.invalid')]]
|
||||
</span>
|
||||
<paper-button raised="" on-click="validateConfig">
|
||||
[[localize('ui.panel.config.core.section.core.validation.check_config')]]
|
||||
</paper-button>
|
||||
</div>
|
||||
<div id="configLog" class="validate-log">[[validateLog]]</div>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
<div id="configLog" class="validate-log">[[validateLog]]</div>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<paper-card heading="[[localize('ui.panel.config.core.section.core.reloading.heading')]]">
|
||||
<div class="card-content">
|
||||
[[localize('ui.panel.config.core.section.core.reloading.introduction')]]
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button hass="[[hass]]" domain="homeassistant" service="reload_core_config">[[localize('ui.panel.config.core.section.core.reloading.core')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button hass="[[hass]]" domain="group" service="reload" hidden$="[[!groupLoaded(hass)]]">[[localize('ui.panel.config.core.section.core.reloading.group')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button hass="[[hass]]" domain="automation" service="reload" hidden$="[[!automationLoaded(hass)]]">[[localize('ui.panel.config.core.section.core.reloading.automation')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button hass="[[hass]]" domain="script" service="reload" hidden$="[[!scriptLoaded(hass)]]">[[localize('ui.panel.config.core.section.core.reloading.script')]]
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
<paper-card
|
||||
heading="[[localize('ui.panel.config.core.section.core.reloading.heading')]]"
|
||||
>
|
||||
<div class="card-content">
|
||||
[[localize('ui.panel.config.core.section.core.reloading.introduction')]]
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="homeassistant"
|
||||
service="reload_core_config"
|
||||
>[[localize('ui.panel.config.core.section.core.reloading.core')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="group"
|
||||
service="reload"
|
||||
hidden$="[[!groupLoaded(hass)]]"
|
||||
>[[localize('ui.panel.config.core.section.core.reloading.group')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="automation"
|
||||
service="reload"
|
||||
hidden$="[[!automationLoaded(hass)]]"
|
||||
>[[localize('ui.panel.config.core.section.core.reloading.automation')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="script"
|
||||
service="reload"
|
||||
hidden$="[[!scriptLoaded(hass)]]"
|
||||
>[[localize('ui.panel.config.core.section.core.reloading.script')]]
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
<paper-card heading="[[localize('ui.panel.config.core.section.core.server_management.heading')]]">
|
||||
<div class="card-content">
|
||||
[[localize('ui.panel.config.core.section.core.server_management.introduction')]]
|
||||
</div>
|
||||
<div class="card-actions warning">
|
||||
<ha-call-service-button class="warning" hass="[[hass]]" domain="homeassistant" service="restart">[[localize('ui.panel.config.core.section.core.server_management.restart')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button class="warning" hass="[[hass]]" domain="homeassistant" service="stop">[[localize('ui.panel.config.core.section.core.server_management.stop')]]
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
|
||||
</ha-config-section>
|
||||
`;
|
||||
<paper-card
|
||||
heading="[[localize('ui.panel.config.core.section.core.server_management.heading')]]"
|
||||
>
|
||||
<div class="card-content">
|
||||
[[localize('ui.panel.config.core.section.core.server_management.introduction')]]
|
||||
</div>
|
||||
<div class="card-actions warning">
|
||||
<ha-call-service-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
domain="homeassistant"
|
||||
service="restart"
|
||||
>[[localize('ui.panel.config.core.section.core.server_management.restart')]]
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button
|
||||
class="warning"
|
||||
hass="[[hass]]"
|
||||
domain="homeassistant"
|
||||
service="stop"
|
||||
>[[localize('ui.panel.config.core.section.core.server_management.stop')]]
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -22,30 +22,40 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class HaConfigCustomize extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
</style>
|
||||
<style include="ha-style"></style>
|
||||
|
||||
<app-header-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="_backTapped"></paper-icon-button>
|
||||
<div main-title="">[[localize('ui.panel.config.customize.caption')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<app-header-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="_backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">
|
||||
[[localize('ui.panel.config.customize.caption')]]
|
||||
</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<div class$="[[computeClasses(isWide)]]">
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Customization</span>
|
||||
<span slot="introduction">
|
||||
Tweak per-entity attributes.<br>
|
||||
Added/edited customizations will take effect immediately. Removed customizations will take effect when the entity is updated.
|
||||
</span>
|
||||
<ha-entity-config hass="[[hass]]" label="Entity" entities="[[entities]]" config="[[entityConfig]]">
|
||||
</ha-entity-config>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
`;
|
||||
<div class$="[[computeClasses(isWide)]]">
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<span slot="header">Customization</span>
|
||||
<span slot="introduction">
|
||||
Tweak per-entity attributes.<br />
|
||||
Added/edited customizations will take effect immediately. Removed
|
||||
customizations will take effect when the entity is updated.
|
||||
</span>
|
||||
<ha-entity-config
|
||||
hass="[[hass]]"
|
||||
label="Entity"
|
||||
entities="[[entities]]"
|
||||
config="[[entityConfig]]"
|
||||
>
|
||||
</ha-entity-config>
|
||||
</ha-config-section>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -13,23 +13,27 @@ import "./types/ha-customize-string";
|
||||
class HaCustomizeAttribute extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-form-style">
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-right: 40px;
|
||||
}
|
||||
<style include="ha-form-style">
|
||||
:host {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
.button {
|
||||
position: absolute;
|
||||
margin-top: -20px;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
<div id="wrapper" class="form-group"></div>
|
||||
<paper-icon-button class="button" icon="[[getIcon(item.secondary)]]" on-click="tapButton"></paper-icon-button>
|
||||
`;
|
||||
.button {
|
||||
position: absolute;
|
||||
margin-top: -20px;
|
||||
top: 50%;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
<div id="wrapper" class="form-group"></div>
|
||||
<paper-icon-button
|
||||
class="button"
|
||||
icon="[[getIcon(item.secondary)]]"
|
||||
on-click="tapButton"
|
||||
></paper-icon-button>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -7,16 +7,16 @@ import "./ha-customize-attribute";
|
||||
class HaFormCustomizeAttributes extends MutableData(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-repeat" items="{{attributes}}" mutable-data="">
|
||||
<ha-customize-attribute item="{{item}}" hidden$="[[item.closed]]">
|
||||
</ha-customize-attribute>
|
||||
</template>
|
||||
`;
|
||||
<style>
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-repeat" items="{{attributes}}" mutable-data="">
|
||||
<ha-customize-attribute item="{{item}}" hidden$="[[item.closed]]">
|
||||
</ha-customize-attribute>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,57 +12,81 @@ import computeStateDomain from "../../../common/entity/compute_state_domain";
|
||||
class HaFormCustomize extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style ha-form-style">
|
||||
.warning {
|
||||
color: red;
|
||||
}
|
||||
<style include="iron-flex ha-style ha-form-style">
|
||||
.warning {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.attributes-text {
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[computeShowWarning(localConfig, globalConfig)]]">
|
||||
<div class="warning">
|
||||
It seems that your configuration.yaml doesn't properly include customize.yaml<br>
|
||||
Changes made here won't affect your configuration.
|
||||
.attributes-text {
|
||||
padding-left: 20px;
|
||||
}
|
||||
</style>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[computeShowWarning(localConfig, globalConfig)]]"
|
||||
>
|
||||
<div class="warning">
|
||||
It seems that your configuration.yaml doesn't properly include
|
||||
customize.yaml<br />
|
||||
Changes made here won't affect your configuration.
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasLocalAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes are already set in customize.yaml<br />
|
||||
</h4>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{localAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasGlobalAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes are customized from outside of
|
||||
customize.yaml<br />
|
||||
Possibly via a domain, a glob or a different include.
|
||||
</h4>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{globalAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasExistingAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes of the entity are set programatically.<br />
|
||||
You can override them if you like.
|
||||
</h4>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{existingAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasNewAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes weren't set. Set them if you like.
|
||||
</h4>
|
||||
<ha-form-customize-attributes
|
||||
attributes="{{newAttributes}}"
|
||||
></ha-form-customize-attributes>
|
||||
</template>
|
||||
<div class="form-group">
|
||||
<paper-dropdown-menu
|
||||
label="Pick an attribute to override"
|
||||
class="flex"
|
||||
dynamic-align=""
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{selectedNewAttribute}}"
|
||||
>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[newAttributesOptions]]"
|
||||
as="option"
|
||||
>
|
||||
<paper-item>[[option]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasLocalAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes are already set in customize.yaml<br>
|
||||
</h4>
|
||||
<ha-form-customize-attributes attributes="{{localAttributes}}"></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasGlobalAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes are customized from outside of customize.yaml<br>
|
||||
Possibly via a domain, a glob or a different include.
|
||||
</h4>
|
||||
<ha-form-customize-attributes attributes="{{globalAttributes}}"></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasExistingAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes of the entity are set programatically.<br>
|
||||
You can override them if you like.
|
||||
</h4>
|
||||
<ha-form-customize-attributes attributes="{{existingAttributes}}"></ha-form-customize-attributes>
|
||||
</template>
|
||||
<template is="dom-if" if="[[hasNewAttributes]]">
|
||||
<h4 class="attributes-text">
|
||||
The following attributes weren't set. Set them if you like.
|
||||
</h4>
|
||||
<ha-form-customize-attributes attributes="{{newAttributes}}"></ha-form-customize-attributes>
|
||||
</template>
|
||||
<div class="form-group">
|
||||
<paper-dropdown-menu label="Pick an attribute to override" class="flex" dynamic-align="">
|
||||
<paper-listbox slot="dropdown-content" selected="{{selectedNewAttribute}}">
|
||||
<template is="dom-repeat" items="[[newAttributesOptions]]" as="option">
|
||||
<paper-item>[[option]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,19 +12,27 @@ import EventsMixin from "../../../../mixins/events-mixin";
|
||||
class HaCustomizeArray extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-dropdown-menu {
|
||||
margin: -9px 0;
|
||||
}
|
||||
</style>
|
||||
<paper-dropdown-menu label="[[item.description]]" disabled="[[item.secondary]]" selected-item-label="{{item.value}}" dynamic-align="">
|
||||
<paper-listbox slot="dropdown-content" selected="[[computeSelected(item)]]">
|
||||
<template is="dom-repeat" items="[[getOptions(item)]]" as="option">
|
||||
<paper-item>[[option]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
`;
|
||||
<style>
|
||||
paper-dropdown-menu {
|
||||
margin: -9px 0;
|
||||
}
|
||||
</style>
|
||||
<paper-dropdown-menu
|
||||
label="[[item.description]]"
|
||||
disabled="[[item.secondary]]"
|
||||
selected-item-label="{{item.value}}"
|
||||
dynamic-align=""
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="[[computeSelected(item)]]"
|
||||
>
|
||||
<template is="dom-repeat" items="[[getOptions(item)]]" as="option">
|
||||
<paper-item>[[option]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -5,10 +5,10 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HaCustomizeBoolean extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<paper-checkbox disabled="[[item.secondary]]" checked="{{item.value}}">
|
||||
[[item.description]]
|
||||
</paper-checkbox>
|
||||
`;
|
||||
<paper-checkbox disabled="[[item.secondary]]" checked="{{item.value}}">
|
||||
[[item.description]]
|
||||
</paper-checkbox>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,21 +6,25 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HaCustomizeIcon extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
@apply --layout-horizontal;
|
||||
}
|
||||
.icon-image {
|
||||
border: 1px solid grey;
|
||||
padding: 8px;
|
||||
margin-right: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
<iron-icon class="icon-image" icon="[[item.value]]"></iron-icon>
|
||||
<paper-input disabled="[[item.secondary]]" label="icon" value="{{item.value}}">
|
||||
</paper-input>
|
||||
`;
|
||||
<style>
|
||||
:host {
|
||||
@apply --layout-horizontal;
|
||||
}
|
||||
.icon-image {
|
||||
border: 1px solid grey;
|
||||
padding: 8px;
|
||||
margin-right: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
<iron-icon class="icon-image" icon="[[item.value]]"></iron-icon>
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
label="icon"
|
||||
value="{{item.value}}"
|
||||
>
|
||||
</paper-input>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -5,22 +5,31 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HaCustomizeKeyValue extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
@apply --layout-horizontal;
|
||||
}
|
||||
paper-input {
|
||||
@apply --layout-flex;
|
||||
}
|
||||
.key {
|
||||
padding-right: 20px;
|
||||
}
|
||||
</style>
|
||||
<paper-input disabled="[[item.secondary]]" class="key" label="Attribute name" value="{{item.attribute}}">
|
||||
</paper-input>
|
||||
<paper-input disabled="[[item.secondary]]" label="Attribute value" value="{{item.value}}">
|
||||
</paper-input>
|
||||
`;
|
||||
<style>
|
||||
:host {
|
||||
@apply --layout-horizontal;
|
||||
}
|
||||
paper-input {
|
||||
@apply --layout-flex;
|
||||
}
|
||||
.key {
|
||||
padding-right: 20px;
|
||||
}
|
||||
</style>
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
class="key"
|
||||
label="Attribute name"
|
||||
value="{{item.attribute}}"
|
||||
>
|
||||
</paper-input>
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
label="Attribute value"
|
||||
value="{{item.value}}"
|
||||
>
|
||||
</paper-input>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -5,9 +5,13 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
class HaCustomizeString extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<paper-input disabled="[[item.secondary]]" label="[[getLabel(item)]]" value="{{item.value}}">
|
||||
</paper-input>
|
||||
`;
|
||||
<paper-input
|
||||
disabled="[[item.secondary]]"
|
||||
label="[[getLabel(item)]]"
|
||||
value="{{item.value}}"
|
||||
>
|
||||
</paper-input>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,28 +18,28 @@ const CORE_PAGES = ["core", "customize"];
|
||||
class HaConfigNavigation extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[pages]]">
|
||||
<template is="dom-if" if="[[_computeLoaded(hass, item)]]">
|
||||
<paper-item on-click="_navigate">
|
||||
<paper-item-body two-line="">
|
||||
[[_computeCaption(item, localize)]]
|
||||
<div secondary="">[[_computeDescription(item, localize)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
</template>
|
||||
</paper-card>
|
||||
`;
|
||||
<style include="iron-flex">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[pages]]">
|
||||
<template is="dom-if" if="[[_computeLoaded(hass, item)]]">
|
||||
<paper-item on-click="_navigate">
|
||||
<paper-item-body two-line="">
|
||||
[[_computeCaption(item, localize)]]
|
||||
<div secondary="">[[_computeDescription(item, localize)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
</template>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -6,67 +6,63 @@ import "../../resources/ha-style";
|
||||
class HaConfigSection extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding: 28px 20px 0;
|
||||
max-width: 1040px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding: 28px 20px 0;
|
||||
max-width: 1040px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply --paper-font-display1;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-display1;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
|
||||
.together {
|
||||
margin-top: 32px;
|
||||
}
|
||||
.together {
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.intro {
|
||||
@apply --paper-font-subhead;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin-right: 40px;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
.intro {
|
||||
@apply --paper-font-subhead;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
margin-right: 40px;
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
|
||||
.panel {
|
||||
margin-top: -24px;
|
||||
}
|
||||
.panel {
|
||||
margin-top: -24px;
|
||||
}
|
||||
|
||||
.panel ::slotted(*) {
|
||||
margin-top: 24px;
|
||||
display: block;
|
||||
}
|
||||
.panel ::slotted(*) {
|
||||
margin-top: 24px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.narrow.content {
|
||||
max-width: 640px;
|
||||
}
|
||||
.narrow .together {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.narrow .header {
|
||||
@apply --paper-font-headline;
|
||||
}
|
||||
.narrow .intro {
|
||||
font-size: 14px;
|
||||
padding-bottom: 20px;
|
||||
margin-right: 0;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<div class$="[[computeContentClasses(isWide)]]">
|
||||
<div class="header"><slot name="header"></slot></div>
|
||||
<div class$="[[computeClasses(isWide)]]">
|
||||
<div class="intro">
|
||||
<slot name="introduction"></slot>
|
||||
</div>
|
||||
<div class="panel flex-auto">
|
||||
<slot></slot>
|
||||
.narrow.content {
|
||||
max-width: 640px;
|
||||
}
|
||||
.narrow .together {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.narrow .header {
|
||||
@apply --paper-font-headline;
|
||||
}
|
||||
.narrow .intro {
|
||||
font-size: 14px;
|
||||
padding-bottom: 20px;
|
||||
margin-right: 0;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<div class$="[[computeContentClasses(isWide)]]">
|
||||
<div class="header"><slot name="header"></slot></div>
|
||||
<div class$="[[computeClasses(isWide)]]">
|
||||
<div class="intro"><slot name="introduction"></slot></div>
|
||||
<div class="panel flex-auto"><slot></slot></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,68 +12,84 @@ import computeStateName from "../../common/entity/compute_state_name";
|
||||
class HaEntityConfig extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.form-placeholder {
|
||||
@apply --layout-vertical;
|
||||
@apply --layout-center-center;
|
||||
height: 96px;
|
||||
}
|
||||
.form-placeholder {
|
||||
@apply --layout-vertical;
|
||||
@apply --layout-center-center;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
[hidden]: {
|
||||
display: none;
|
||||
}
|
||||
[hidden]: {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="[[label]]" class="flex" disabled="[[!entities.length]]">
|
||||
<paper-listbox slot="dropdown-content" selected="{{selectedEntity}}">
|
||||
<template is="dom-repeat" items="[[entities]]" as="state">
|
||||
<paper-item>[[computeSelectCaption(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
.card-actions {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-justified;
|
||||
}
|
||||
</style>
|
||||
<paper-card>
|
||||
<div class="card-content">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu
|
||||
label="[[label]]"
|
||||
class="flex"
|
||||
disabled="[[!entities.length]]"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{selectedEntity}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[entities]]" as="state">
|
||||
<paper-item>[[computeSelectCaption(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<template is="dom-if" if="[[computeShowPlaceholder(formState)]]">
|
||||
<div class="form-placeholder">
|
||||
<template is="dom-if" if="[[computeShowNoDevices(formState)]]">
|
||||
No entities found! :-(
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[computeShowSpinner(formState)]]">
|
||||
<paper-spinner active="" alt="[[formState]]"></paper-spinner>
|
||||
[[formState]]
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div hidden$="[[!computeShowForm(formState)]]" id="form"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
<template is="dom-if" if="[[computeShowPlaceholder(formState)]]">
|
||||
<div class="form-placeholder">
|
||||
<template is="dom-if" if="[[computeShowNoDevices(formState)]]">
|
||||
No entities found! :-(
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[computeShowSpinner(formState)]]">
|
||||
<paper-spinner active="" alt="[[formState]]"></paper-spinner>
|
||||
[[formState]]
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button
|
||||
on-click="saveEntity"
|
||||
disabled="[[computeShowPlaceholder(formState)]]"
|
||||
>SAVE</paper-button
|
||||
>
|
||||
<template is="dom-if" if="[[allowDelete]]">
|
||||
<paper-button
|
||||
class="warning"
|
||||
on-click="deleteEntity"
|
||||
disabled="[[computeShowPlaceholder(formState)]]"
|
||||
>DELETE</paper-button
|
||||
>
|
||||
</template>
|
||||
|
||||
<div hidden$="[[!computeShowForm(formState)]]" id="form"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="saveEntity" disabled="[[computeShowPlaceholder(formState)]]">SAVE</paper-button>
|
||||
<template is="dom-if" if="[[allowDelete]]">
|
||||
<paper-button class="warning" on-click="deleteEntity" disabled="[[computeShowPlaceholder(formState)]]">DELETE</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -26,97 +26,135 @@ import(/* webpackChunkName: "panel-config-zwave" */ "./zwave/ha-config-zwave");
|
||||
class HaPanelConfig extends EventsMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<app-route
|
||||
route='[[route]]'
|
||||
pattern='/:page'
|
||||
data="{{_routeData}}"
|
||||
></app-route>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/:page"
|
||||
data="{{_routeData}}"
|
||||
></app-route>
|
||||
|
||||
<iron-media-query query="(min-width: 1040px)" query-matches="{{wide}}">
|
||||
</iron-media-query>
|
||||
<iron-media-query query="(min-width: 1296px)" query-matches="{{wideSidebar}}">
|
||||
</iron-media-query>
|
||||
<iron-media-query query="(min-width: 1040px)" query-matches="{{wide}}">
|
||||
</iron-media-query>
|
||||
<iron-media-query
|
||||
query="(min-width: 1296px)"
|
||||
query-matches="{{wideSidebar}}"
|
||||
>
|
||||
</iron-media-query>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "core")]]' restamp>
|
||||
<ha-config-core
|
||||
page-name='core'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-core>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "core")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-core
|
||||
page-name="core"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-core>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "cloud")]]' restamp>
|
||||
<ha-config-cloud
|
||||
page-name='cloud'
|
||||
route='[[route]]'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
cloud-status='[[_cloudStatus]]'
|
||||
></ha-config-cloud>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "cloud")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-cloud
|
||||
page-name="cloud"
|
||||
route="[[route]]"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
cloud-status="[[_cloudStatus]]"
|
||||
></ha-config-cloud>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "dashboard")]]'>
|
||||
<ha-config-dashboard
|
||||
page-name='dashboard'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
cloud-status='[[_cloudStatus]]'
|
||||
narrow='[[narrow]]'
|
||||
show-menu='[[showMenu]]'
|
||||
></ha-config-dashboard>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "dashboard")]]"
|
||||
>
|
||||
<ha-config-dashboard
|
||||
page-name="dashboard"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
cloud-status="[[_cloudStatus]]"
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-config-dashboard>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "automation")]]' restamp>
|
||||
<ha-config-automation
|
||||
page-name='automation'
|
||||
route='[[route]]'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-automation>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "automation")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-automation
|
||||
page-name="automation"
|
||||
route="[[route]]"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-automation>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "script")]]' restamp>
|
||||
<ha-config-script
|
||||
page-name='script'
|
||||
route='[[route]]'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-script>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "script")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-script
|
||||
page-name="script"
|
||||
route="[[route]]"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-script>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "zwave")]]' restamp>
|
||||
<ha-config-zwave
|
||||
page-name='zwave'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-zwave>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "zwave")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-zwave
|
||||
page-name="zwave"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-zwave>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "customize")]]' restamp>
|
||||
<ha-config-customize
|
||||
page-name='customize'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
></ha-config-customize>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "customize")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-customize
|
||||
page-name="customize"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-config-customize>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "integrations")]]' restamp>
|
||||
<ha-config-entries
|
||||
route='[[route]]'
|
||||
page-name='integrations'
|
||||
hass='[[hass]]'
|
||||
is-wide='[[isWide]]'
|
||||
narrow='[[narrow]]'
|
||||
></ha-config-entries>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "integrations")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-entries
|
||||
route="[[route]]"
|
||||
page-name="integrations"
|
||||
hass="[[hass]]"
|
||||
is-wide="[[isWide]]"
|
||||
narrow="[[narrow]]"
|
||||
></ha-config-entries>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if='[[_equals(_routeData.page, "users")]]' restamp>
|
||||
<ha-config-users
|
||||
page-name='users'
|
||||
route='[[route]]'
|
||||
hass='[[hass]]'
|
||||
></ha-config-users>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.page, "users")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-config-users
|
||||
page-name="users"
|
||||
route="[[route]]"
|
||||
hass="[[hass]]"
|
||||
></ha-config-users>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -11,23 +11,43 @@ import computeStateDomain from "../../../common/entity/compute_state_domain";
|
||||
class HaConfigScript extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
ha-script-picker,
|
||||
ha-script-editor {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<app-route route="[[route]]" pattern="/script/edit/:script" data="{{_routeData}}" active="{{_edittingScript}}"></app-route>
|
||||
<app-route route="[[route]]" pattern="/script/new" active="{{_creatingNew}}"></app-route>
|
||||
<style>
|
||||
ha-script-picker,
|
||||
ha-script-editor {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/script/edit/:script"
|
||||
data="{{_routeData}}"
|
||||
active="{{_edittingScript}}"
|
||||
></app-route>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/script/new"
|
||||
active="{{_creatingNew}}"
|
||||
></app-route>
|
||||
|
||||
<template is="dom-if" if="[[!showEditor]]">
|
||||
<ha-script-picker hass="[[hass]]" narrow="[[narrow]]" show-menu="[[showMenu]]" scripts="[[scripts]]" is-wide="[[isWide]]"></ha-script-picker>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!showEditor]]">
|
||||
<ha-script-picker
|
||||
hass="[[hass]]"
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
scripts="[[scripts]]"
|
||||
is-wide="[[isWide]]"
|
||||
></ha-script-picker>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[showEditor]]" restamp="">
|
||||
<ha-script-editor hass="[[hass]]" script="[[script]]" is-wide="[[isWide]]" creating-new="[[_creatingNew]]"></ha-script-editor>
|
||||
</template>
|
||||
`;
|
||||
<template is="dom-if" if="[[showEditor]]" restamp="">
|
||||
<ha-script-editor
|
||||
hass="[[hass]]"
|
||||
script="[[script]]"
|
||||
is-wide="[[isWide]]"
|
||||
creating-new="[[_creatingNew]]"
|
||||
></ha-script-editor>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -27,77 +27,87 @@ function ScriptEditor(mountEl, props, mergeEl) {
|
||||
class HaScriptEditor extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
.errors {
|
||||
padding: 20px;
|
||||
font-weight: bold;
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.triggers,
|
||||
.script {
|
||||
margin-top: -16px;
|
||||
}
|
||||
.triggers paper-card,
|
||||
.script paper-card {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.add-card paper-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.card-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.card-menu paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
span[slot=introduction] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
margin-bottom: -80px;
|
||||
transition: margin-bottom .3s;
|
||||
}
|
||||
<style include="ha-style">
|
||||
.errors {
|
||||
padding: 20px;
|
||||
font-weight: bold;
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
.triggers,
|
||||
.script {
|
||||
margin-top: -16px;
|
||||
}
|
||||
.triggers paper-card,
|
||||
.script paper-card {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.add-card paper-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.card-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.card-menu paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
span[slot="introduction"] a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
margin-bottom: -80px;
|
||||
transition: margin-bottom 0.3s;
|
||||
}
|
||||
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
paper-fab[dirty] {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="backTapped"></paper-icon-button>
|
||||
<div main-title="">Script [[computeName(script)]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<div class="content">
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">[[errors]]</div>
|
||||
</template>
|
||||
<div id="root"></div>
|
||||
</div>
|
||||
<paper-fab slot="fab" is-wide$="[[isWide]]" dirty$="[[dirty]]" icon="hass:content-save" title="Save" on-click="saveScript"></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
paper-fab[dirty] {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">Script [[computeName(script)]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<div class="content">
|
||||
<template is="dom-if" if="[[errors]]">
|
||||
<div class="errors">[[errors]]</div>
|
||||
</template>
|
||||
<div id="root"></div>
|
||||
</div>
|
||||
<paper-fab
|
||||
slot="fab"
|
||||
is-wide$="[[isWide]]"
|
||||
dirty$="[[dirty]]"
|
||||
icon="hass:content-save"
|
||||
title="Save"
|
||||
on-click="saveScript"
|
||||
></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -23,68 +23,84 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class HaScriptPicker extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="_backTapped"></paper-icon-button>
|
||||
<div main-title="">[[localize('ui.panel.config.script.caption')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div slot="header">Script Editor</div>
|
||||
<div slot="introduction">
|
||||
The script editor allows you to create and edit scripts.
|
||||
Please read <a href="https://home-assistant.io/docs/scripts/editor/" target="_blank">the instructions</a> to make sure that you have configured Home Assistant correctly.
|
||||
</div>
|
||||
|
||||
<paper-card heading="Pick script to edit">
|
||||
<template is="dom-if" if="[[!scripts.length]]">
|
||||
<div class="card-content">
|
||||
<p>We couldn't find any editable scripts.</p>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="_backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">
|
||||
[[localize('ui.panel.config.script.caption')]]
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[scripts]]" as="script">
|
||||
<paper-item>
|
||||
<paper-item-body two-line="" on-click="scriptTapped">
|
||||
<div>[[computeName(script)]]</div>
|
||||
<div secondary="">[[computeDescription(script)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<paper-fab slot="fab" is-wide$="[[isWide]]" icon="hass:plus" title="Add Script" on-click="addScript"></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div slot="header">Script Editor</div>
|
||||
<div slot="introduction">
|
||||
The script editor allows you to create and edit scripts. Please read
|
||||
<a
|
||||
href="https://home-assistant.io/docs/scripts/editor/"
|
||||
target="_blank"
|
||||
>the instructions</a
|
||||
>
|
||||
to make sure that you have configured Home Assistant correctly.
|
||||
</div>
|
||||
|
||||
<paper-card heading="Pick script to edit">
|
||||
<template is="dom-if" if="[[!scripts.length]]">
|
||||
<div class="card-content">
|
||||
<p>We couldn't find any editable scripts.</p>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[scripts]]" as="script">
|
||||
<paper-item>
|
||||
<paper-item-body two-line="" on-click="scriptTapped">
|
||||
<div>[[computeName(script)]]</div>
|
||||
<div secondary="">[[computeDescription(script)]]</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</template>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
|
||||
<paper-fab
|
||||
slot="fab"
|
||||
is-wide$="[[isWide]]"
|
||||
icon="hass:plus"
|
||||
title="Add Script"
|
||||
on-click="addScript"
|
||||
></paper-fab>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -16,25 +16,29 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
||||
class HaConfigUsers extends NavigateMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<app-route
|
||||
route='[[route]]'
|
||||
pattern='/users/:user'
|
||||
data="{{_routeData}}"
|
||||
></app-route>
|
||||
<app-route
|
||||
route="[[route]]"
|
||||
pattern="/users/:user"
|
||||
data="{{_routeData}}"
|
||||
></app-route>
|
||||
|
||||
<template is='dom-if' if='[[_equals(_routeData.user, "picker")]]'>
|
||||
<ha-user-picker
|
||||
hass='[[hass]]'
|
||||
users='[[_users]]'
|
||||
></ha-user-picker>
|
||||
</template>
|
||||
<template is='dom-if' if='[[!_equals(_routeData.user, "picker")]]' restamp>
|
||||
<ha-user-editor
|
||||
hass='[[hass]]'
|
||||
user='[[_computeUser(_users, _routeData.user)]]'
|
||||
></ha-user-editor>
|
||||
</template>
|
||||
`;
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_equals(_routeData.user, "picker")]]"
|
||||
>
|
||||
<ha-user-picker hass="[[hass]]" users="[[_users]]"></ha-user-picker>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[!_equals(_routeData.user, "picker")]]"
|
||||
restamp
|
||||
>
|
||||
<ha-user-editor
|
||||
hass="[[hass]]"
|
||||
user="[[_computeUser(_users, _routeData.user)]]"
|
||||
></ha-user-editor>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -14,61 +14,68 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class HaDialogAddUser extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style-dialog">
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
paper-dialog {
|
||||
max-width: 500px;
|
||||
}
|
||||
.username {
|
||||
margin-top: -8px;
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" with-backdrop opened="{{_opened}}" on-opened-changed="_openedChanged">
|
||||
<h2>Add user</h2>
|
||||
<div>
|
||||
<template is="dom-if" if="[[_errorMsg]]">
|
||||
<div class='error'>[[_errorMsg]]</div>
|
||||
</template>
|
||||
<paper-input
|
||||
class='name'
|
||||
label='Name'
|
||||
value='{{_name}}'
|
||||
required
|
||||
auto-validate
|
||||
autocapitalize='on'
|
||||
error-message='Required'
|
||||
on-blur='_maybePopulateUsername'
|
||||
></paper-input>
|
||||
<paper-input
|
||||
class='username'
|
||||
label='Username'
|
||||
value='{{_username}}'
|
||||
required
|
||||
auto-validate
|
||||
autocapitalize='none'
|
||||
error-message='Required'
|
||||
></paper-input>
|
||||
<paper-input
|
||||
label='Password'
|
||||
type='password'
|
||||
value='{{_password}}'
|
||||
required
|
||||
auto-validate
|
||||
error-message='Required'
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<template is="dom-if" if="[[_loading]]">
|
||||
<div class='submit-spinner'><paper-spinner active></paper-spinner></div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_loading]]">
|
||||
<paper-button on-click="_createUser">Create</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
`;
|
||||
<style include="ha-style-dialog">
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
paper-dialog {
|
||||
max-width: 500px;
|
||||
}
|
||||
.username {
|
||||
margin-top: -8px;
|
||||
}
|
||||
</style>
|
||||
<paper-dialog
|
||||
id="dialog"
|
||||
with-backdrop
|
||||
opened="{{_opened}}"
|
||||
on-opened-changed="_openedChanged"
|
||||
>
|
||||
<h2>Add user</h2>
|
||||
<div>
|
||||
<template is="dom-if" if="[[_errorMsg]]">
|
||||
<div class="error">[[_errorMsg]]</div>
|
||||
</template>
|
||||
<paper-input
|
||||
class="name"
|
||||
label="Name"
|
||||
value="{{_name}}"
|
||||
required
|
||||
auto-validate
|
||||
autocapitalize="on"
|
||||
error-message="Required"
|
||||
on-blur="_maybePopulateUsername"
|
||||
></paper-input>
|
||||
<paper-input
|
||||
class="username"
|
||||
label="Username"
|
||||
value="{{_username}}"
|
||||
required
|
||||
auto-validate
|
||||
autocapitalize="none"
|
||||
error-message="Required"
|
||||
></paper-input>
|
||||
<paper-input
|
||||
label="Password"
|
||||
type="password"
|
||||
value="{{_password}}"
|
||||
required
|
||||
auto-validate
|
||||
error-message="Required"
|
||||
></paper-input>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<template is="dom-if" if="[[_loading]]">
|
||||
<div class="submit-spinner">
|
||||
<paper-spinner active></paper-spinner>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_loading]]">
|
||||
<paper-button on-click="_createUser">Create</paper-button>
|
||||
</template>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -18,53 +18,56 @@ class HaUserEditor extends EventsMixin(
|
||||
) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-card {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 16px;
|
||||
}
|
||||
paper-card:first-child {
|
||||
margin-top: 16px;
|
||||
}
|
||||
paper-card:last-child {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
paper-card {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 0 auto 16px;
|
||||
}
|
||||
paper-card:first-child {
|
||||
margin-top: 16px;
|
||||
}
|
||||
paper-card:last-child {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<hass-subpage header="View user">
|
||||
<paper-card heading="[[_computeName(user)]]">
|
||||
<table class='card-content'>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>[[user.id]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Owner</td>
|
||||
<td>[[user.is_owner]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Active</td>
|
||||
<td>[[user.is_active]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>System generated</td>
|
||||
<td>[[user.system_generated]]</td>
|
||||
</tr>
|
||||
</table>
|
||||
</paper-card>
|
||||
<paper-card>
|
||||
<div class='card-actions'>
|
||||
<paper-button on-click='_deleteUser' disabled='[[user.system_generated]]'>
|
||||
[[localize('ui.panel.config.users.editor.delete_user')]]
|
||||
</paper-button>
|
||||
<template is='dom-if' if='[[user.system_generated]]'>
|
||||
Unable to remove system generated users.
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
</hass-subpage>
|
||||
`;
|
||||
<hass-subpage header="View user">
|
||||
<paper-card heading="[[_computeName(user)]]">
|
||||
<table class="card-content">
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>[[user.id]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Owner</td>
|
||||
<td>[[user.is_owner]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Active</td>
|
||||
<td>[[user.is_active]]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>System generated</td>
|
||||
<td>[[user.system_generated]]</td>
|
||||
</tr>
|
||||
</table>
|
||||
</paper-card>
|
||||
<paper-card>
|
||||
<div class="card-actions">
|
||||
<paper-button
|
||||
on-click="_deleteUser"
|
||||
disabled="[[user.system_generated]]"
|
||||
>
|
||||
[[localize('ui.panel.config.users.editor.delete_user')]]
|
||||
</paper-button>
|
||||
<template is="dom-if" if="[[user.system_generated]]">
|
||||
Unable to remove system generated users.
|
||||
</template>
|
||||
</div>
|
||||
</paper-card>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -23,56 +23,56 @@ class HaUserPicker extends EventsMixin(
|
||||
) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 16px auto;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
paper-fab {
|
||||
position: fixed;
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
}
|
||||
paper-fab[is-wide] {
|
||||
bottom: 24px;
|
||||
right: 24px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 16px auto;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<hass-subpage header="[[localize('ui.panel.config.users.picker.title')]]">
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[users]]" as="user">
|
||||
<a href='[[_computeUrl(user)]]'>
|
||||
<paper-item>
|
||||
<paper-item-body two-line>
|
||||
<div>[[_withDefault(user.name, 'Unnamed User')]]</div>
|
||||
<div secondary="">
|
||||
[[user.id]]
|
||||
<template is='dom-if' if='[[user.system_generated]]'>
|
||||
- System Generated
|
||||
</template>
|
||||
</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</a>
|
||||
</template>
|
||||
</paper-card>
|
||||
<hass-subpage header="[[localize('ui.panel.config.users.picker.title')]]">
|
||||
<paper-card>
|
||||
<template is="dom-repeat" items="[[users]]" as="user">
|
||||
<a href="[[_computeUrl(user)]]">
|
||||
<paper-item>
|
||||
<paper-item-body two-line>
|
||||
<div>[[_withDefault(user.name, 'Unnamed User')]]</div>
|
||||
<div secondary="">
|
||||
[[user.id]]
|
||||
<template is="dom-if" if="[[user.system_generated]]">
|
||||
- System Generated
|
||||
</template>
|
||||
</div>
|
||||
</paper-item-body>
|
||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||
</paper-item>
|
||||
</a>
|
||||
</template>
|
||||
</paper-card>
|
||||
|
||||
<paper-fab
|
||||
is-wide$="[[isWide]]"
|
||||
icon="hass:plus"
|
||||
title="[[localize('ui.panel.config.users.picker.add_user')]]"
|
||||
on-click="_addUser"
|
||||
></paper-fab>
|
||||
</hass-subpage>
|
||||
`;
|
||||
<paper-fab
|
||||
is-wide$="[[isWide]]"
|
||||
icon="hass:plus"
|
||||
title="[[localize('ui.panel.config.users.picker.add_user')]]"
|
||||
on-click="_addUser"
|
||||
></paper-fab>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -38,286 +38,331 @@ import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||
class HaConfigZwave extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style ha-form-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
<style include="iron-flex ha-style ha-form-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.node-info {
|
||||
margin-left: 16px;
|
||||
}
|
||||
.node-info {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
ha-service-description {
|
||||
display: block;
|
||||
color: grey;
|
||||
}
|
||||
ha-service-description {
|
||||
display: block;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.toggle-help-icon {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 0;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button icon="hass:arrow-left" on-click="_backTapped"></paper-icon-button>
|
||||
<div main-title="">[[localize('ui.panel.config.zwave.caption')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
.toggle-help-icon {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 0;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
<ha-app-layout has-scrolling-region="">
|
||||
<app-header slot="header" fixed="">
|
||||
<app-toolbar>
|
||||
<paper-icon-button
|
||||
icon="hass:arrow-left"
|
||||
on-click="_backTapped"
|
||||
></paper-icon-button>
|
||||
<div main-title="">
|
||||
[[localize('ui.panel.config.zwave.caption')]]
|
||||
</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<zwave-network id="zwave-network" is-wide="[[isWide]]" hass="[[hass]]"></zwave-network>
|
||||
<zwave-network
|
||||
id="zwave-network"
|
||||
is-wide="[[isWide]]"
|
||||
hass="[[hass]]"
|
||||
></zwave-network>
|
||||
|
||||
<!--Node card-->
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div style="position: relative" slot="header">
|
||||
<span>Z-Wave Node Management</span>
|
||||
<paper-icon-button class="toggle-help-icon" on-click="toggleHelp" icon="hass:help-circle"></paper-icon-button>
|
||||
|
||||
</div>
|
||||
<span slot="introduction">
|
||||
Run Z-Wave commands that affect a single node. Pick a node to see a list of available commands.
|
||||
</span>
|
||||
|
||||
<paper-card class="content">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu dynamic-align="" label="Nodes" class="flex">
|
||||
<paper-listbox slot="dropdown-content" selected="{{selectedNode}}">
|
||||
<template is="dom-repeat" items="[[nodes]]" as="state">
|
||||
<paper-item>[[computeSelectCaption(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<!-- Node card -->
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div style="position: relative" slot="header">
|
||||
<span>Z-Wave Node Management</span>
|
||||
<paper-icon-button
|
||||
class="toggle-help-icon"
|
||||
on-click="toggleHelp"
|
||||
icon="hass:help-circle"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<span slot="introduction">
|
||||
Run Z-Wave commands that affect a single node. Pick a node to see a
|
||||
list of available commands.
|
||||
</span>
|
||||
|
||||
<paper-card class="content">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu dynamic-align="" label="Nodes" class="flex">
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{selectedNode}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[nodes]]" as="state">
|
||||
<paper-item>[[computeSelectCaption(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<template is="dom-if" if="[[!computeIsNodeSelected(selectedNode)]]">
|
||||
<template is="dom-if" if="[[showHelp]]">
|
||||
<div style="color: grey; padding: 12px">Select node to view per-node options</div>
|
||||
<div style="color: grey; padding: 12px">
|
||||
Select node to view per-node options
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[computeIsNodeSelected(selectedNode)]]">
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]">
|
||||
Refresh Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_node"
|
||||
hidden$="[[!showHelp]]">
|
||||
</ha-service-description>
|
||||
<template is="dom-if" if="[[computeIsNodeSelected(selectedNode)]]">
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]"
|
||||
>
|
||||
Refresh Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_node"
|
||||
hidden$="[[!showHelp]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<template is="dom-if" if="[[nodeFailed]]">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_failed_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]">
|
||||
Remove Failed Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_failed_node"
|
||||
hidden$="[[!showHelp]]">
|
||||
</ha-service-description>
|
||||
<template is="dom-if" if="[[nodeFailed]]">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_failed_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]"
|
||||
>
|
||||
Remove Failed Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_failed_node"
|
||||
hidden$="[[!showHelp]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="replace_failed_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]">
|
||||
Replace Failed Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="replace_failed_node"
|
||||
hidden$="[[!showHelp]]">
|
||||
</ha-service-description>
|
||||
</template>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="print_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]">
|
||||
Print Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="print_node"
|
||||
hidden$="[[!showHelp]]">
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="heal_node"
|
||||
service-data="[[computeHealNodeServiceData(selectedNode)]]">
|
||||
Heal Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="heal_node"
|
||||
hidden$="[[!showHelp]]">
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]">
|
||||
Test Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_node"
|
||||
hidden$="[[!showHelp]]">
|
||||
</ha-service-description>
|
||||
<paper-button on-click="_nodeMoreInfo">Node Information</paper-button>
|
||||
</div>
|
||||
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Entities of this node" dynamic-align="" class="flex">
|
||||
<paper-listbox slot="dropdown-content" selected="{{selectedEntity}}">
|
||||
<template is="dom-repeat" items="[[entities]]" as="state">
|
||||
<paper-item>[[state.entity_id]]</paper-item>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="replace_failed_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]"
|
||||
>
|
||||
Replace Failed Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="replace_failed_node"
|
||||
hidden$="[[!showHelp]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<template is="dom-if" if="[[!computeIsEntitySelected(selectedEntity)]]">
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_entity"
|
||||
service-data="[[computeRefreshEntityServiceData(selectedEntity)]]">
|
||||
Refresh Entity
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_entity"
|
||||
hidden$="[[!showHelp]]">
|
||||
</ha-service-description>
|
||||
<paper-button on-click="_entityMoreInfo">Entity Information</paper-button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<paper-checkbox checked="{{entityIgnored}}" class="form-control">
|
||||
Exclude this entity from Home Assistant
|
||||
</paper-checkbox>
|
||||
<paper-input
|
||||
disabled="{{entityIgnored}}"
|
||||
label="Polling intensity"
|
||||
type="number"
|
||||
min="0"
|
||||
value="{{entityPollingIntensity}}">
|
||||
</paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="set_poll_intensity"
|
||||
service-data="[[computePollIntensityServiceData(entityPollingIntensity)]]">
|
||||
Save
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="print_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]"
|
||||
>
|
||||
Print Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="print_node"
|
||||
hidden$="[[!showHelp]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="heal_node"
|
||||
service-data="[[computeHealNodeServiceData(selectedNode)]]"
|
||||
>
|
||||
Heal Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="heal_node"
|
||||
hidden$="[[!showHelp]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_node"
|
||||
service-data="[[computeNodeServiceData(selectedNode)]]"
|
||||
>
|
||||
Test Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_node"
|
||||
hidden$="[[!showHelp]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
<paper-button on-click="_nodeMoreInfo"
|
||||
>Node Information</paper-button
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu
|
||||
label="Entities of this node"
|
||||
dynamic-align=""
|
||||
class="flex"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{selectedEntity}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[entities]]" as="state">
|
||||
<paper-item>[[state.entity_id]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[!computeIsEntitySelected(selectedEntity)]]"
|
||||
>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_entity"
|
||||
service-data="[[computeRefreshEntityServiceData(selectedEntity)]]"
|
||||
>
|
||||
Refresh Entity
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="refresh_entity"
|
||||
hidden$="[[!showHelp]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
<paper-button on-click="_entityMoreInfo"
|
||||
>Entity Information</paper-button
|
||||
>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<paper-checkbox
|
||||
checked="{{entityIgnored}}"
|
||||
class="form-control"
|
||||
>
|
||||
Exclude this entity from Home Assistant
|
||||
</paper-checkbox>
|
||||
<paper-input
|
||||
disabled="{{entityIgnored}}"
|
||||
label="Polling intensity"
|
||||
type="number"
|
||||
min="0"
|
||||
value="{{entityPollingIntensity}}"
|
||||
>
|
||||
</paper-input>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="set_poll_intensity"
|
||||
service-data="[[computePollIntensityServiceData(entityPollingIntensity)]]"
|
||||
>
|
||||
Save
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</paper-card>
|
||||
|
||||
<template is="dom-if" if="[[computeIsNodeSelected(selectedNode)]]">
|
||||
<!-- Value card -->
|
||||
<zwave-values
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
values="[[values]]"
|
||||
></zwave-values>
|
||||
|
||||
<!-- Group card -->
|
||||
<zwave-groups
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
groups="[[groups]]"
|
||||
></zwave-groups>
|
||||
|
||||
<!-- Config card -->
|
||||
<zwave-node-config
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
config="[[config]]"
|
||||
></zwave-node-config>
|
||||
</template>
|
||||
</paper-card>
|
||||
|
||||
<template is="dom-if" if="[[computeIsNodeSelected(selectedNode)]]">
|
||||
<!-- Protection card -->
|
||||
<template is="dom-if" if="{{_protectionNode}}">
|
||||
<zwave-node-protection
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
protection="[[_protection]]"
|
||||
></zwave-node-protection>
|
||||
</template>
|
||||
|
||||
<!--Value card-->
|
||||
<zwave-values
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
values="[[values]]"
|
||||
></zwave-values>
|
||||
<!-- User Codes -->
|
||||
<template is="dom-if" if="{{hasNodeUserCodes}}">
|
||||
<zwave-usercodes
|
||||
id="zwave-usercodes"
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
user-codes="[[userCodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
></zwave-usercodes>
|
||||
</template>
|
||||
</ha-config-section>
|
||||
|
||||
<!--Group card-->
|
||||
<zwave-groups
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
groups="[[groups]]"
|
||||
></zwave-groups>
|
||||
|
||||
<!--Config card-->
|
||||
<zwave-node-config
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
config="[[config]]"
|
||||
></zwave-node-config>
|
||||
|
||||
</template>
|
||||
|
||||
<!--Protection card-->
|
||||
<template is="dom-if" if="{{_protectionNode}}">
|
||||
<zwave-node-protection
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
protection="[[_protection]]"
|
||||
></zwave-node-protection>
|
||||
</template>
|
||||
|
||||
<!--User Codes-->
|
||||
<template is="dom-if" if="{{hasNodeUserCodes}}">
|
||||
<zwave-usercodes
|
||||
id="zwave-usercodes"
|
||||
hass="[[hass]]"
|
||||
nodes="[[nodes]]"
|
||||
user-codes="[[userCodes]]"
|
||||
selected-node="[[selectedNode]]"
|
||||
></zwave-usercodes>
|
||||
</template>
|
||||
</ha-config-section>
|
||||
|
||||
|
||||
|
||||
<!--Ozw log-->
|
||||
<ozw-log is-wide="[[isWide]]" hass="[[hass]]"></ozw-log>
|
||||
|
||||
</ha-app-layout>
|
||||
`;
|
||||
<!-- Ozw log -->
|
||||
<ozw-log is-wide="[[isWide]]" hass="[[hass]]"></ozw-log>
|
||||
</ha-app-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -12,89 +12,106 @@ import computeStateName from "../../../common/entity/compute_state_name";
|
||||
class ZwaveGroups extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
</style>
|
||||
<paper-card class="content" heading="Node group associations">
|
||||
<!--TODO make api for getting groups and members-->
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Group" dynamic-align="" class="flex">
|
||||
<paper-listbox slot="dropdown-content" selected="{{_selectedGroup}}">
|
||||
<template is="dom-repeat" items="[[groups]]" as="state">
|
||||
<paper-item>[[_computeSelectCaptionGroup(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<template is="dom-if" if="[[_computeIsGroupSelected(_selectedGroup)]]">
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
</style>
|
||||
<paper-card class="content" heading="Node group associations">
|
||||
<!-- TODO make api for getting groups and members -->
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Node to control" dynamic-align="" class="flex">
|
||||
<paper-listbox slot="dropdown-content" selected="{{_selectedTargetNode}}">
|
||||
<template is="dom-repeat" items="[[nodes]]" as="state">
|
||||
<paper-item>[[_computeSelectCaption(state)]]</paper-item>
|
||||
<paper-dropdown-menu label="Group" dynamic-align="" class="flex">
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_selectedGroup}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[groups]]" as="state">
|
||||
<paper-item>[[_computeSelectCaptionGroup(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<template is="dom-if" if="[[_computeIsGroupSelected(_selectedGroup)]]">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu
|
||||
label="Node to control"
|
||||
dynamic-align=""
|
||||
class="flex"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_selectedTargetNode}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[nodes]]" as="state">
|
||||
<paper-item>[[_computeSelectCaption(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
<div class="help-text">
|
||||
<span>Other Nodes in this group:</span>
|
||||
<template is="dom-repeat" items="[[_otherGroupNodes]]" as="state">
|
||||
<div>[[state]]</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="help-text">
|
||||
<span>Max Associations:</span>
|
||||
<span>[[_maxAssociations]]</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="help-text">
|
||||
<span>Other Nodes in this group:</span>
|
||||
<template is="dom-repeat" items="[[_otherGroupNodes]]" as="state">
|
||||
<div>[[state]]</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="help-text">
|
||||
<span>Max Associations:</span> <span>[[_maxAssociations]]</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template is="dom-if" if="[[_computeIsTargetNodeSelected(_selectedTargetNode)]]">
|
||||
<div class="card-actions">
|
||||
<template is="dom-if" if="[[!_noAssociationsLeft]]">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="change_association"
|
||||
service-data="[[_addAssocServiceData]]">
|
||||
Add To Group
|
||||
</ha-call-service-button>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_computeTargetInGroup(_selectedGroup, _selectedTargetNode)]]">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="change_association"
|
||||
service-data="[[_removeAssocServiceData]]">
|
||||
Remove From Group
|
||||
</ha-call-service-button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
`;
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_computeIsTargetNodeSelected(_selectedTargetNode)]]"
|
||||
>
|
||||
<div class="card-actions">
|
||||
<template is="dom-if" if="[[!_noAssociationsLeft]]">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="change_association"
|
||||
service-data="[[_addAssocServiceData]]"
|
||||
>
|
||||
Add To Group
|
||||
</ha-call-service-button>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_computeTargetInGroup(_selectedGroup, _selectedTargetNode)]]"
|
||||
>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="change_association"
|
||||
service-data="[[_removeAssocServiceData]]"
|
||||
>
|
||||
Remove From Group
|
||||
</ha-call-service-button>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,175 +11,191 @@ import "../ha-config-section";
|
||||
class ZwaveNetwork extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.card-actions.warning ha-call-service-button {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
.card-actions.warning ha-call-service-button {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
|
||||
.toggle-help-icon {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 0;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.toggle-help-icon {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 0;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
ha-service-description {
|
||||
display: block;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div style="position: relative" slot="header">
|
||||
<span>Z-Wave Network Management</span>
|
||||
<paper-icon-button class="toggle-help-icon" on-click="helpTap" icon="hass:help-circle"></paper-icon-button>
|
||||
|
||||
</div>
|
||||
<span slot="introduction">
|
||||
Run commands that affect the Z-Wave network. You won't get feedback on whether the command succeeded, but you can look in the OZW Log to try to figure out.
|
||||
</span>
|
||||
|
||||
|
||||
<paper-card class="content">
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node_secure">
|
||||
Add Node Secure
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node_secure"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node">
|
||||
Add Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_node">
|
||||
Remove Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_node"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
ha-service-description {
|
||||
display: block;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<ha-config-section is-wide="[[isWide]]">
|
||||
<div style="position: relative" slot="header">
|
||||
<span>Z-Wave Network Management</span>
|
||||
<paper-icon-button
|
||||
class="toggle-help-icon"
|
||||
on-click="helpTap"
|
||||
icon="hass:help-circle"
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
<div class="card-actions warning">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="cancel_command">
|
||||
Cancel Command
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="cancel_command"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
<span slot="introduction">
|
||||
Run commands that affect the Z-Wave network. You won't get feedback on
|
||||
whether the command succeeded, but you can look in the OZW Log to try
|
||||
to figure out.
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="heal_network">
|
||||
Heal Network
|
||||
</ha-call-service-button>
|
||||
<paper-card class="content">
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node_secure"
|
||||
>
|
||||
Add Node Secure
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node_secure"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="start_network">
|
||||
Start Network
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="start_network"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node"
|
||||
>
|
||||
Add Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="add_node"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="stop_network">
|
||||
Stop Network
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="stop_network"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_node"
|
||||
>
|
||||
Remove Node
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="remove_node"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
</div>
|
||||
<div class="card-actions warning">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="cancel_command"
|
||||
>
|
||||
Cancel Command
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="cancel_command"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="heal_network"
|
||||
>
|
||||
Heal Network
|
||||
</ha-call-service-button>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="soft_reset">
|
||||
Soft Reset
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="soft_reset"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="start_network"
|
||||
>
|
||||
Start Network
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="start_network"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_network">
|
||||
Test Network
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_network"
|
||||
hidden$="[[!showDescription]]">
|
||||
</ha-service-description>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="stop_network"
|
||||
>
|
||||
Stop Network
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="stop_network"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="zwave/saveconfig">
|
||||
Save Config
|
||||
</ha-call-api-button>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="soft_reset"
|
||||
>
|
||||
Soft Reset
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="soft_reset"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
</div>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
`;
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_network"
|
||||
>
|
||||
Test Network
|
||||
</ha-call-service-button>
|
||||
<ha-service-description
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="test_network"
|
||||
hidden$="[[!showDescription]]"
|
||||
>
|
||||
</ha-service-description>
|
||||
|
||||
<ha-call-api-button hass="[[hass]]" path="zwave/saveconfig">
|
||||
Save Config
|
||||
</ha-call-api-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</ha-config-section>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,110 +11,157 @@ import "../../../components/buttons/ha-call-service-button";
|
||||
class ZwaveNodeConfig extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<paper-card heading="Node config options">
|
||||
<template is="dom-if" if="[[_wakeupNode]]">
|
||||
<div class="card-actions">
|
||||
<paper-input
|
||||
float-label="Wakeup Interval"
|
||||
type="number"
|
||||
value="{{_wakeupInput}}"
|
||||
placeholder="[[_computeGetWakeupValue(selectedNode)]]">
|
||||
<div suffix="">seconds</div>
|
||||
</paper-input>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="set_wakeup"
|
||||
service-data="[[_computeWakeupServiceData(_wakeupInput)]]">
|
||||
Set Wakeup
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Config parameter" dynamic-align="" class="flex">
|
||||
<paper-listbox slot="dropdown-content" selected="{{_selectedConfigParameter}}">
|
||||
<template is="dom-repeat" items="[[config]]" as="state">
|
||||
<paper-item>[[_computeSelectCaptionConfigParameter(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<template is="dom-if" if="[[_isConfigParameterSelected(_selectedConfigParameter, 'List')]]">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Config value" dynamic-align="" class="flex" placeholder="{{_loadedConfigValue}}">
|
||||
<paper-listbox slot="dropdown-content" selected="{{_selectedConfigValue}}">
|
||||
<template is="dom-repeat" items="[[_selectedConfigParameterValues]]" as="state">
|
||||
<paper-item>[[state]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
<template is="dom-if" if="[[_isConfigParameterSelected(_selectedConfigParameter, 'Byte Short Int')]]">
|
||||
<div class="card-actions">
|
||||
<paper-input
|
||||
label="{{_selectedConfigParameterNumValues}}"
|
||||
type="number"
|
||||
value="{{_selectedConfigValue}}"
|
||||
max="{{_configParameterMax}}"
|
||||
min="{{_configParameterMin}}">
|
||||
</paper-input>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_isConfigParameterSelected(_selectedConfigParameter, 'Bool Button')]]">
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<paper-card heading="Node config options">
|
||||
<template is="dom-if" if="[[_wakeupNode]]">
|
||||
<div class="card-actions">
|
||||
<paper-input
|
||||
float-label="Wakeup Interval"
|
||||
type="number"
|
||||
value="{{_wakeupInput}}"
|
||||
placeholder="[[_computeGetWakeupValue(selectedNode)]]"
|
||||
>
|
||||
<div suffix="">seconds</div>
|
||||
</paper-input>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="set_wakeup"
|
||||
service-data="[[_computeWakeupServiceData(_wakeupInput)]]"
|
||||
>
|
||||
Set Wakeup
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Config value" class="flex" dynamic-align="" placeholder="{{_loadedConfigValue}}">
|
||||
<paper-listbox slot="dropdown-content" selected="{{_selectedConfigValue}}">
|
||||
<template is="dom-repeat" items="[[_selectedConfigParameterValues]]" as="state">
|
||||
<paper-item>[[state]]</paper-item>
|
||||
<paper-dropdown-menu
|
||||
label="Config parameter"
|
||||
dynamic-align=""
|
||||
class="flex"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_selectedConfigParameter}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[config]]" as="state">
|
||||
<paper-item
|
||||
>[[_computeSelectCaptionConfigParameter(state)]]</paper-item
|
||||
>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
<div class="help-text">
|
||||
<span>[[_configValueHelpText]]</span>
|
||||
</div>
|
||||
<template is="dom-if" if="[[_isConfigParameterSelected(_selectedConfigParameter, 'Bool Button Byte Short Int List')]]">
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="set_config_parameter"
|
||||
service-data="[[_computeSetConfigParameterServiceData(_selectedConfigValue)]]">
|
||||
Set Config Parameter
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_isConfigParameterSelected(_selectedConfigParameter, 'List')]]"
|
||||
>
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu
|
||||
label="Config value"
|
||||
dynamic-align=""
|
||||
class="flex"
|
||||
placeholder="{{_loadedConfigValue}}"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_selectedConfigValue}}"
|
||||
>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[_selectedConfigParameterValues]]"
|
||||
as="state"
|
||||
>
|
||||
<paper-item>[[state]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_isConfigParameterSelected(_selectedConfigParameter, 'Byte Short Int')]]"
|
||||
>
|
||||
<div class="card-actions">
|
||||
<paper-input
|
||||
label="{{_selectedConfigParameterNumValues}}"
|
||||
type="number"
|
||||
value="{{_selectedConfigValue}}"
|
||||
max="{{_configParameterMax}}"
|
||||
min="{{_configParameterMin}}"
|
||||
>
|
||||
</paper-input>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_isConfigParameterSelected(_selectedConfigParameter, 'Bool Button')]]"
|
||||
>
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu
|
||||
label="Config value"
|
||||
class="flex"
|
||||
dynamic-align=""
|
||||
placeholder="{{_loadedConfigValue}}"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_selectedConfigValue}}"
|
||||
>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[_selectedConfigParameterValues]]"
|
||||
as="state"
|
||||
>
|
||||
<paper-item>[[state]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</template>
|
||||
<div class="help-text"><span>[[_configValueHelpText]]</span></div>
|
||||
<template
|
||||
is="dom-if"
|
||||
if="[[_isConfigParameterSelected(_selectedConfigParameter, 'Bool Button Byte Short Int List')]]"
|
||||
>
|
||||
<div class="card-actions">
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="zwave"
|
||||
service="set_config_parameter"
|
||||
service-data="[[_computeSetConfigParameterServiceData(_selectedConfigValue)]]"
|
||||
>
|
||||
Set Config Parameter
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -11,35 +11,44 @@ import "../../../components/buttons/ha-call-service-button";
|
||||
class ZwaveUsercodes extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<paper-card heading="Node user codes">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Code slot" dynamic-align="" class="flex">
|
||||
<paper-listbox slot="dropdown-content" selected="{{_selectedUserCode}}">
|
||||
<template is="dom-repeat" items="[[userCodes]]" as="state">
|
||||
<paper-item>[[_computeSelectCaptionUserCodes(state)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-dropdown-menu
|
||||
label="Code slot"
|
||||
dynamic-align=""
|
||||
class="flex"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_selectedUserCode}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[userCodes]]" as="state">
|
||||
<paper-item
|
||||
>[[_computeSelectCaptionUserCodes(state)]]</paper-item
|
||||
>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
|
||||
<template is="dom-if" if="[[_isUserCodeSelected(_selectedUserCode)]]">
|
||||
@ -49,7 +58,9 @@ class ZwaveUsercodes extends PolymerElement {
|
||||
type="text"
|
||||
allowed-pattern="[0-9,a-f,x,\\\\]"
|
||||
maxlength="40"
|
||||
minlength="16" value="{{_selectedUserCodeValue}}">
|
||||
minlength="16"
|
||||
value="{{_selectedUserCodeValue}}"
|
||||
>
|
||||
</paper-input>
|
||||
<pre>Ascii: [[_computedCodeOutput]]</pre>
|
||||
</div>
|
||||
@ -58,21 +69,23 @@ class ZwaveUsercodes extends PolymerElement {
|
||||
hass="[[hass]]"
|
||||
domain="lock"
|
||||
service="set_usercode"
|
||||
service-data="[[_computeUserCodeServiceData(_selectedUserCodeValue, "Add")]]">
|
||||
service-data="[[_computeUserCodeServiceData(_selectedUserCodeValue, "Add")]]"
|
||||
>
|
||||
Set Usercode
|
||||
</ha-call-service-button>
|
||||
<ha-call-service-button
|
||||
hass="[[hass]]"
|
||||
domain="lock"
|
||||
service="clear_usercode"
|
||||
service-data="[[_computeUserCodeServiceData(_selectedUserCode, "Delete")]]">
|
||||
service-data="[[_computeUserCodeServiceData(_selectedUserCode, "Delete")]]"
|
||||
>
|
||||
Delete Usercode
|
||||
</ha-call-service-button>
|
||||
</div>
|
||||
</template>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -10,44 +10,47 @@ import "../../../components/buttons/ha-call-service-button";
|
||||
class ZwaveValues extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<paper-card heading="Node Values">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Value" dynamic-align="" class="flex">
|
||||
<paper-listbox slot="dropdown-content" selected="{{_selectedValue}}">
|
||||
<template is="dom-repeat" items="[[values]]" as="item">
|
||||
<paper-item>[[_computeSelectCaption(item)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
paper-card {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.device-picker {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-center-center;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
padding-bottom: 24px;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
<paper-card heading="Node Values">
|
||||
<div class="device-picker">
|
||||
<paper-dropdown-menu label="Value" dynamic-align="" class="flex">
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_selectedValue}}"
|
||||
>
|
||||
<template is="dom-repeat" items="[[values]]" as="item">
|
||||
<paper-item>[[_computeSelectCaption(item)]]</paper-item>
|
||||
</template>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -9,31 +9,32 @@ import EventsMixin from "../../mixins/events-mixin";
|
||||
class EventsList extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
<style>
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
line-height: 2em;
|
||||
}
|
||||
li {
|
||||
list-style: none;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--dark-primary-color);
|
||||
}
|
||||
</style>
|
||||
a {
|
||||
color: var(--dark-primary-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<ul>
|
||||
<template is="dom-repeat" items="[[events]]" as="event">
|
||||
<li>
|
||||
<a href="#" on-click="eventSelected">{{event.event}}</a>
|
||||
<span> (</span><span>{{event.listener_count}}</span><span> listeners)</span>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
`;
|
||||
<ul>
|
||||
<template is="dom-repeat" items="[[events]]" as="event">
|
||||
<li>
|
||||
<a href="#" on-click="eventSelected">{{event.event}}</a>
|
||||
<span> (</span><span>{{event.listener_count}}</span
|
||||
><span> listeners)</span>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -19,55 +19,69 @@ import EventsMixin from "../../mixins/events-mixin";
|
||||
class HaPanelDevEvent extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style iron-flex iron-positioning"></style>
|
||||
<style>
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
<style include="ha-style iron-flex iron-positioning"></style>
|
||||
<style>
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
|
||||
.content {
|
||||
@apply --paper-font-body1;
|
||||
padding: 16px;
|
||||
}
|
||||
.content {
|
||||
@apply --paper-font-body1;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.ha-form {
|
||||
margin-right: 16px;
|
||||
}
|
||||
.ha-form {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply --paper-font-title;
|
||||
}
|
||||
</style>
|
||||
.header {
|
||||
@apply --paper-font-title;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>Events</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>Events</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<div class$='[[computeFormClasses(narrow)]]'>
|
||||
<div class='flex'>
|
||||
<p>
|
||||
Fire an event on the event bus.
|
||||
</p>
|
||||
<div class$="[[computeFormClasses(narrow)]]">
|
||||
<div class="flex">
|
||||
<p>Fire an event on the event bus.</p>
|
||||
|
||||
<div class='ha-form'>
|
||||
<paper-input label="Event Type" autofocus required value='{{eventType}}'></paper-input>
|
||||
<paper-textarea label="Event Data (JSON, optional)" value='{{eventData}}'></paper-textarea>
|
||||
<paper-button on-click='fireEvent' raised>Fire Event</paper-button>
|
||||
<div class="ha-form">
|
||||
<paper-input
|
||||
label="Event Type"
|
||||
autofocus
|
||||
required
|
||||
value="{{eventType}}"
|
||||
></paper-input>
|
||||
<paper-textarea
|
||||
label="Event Data (JSON, optional)"
|
||||
value="{{eventData}}"
|
||||
></paper-textarea>
|
||||
<paper-button on-click="fireEvent" raised
|
||||
>Fire Event</paper-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="header">Available Events</div>
|
||||
<events-list
|
||||
on-event-selected="eventSelected"
|
||||
hass="[[hass]]"
|
||||
></events-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class='header'>Available Events</div>
|
||||
<events-list on-event-selected='eventSelected' hass='[[hass]]'></events-list>
|
||||
</div>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -13,22 +13,22 @@ import EventsMixin from "../../mixins/events-mixin";
|
||||
class HaLoadedComponents extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style-dialog">
|
||||
paper-dialog {
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" with-backdrop="" opened="{{_opened}}">
|
||||
<h2>Loaded Components</h2>
|
||||
<paper-dialog-scrollable id="scrollable">
|
||||
<p>The following components are currently loaded:</p>
|
||||
<ul>
|
||||
<template is='dom-repeat' items='[[_components]]'>
|
||||
<li>[[item]]</li>
|
||||
</template>
|
||||
</ul>
|
||||
</paper-dialog-scrollable>
|
||||
</paper-dialog>
|
||||
<style include="ha-style-dialog">
|
||||
paper-dialog {
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" with-backdrop="" opened="{{_opened}}">
|
||||
<h2>Loaded Components</h2>
|
||||
<paper-dialog-scrollable id="scrollable">
|
||||
<p>The following components are currently loaded:</p>
|
||||
<ul>
|
||||
<template is="dom-repeat" items="[[_components]]">
|
||||
<li>[[item]]</li>
|
||||
</template>
|
||||
</ul>
|
||||
</paper-dialog-scrollable>
|
||||
</paper-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -15,66 +15,64 @@ import "../../util/app-localstorage-document";
|
||||
class HaPanelDevMqtt extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include='ha-style'>
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 24px 0 32px;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.content {
|
||||
padding: 24px 0 32px;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
paper-card {
|
||||
display: block;
|
||||
}
|
||||
|
||||
paper-button {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
paper-button {
|
||||
background-color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>MQTT</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>MQTT</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<app-localstorage-document
|
||||
key='panel-dev-mqtt-topic'
|
||||
data='{{topic}}'>
|
||||
</app-localstorage-document>
|
||||
<app-localstorage-document
|
||||
key='panel-dev-mqtt-payload'
|
||||
data='{{payload}}'>
|
||||
</app-localstorage-document>
|
||||
<app-localstorage-document key="panel-dev-mqtt-topic" data="{{topic}}">
|
||||
</app-localstorage-document>
|
||||
<app-localstorage-document
|
||||
key="panel-dev-mqtt-payload"
|
||||
data="{{payload}}"
|
||||
>
|
||||
</app-localstorage-document>
|
||||
|
||||
<div class='content'>
|
||||
<paper-card heading="Publish a packet">
|
||||
<div class='card-content'>
|
||||
<paper-input
|
||||
label="topic"
|
||||
value="{{topic}}"
|
||||
></paper-input>
|
||||
<div class="content">
|
||||
<paper-card heading="Publish a packet">
|
||||
<div class="card-content">
|
||||
<paper-input label="topic" value="{{topic}}"></paper-input>
|
||||
|
||||
<paper-textarea
|
||||
always-float-label
|
||||
label='Payload (template allowed)'
|
||||
value='{{payload}}'
|
||||
></paper-textarea>
|
||||
</div>
|
||||
<div class='card-actions'>
|
||||
<paper-button on-click='_publish'>Publish</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
|
||||
</app-header-layout>
|
||||
<paper-textarea
|
||||
always-float-label
|
||||
label="Payload (template allowed)"
|
||||
value="{{payload}}"
|
||||
></paper-textarea>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<paper-button on-click="_publish">Publish</paper-button>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -16,157 +16,169 @@ const ERROR_SENTINEL = {};
|
||||
class HaPanelDevService extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include='ha-style'>
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.ha-form {
|
||||
margin-right: 16px;
|
||||
max-width: 400px;
|
||||
}
|
||||
.ha-form {
|
||||
margin-right: 16px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-top: 24px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.description {
|
||||
margin-top: 24px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply --paper-font-title;
|
||||
}
|
||||
.header {
|
||||
@apply --paper-font-title;
|
||||
}
|
||||
|
||||
.attributes th {
|
||||
text-align: left;
|
||||
}
|
||||
.attributes th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.attributes tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
.attributes tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.attributes tr:nth-child(odd) {
|
||||
background-color: var(--table-row-background-color,#eee)
|
||||
}
|
||||
.attributes tr:nth-child(odd) {
|
||||
background-color: var(--table-row-background-color, #eee);
|
||||
}
|
||||
|
||||
.attributes tr:nth-child(even) {
|
||||
background-color: var(--table-row-alternative-background-color,#eee)
|
||||
}
|
||||
.attributes tr:nth-child(even) {
|
||||
background-color: var(--table-row-alternative-background-color, #eee);
|
||||
}
|
||||
|
||||
.attributes td:nth-child(3) {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
.attributes td:nth-child(3) {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
white-space: normal;
|
||||
}
|
||||
h1 {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 4px;
|
||||
}
|
||||
td {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
</style>
|
||||
.error {
|
||||
color: var(--google-red-500);
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>Services</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>Services</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<app-localstorage-document
|
||||
key='panel-dev-service-state-domain-service'
|
||||
data='{{domainService}}'>
|
||||
</app-localstorage-document>
|
||||
<app-localstorage-document
|
||||
key='[[_computeServicedataKey(domainService)]]'
|
||||
data='{{serviceData}}'>
|
||||
</app-localstorage-document>
|
||||
<app-localstorage-document
|
||||
key="panel-dev-service-state-domain-service"
|
||||
data="{{domainService}}"
|
||||
>
|
||||
</app-localstorage-document>
|
||||
<app-localstorage-document
|
||||
key="[[_computeServicedataKey(domainService)]]"
|
||||
data="{{serviceData}}"
|
||||
>
|
||||
</app-localstorage-document>
|
||||
|
||||
<div class='content'>
|
||||
<p>
|
||||
The service dev tool allows you to call any available service in Home Assistant.
|
||||
</p>
|
||||
<div class="content">
|
||||
<p>
|
||||
The service dev tool allows you to call any available service in
|
||||
Home Assistant.
|
||||
</p>
|
||||
|
||||
<div class='ha-form'>
|
||||
<ha-service-picker
|
||||
hass='[[hass]]'
|
||||
value='{{domainService}}'
|
||||
></ha-service-picker>
|
||||
<template is='dom-if' if='[[_computeHasEntity(_attributes)]]'>
|
||||
<ha-entity-picker
|
||||
hass='[[hass]]'
|
||||
value='[[_computeEntityValue(parsedJSON)]]'
|
||||
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>
|
||||
<paper-button
|
||||
on-click='_callService'
|
||||
raised
|
||||
disabled='[[!validJSON]]'
|
||||
>Call Service</paper-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 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>
|
||||
<div class="ha-form">
|
||||
<ha-service-picker
|
||||
hass="[[hass]]"
|
||||
value="{{domainService}}"
|
||||
></ha-service-picker>
|
||||
<template is="dom-if" if="[[_computeHasEntity(_attributes)]]">
|
||||
<ha-entity-picker
|
||||
hass="[[hass]]"
|
||||
value="[[_computeEntityValue(parsedJSON)]]"
|
||||
on-change="_entityPicked"
|
||||
disabled="[[!validJSON]]"
|
||||
domain-filter="[[_computeEntityDomainFilter(_domain)]]"
|
||||
allow-custom-entity
|
||||
></ha-entity-picker>
|
||||
</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>
|
||||
<paper-textarea
|
||||
always-float-label
|
||||
label="Service Data (JSON, optional)"
|
||||
value="{{serviceData}}"
|
||||
autocapitalize="none"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
></paper-textarea>
|
||||
<paper-button
|
||||
on-click="_callService"
|
||||
raised
|
||||
disabled="[[!validJSON]]"
|
||||
>Call Service</paper-button
|
||||
>
|
||||
<template is="dom-if" if="[[!validJSON]]">
|
||||
<span class="error">Invalid JSON</span>
|
||||
</template>
|
||||
</table>
|
||||
</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>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -19,132 +19,162 @@ import EventsMixin from "../../mixins/events-mixin";
|
||||
class HaPanelDevState extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
<style include="ha-style">
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
ha-entity-picker, .state-input, paper-textarea {
|
||||
display: block;
|
||||
max-width: 400px;
|
||||
}
|
||||
ha-entity-picker,
|
||||
.state-input,
|
||||
paper-textarea {
|
||||
display: block;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.entities th {
|
||||
text-align: left;
|
||||
}
|
||||
.entities th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.entities tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
.entities tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.entities tr:nth-child(odd) {
|
||||
background-color: var(--table-row-background-color, #fff)
|
||||
}
|
||||
.entities tr:nth-child(odd) {
|
||||
background-color: var(--table-row-background-color, #fff);
|
||||
}
|
||||
|
||||
.entities tr:nth-child(even) {
|
||||
background-color: var(--table-row-alternative-background-color, #eee)
|
||||
}
|
||||
.entities td {
|
||||
padding: 4px;
|
||||
}
|
||||
.entities paper-icon-button {
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
.entities td:nth-child(3) {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
.entities tr:nth-child(even) {
|
||||
background-color: var(--table-row-alternative-background-color, #eee);
|
||||
}
|
||||
.entities td {
|
||||
padding: 4px;
|
||||
}
|
||||
.entities paper-icon-button {
|
||||
height: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
.entities td:nth-child(3) {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.entities a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
.entities a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>States</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></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 />
|
||||
This will not communicate with the actual device.
|
||||
</p>
|
||||
<div class="content">
|
||||
<div>
|
||||
<p>
|
||||
Set the representation of a device within Home Assistant.<br />
|
||||
This will not communicate with the actual device.
|
||||
</p>
|
||||
|
||||
<ha-entity-picker
|
||||
autofocus
|
||||
hass="[[hass]]"
|
||||
value="{{_entityId}}"
|
||||
allow-custom-entity
|
||||
></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>
|
||||
<paper-button on-click='handleSetState' raised>Set State</paper-button>
|
||||
</div>
|
||||
<ha-entity-picker
|
||||
autofocus
|
||||
hass="[[hass]]"
|
||||
value="{{_entityId}}"
|
||||
allow-custom-entity
|
||||
></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>
|
||||
<paper-button on-click="handleSetState" raised
|
||||
>Set State</paper-button
|
||||
>
|
||||
</div>
|
||||
|
||||
<h1>Current entities</h1>
|
||||
<table class='entities'>
|
||||
<tr>
|
||||
<th>Entity</th>
|
||||
<th>State</th>
|
||||
<th hidden$='[[narrow]]'>
|
||||
Attributes
|
||||
<paper-checkbox checked='{{_showAttributes}}'></paper-checkbox>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><paper-input label="Filter entities" type="search" value='{{_entityFilter}}'></paper-input></th>
|
||||
<th><paper-input label="Filter states" type="search" value='{{_stateFilter}}'></paper-input></th>
|
||||
<th hidden$='[[!computeShowAttributes(narrow, _showAttributes)]]'><paper-input 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'>
|
||||
<h1>Current entities</h1>
|
||||
<table class="entities">
|
||||
<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>
|
||||
<th>Entity</th>
|
||||
<th>State</th>
|
||||
<th hidden$="[[narrow]]">
|
||||
Attributes
|
||||
<paper-checkbox checked="{{_showAttributes}}"></paper-checkbox>
|
||||
</th>
|
||||
</tr>
|
||||
</template>
|
||||
</table>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
<tr>
|
||||
<th>
|
||||
<paper-input
|
||||
label="Filter entities"
|
||||
type="search"
|
||||
value="{{_entityFilter}}"
|
||||
></paper-input>
|
||||
</th>
|
||||
<th>
|
||||
<paper-input
|
||||
label="Filter states"
|
||||
type="search"
|
||||
value="{{_stateFilter}}"
|
||||
></paper-input>
|
||||
</th>
|
||||
<th hidden$="[[!computeShowAttributes(narrow, _showAttributes)]]">
|
||||
<paper-input
|
||||
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>
|
||||
</table>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -14,88 +14,107 @@ import "../../resources/ha-style";
|
||||
class HaPanelDevTemplate extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style iron-flex iron-positioning"></style>
|
||||
<style>
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.edit-pane {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.edit-pane a {
|
||||
color: var(--dark-primary-color);
|
||||
}
|
||||
|
||||
.horizontal .edit-pane {
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.render-pane {
|
||||
position: relative;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.render-spinner {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
paper-textarea {
|
||||
--paper-input-container-input: {
|
||||
@apply --paper-font-code1;
|
||||
<style include="ha-style iron-flex iron-positioning"></style>
|
||||
<style>
|
||||
:host {
|
||||
-ms-user-select: initial;
|
||||
-webkit-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.rendered {
|
||||
@apply --paper-font-code1;
|
||||
clear: both;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.rendered.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
.edit-pane {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>Templates</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
.edit-pane a {
|
||||
color: var(--dark-primary-color);
|
||||
}
|
||||
|
||||
<div class$='[[computeFormClasses(narrow)]]'>
|
||||
<div class='edit-pane'>
|
||||
<p>
|
||||
Templates are rendered using the Jinja2 template engine with some Home Assistant specific extensions.
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href='http://jinja.pocoo.org/docs/dev/templates/' target='_blank'>Jinja2 template documentation</a></li>
|
||||
<li><a href='https://home-assistant.io/docs/configuration/templating/' target='_blank'>Home Assistant template extensions</a></li>
|
||||
</ul>
|
||||
<paper-textarea
|
||||
label="Template editor"
|
||||
value='{{template}}'
|
||||
autofocus
|
||||
></paper-textarea>
|
||||
.horizontal .edit-pane {
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.render-pane {
|
||||
position: relative;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.render-spinner {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
|
||||
paper-textarea {
|
||||
--paper-input-container-input: {
|
||||
@apply --paper-font-code1;
|
||||
}
|
||||
}
|
||||
|
||||
.rendered {
|
||||
@apply --paper-font-code1;
|
||||
clear: both;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.rendered.error {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>Templates</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<div class$="[[computeFormClasses(narrow)]]">
|
||||
<div class="edit-pane">
|
||||
<p>
|
||||
Templates are rendered using the Jinja2 template engine with some
|
||||
Home Assistant specific extensions.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="http://jinja.pocoo.org/docs/dev/templates/"
|
||||
target="_blank"
|
||||
>Jinja2 template documentation</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://home-assistant.io/docs/configuration/templating/"
|
||||
target="_blank"
|
||||
>Home Assistant template extensions</a
|
||||
>
|
||||
</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 class='render-pane'>
|
||||
<paper-spinner class='render-spinner' active='[[rendering]]'></paper-spinner>
|
||||
<pre class$='[[computeRenderedClasses(error)]]'>[[processed]]</pre>
|
||||
</div>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -25,75 +25,85 @@ import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
class HaPanelHistory extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
<style include="iron-flex ha-style">
|
||||
.content {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
|
||||
vaadin-date-picker {
|
||||
margin-right: 16px;
|
||||
max-width: 200px;
|
||||
}
|
||||
vaadin-date-picker {
|
||||
margin-right: 16px;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
paper-dropdown-menu {
|
||||
max-width: 100px;
|
||||
}
|
||||
paper-dropdown-menu {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-state-history-data
|
||||
hass='[[hass]]'
|
||||
filter-type='[[_filterType]]'
|
||||
start-time='[[_computeStartTime(_currentDate)]]'
|
||||
end-time='[[endTime]]'
|
||||
data='{{stateHistory}}'
|
||||
is-loading='{{isLoadingData}}'
|
||||
></ha-state-history-data>
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>[[localize('panel.history')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<ha-state-history-data
|
||||
hass="[[hass]]"
|
||||
filter-type="[[_filterType]]"
|
||||
start-time="[[_computeStartTime(_currentDate)]]"
|
||||
end-time="[[endTime]]"
|
||||
data="{{stateHistory}}"
|
||||
is-loading="{{isLoadingData}}"
|
||||
></ha-state-history-data>
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>[[localize('panel.history')]]</div>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<div class="flex content">
|
||||
<div class="flex layout horizontal wrap">
|
||||
<vaadin-date-picker
|
||||
id='picker'
|
||||
value='{{_currentDate}}'
|
||||
label="[[localize('ui.panel.history.showing_entries')]]"
|
||||
disabled='[[isLoadingData]]'
|
||||
required
|
||||
></vaadin-date-picker>
|
||||
<div class="flex content">
|
||||
<div class="flex layout horizontal wrap">
|
||||
<vaadin-date-picker
|
||||
id="picker"
|
||||
value="{{_currentDate}}"
|
||||
label="[[localize('ui.panel.history.showing_entries')]]"
|
||||
disabled="[[isLoadingData]]"
|
||||
required
|
||||
></vaadin-date-picker>
|
||||
|
||||
<paper-dropdown-menu
|
||||
label-float
|
||||
label="[[localize('ui.panel.history.period')]]"
|
||||
disabled='[[isLoadingData]]'
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_periodIndex}}"
|
||||
<paper-dropdown-menu
|
||||
label-float
|
||||
label="[[localize('ui.panel.history.period')]]"
|
||||
disabled="[[isLoadingData]]"
|
||||
>
|
||||
<paper-item>[[localize('ui.duration.day', 'count', 1)]]</paper-item>
|
||||
<paper-item>[[localize('ui.duration.day', 'count', 3)]]</paper-item>
|
||||
<paper-item>[[localize('ui.duration.week', 'count', 1)]]</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_periodIndex}}"
|
||||
>
|
||||
<paper-item
|
||||
>[[localize('ui.duration.day', 'count', 1)]]</paper-item
|
||||
>
|
||||
<paper-item
|
||||
>[[localize('ui.duration.day', 'count', 3)]]</paper-item
|
||||
>
|
||||
<paper-item
|
||||
>[[localize('ui.duration.week', 'count', 1)]]</paper-item
|
||||
>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
<state-history-charts
|
||||
hass="[[hass]]"
|
||||
history-data="[[stateHistory]]"
|
||||
is-loading-data="[[isLoadingData]]"
|
||||
end-time="[[endTime]]"
|
||||
no-single
|
||||
>
|
||||
</state-history-charts>
|
||||
</div>
|
||||
<state-history-charts
|
||||
hass='[[hass]]'
|
||||
history-data="[[stateHistory]]"
|
||||
is-loading-data="[[isLoadingData]]"
|
||||
end-time="[[endTime]]"
|
||||
no-single>
|
||||
</state-history-charts>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -8,23 +8,28 @@ import "../../resources/ha-style";
|
||||
class HaPanelIframe extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include='ha-style'>
|
||||
iframe {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
</style>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>[[panel.title]]</div>
|
||||
</app-toolbar>
|
||||
<style include="ha-style">
|
||||
iframe {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 64px);
|
||||
}
|
||||
</style>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>[[panel.title]]</div>
|
||||
</app-toolbar>
|
||||
|
||||
<iframe
|
||||
src='[[panel.config.url]]'
|
||||
sandbox="allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts"
|
||||
allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true"
|
||||
></iframe>
|
||||
<iframe
|
||||
src="[[panel.config.url]]"
|
||||
sandbox="allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts"
|
||||
allowfullscreen="true"
|
||||
webkitallowfullscreen="true"
|
||||
mozallowfullscreen="true"
|
||||
></iframe>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -6,13 +6,13 @@ import "../../layouts/partial-cards";
|
||||
class HaPanelKiosk extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<partial-cards
|
||||
id='kiosk-states'
|
||||
hass='[[hass]]'
|
||||
show-menu
|
||||
route='[[route]]'
|
||||
panel-visible
|
||||
></partial-cards>
|
||||
<partial-cards
|
||||
id="kiosk-states"
|
||||
hass="[[hass]]"
|
||||
show-menu
|
||||
route="[[route]]"
|
||||
panel-visible
|
||||
></partial-cards>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -14,62 +14,63 @@ import domainIcon from "../../common/entity/domain_icon";
|
||||
class HaLogbook extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
<style include="iron-flex"></style>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.entry {
|
||||
@apply --paper-font-body1;
|
||||
line-height: 2em;
|
||||
}
|
||||
.entry {
|
||||
@apply --paper-font-body1;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 55px;
|
||||
font-size: .8em;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.time {
|
||||
width: 55px;
|
||||
font-size: 0.8em;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
iron-icon {
|
||||
margin: 0 8px 0 16px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
iron-icon {
|
||||
margin: 0 8px 0 16px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.message {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.message {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<template is="dom-if" if="[[!entries.length]]">
|
||||
No logbook entries found.
|
||||
</template>
|
||||
|
||||
<template is="dom-repeat" items="[[entries]]">
|
||||
<template is="dom-if" if="{{_needHeader(entries.*, index)}}">
|
||||
<h4 class="date">[[_formatDate(item.when)]]</h4>
|
||||
<template is="dom-if" if="[[!entries.length]]">
|
||||
No logbook entries found.
|
||||
</template>
|
||||
|
||||
<div class="horizontal layout entry">
|
||||
<div class="time">[[_formatTime(item.when)]]</div>
|
||||
<iron-icon icon="[[_computeIcon(item.domain)]]"></iron-icon>
|
||||
<div class="message" flex="">
|
||||
<template is="dom-if" if="[[!item.entity_id]]">
|
||||
<span class="name">[[item.name]]</span>
|
||||
</template>
|
||||
<template is="dom-if" if="[[item.entity_id]]">
|
||||
<a href="#" on-click="entityClicked" class="name">[[item.name]]</a>
|
||||
</template>
|
||||
<span> </span>
|
||||
<span>[[item.message]]</span>
|
||||
<template is="dom-repeat" items="[[entries]]">
|
||||
<template is="dom-if" if="{{_needHeader(entries.*, index)}}">
|
||||
<h4 class="date">[[_formatDate(item.when)]]</h4>
|
||||
</template>
|
||||
|
||||
<div class="horizontal layout entry">
|
||||
<div class="time">[[_formatTime(item.when)]]</div>
|
||||
<iron-icon icon="[[_computeIcon(item.domain)]]"></iron-icon>
|
||||
<div class="message" flex="">
|
||||
<template is="dom-if" if="[[!item.entity_id]]">
|
||||
<span class="name">[[item.name]]</span>
|
||||
</template>
|
||||
<template is="dom-if" if="[[item.entity_id]]">
|
||||
<a href="#" on-click="entityClicked" class="name"
|
||||
>[[item.name]]</a
|
||||
>
|
||||
</template>
|
||||
<span> </span> <span>[[item.message]]</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
|
||||
@ -25,115 +25,128 @@ import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
class HaPanelLogbook extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
.content {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
<style include="ha-style">
|
||||
.content {
|
||||
padding: 0 16px 16px;
|
||||
}
|
||||
|
||||
paper-spinner {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
paper-spinner {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.wrap {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.wrap {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
vaadin-date-picker {
|
||||
--vaadin-date-picker-clear-icon: {
|
||||
display: none;
|
||||
}
|
||||
max-width: 200px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
vaadin-date-picker {
|
||||
--vaadin-date-picker-clear-icon: {
|
||||
display: none;
|
||||
}
|
||||
max-width: 200px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
paper-dropdown-menu {
|
||||
max-width: 100px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
paper-dropdown-menu {
|
||||
max-width: 100px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
ha-entity-picker {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
ha-entity-picker {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-logbook-data
|
||||
hass='[[hass]]'
|
||||
is-loading='{{isLoading}}'
|
||||
entries='{{entries}}'
|
||||
filter-date='[[_computeFilterDate(_currentDate)]]'
|
||||
filter-period='[[_computeFilterDays(_periodIndex)]]'
|
||||
filter-entity='[[entityId]]'
|
||||
></ha-logbook-data>
|
||||
<ha-logbook-data
|
||||
hass="[[hass]]"
|
||||
is-loading="{{isLoading}}"
|
||||
entries="{{entries}}"
|
||||
filter-date="[[_computeFilterDate(_currentDate)]]"
|
||||
filter-period="[[_computeFilterDays(_periodIndex)]]"
|
||||
filter-entity="[[entityId]]"
|
||||
></ha-logbook-data>
|
||||
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
|
||||
<div main-title>[[localize('panel.logbook')]]</div>
|
||||
<paper-icon-button
|
||||
icon='hass:refresh'
|
||||
on-click='refreshLogbook'
|
||||
hidden$='[[isLoading]]'
|
||||
></paper-icon-button>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
<app-header-layout has-scrolling-region>
|
||||
<app-header slot="header" fixed>
|
||||
<app-toolbar>
|
||||
<ha-menu-button
|
||||
narrow="[[narrow]]"
|
||||
show-menu="[[showMenu]]"
|
||||
></ha-menu-button>
|
||||
<div main-title>[[localize('panel.logbook')]]</div>
|
||||
<paper-icon-button
|
||||
icon="hass:refresh"
|
||||
on-click="refreshLogbook"
|
||||
hidden$="[[isLoading]]"
|
||||
></paper-icon-button>
|
||||
</app-toolbar>
|
||||
</app-header>
|
||||
|
||||
<div class="content">
|
||||
<paper-spinner
|
||||
active='[[isLoading]]'
|
||||
hidden$='[[!isLoading]]'
|
||||
alt="[[localize('ui.common.loading')]]"
|
||||
></paper-spinner>
|
||||
<div class="content">
|
||||
<paper-spinner
|
||||
active="[[isLoading]]"
|
||||
hidden$="[[!isLoading]]"
|
||||
alt="[[localize('ui.common.loading')]]"
|
||||
></paper-spinner>
|
||||
|
||||
<div class="flex layout horizontal wrap">
|
||||
<vaadin-date-picker
|
||||
id='picker'
|
||||
value='{{_currentDate}}'
|
||||
label="[[localize('ui.panel.logbook.showing_entries')]]"
|
||||
disabled='[[isLoading]]'
|
||||
required
|
||||
></vaadin-date-picker>
|
||||
<div class="flex layout horizontal wrap">
|
||||
<vaadin-date-picker
|
||||
id="picker"
|
||||
value="{{_currentDate}}"
|
||||
label="[[localize('ui.panel.logbook.showing_entries')]]"
|
||||
disabled="[[isLoading]]"
|
||||
required
|
||||
></vaadin-date-picker>
|
||||
|
||||
<paper-dropdown-menu
|
||||
label-float
|
||||
label="[[localize('ui.panel.logbook.period')]]"
|
||||
disabled='[[isLoading]]'
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_periodIndex}}"
|
||||
<paper-dropdown-menu
|
||||
label-float
|
||||
label="[[localize('ui.panel.logbook.period')]]"
|
||||
disabled="[[isLoading]]"
|
||||
>
|
||||
<paper-item>[[localize('ui.duration.day', 'count', 1)]]</paper-item>
|
||||
<paper-item>[[localize('ui.duration.day', 'count', 3)]]</paper-item>
|
||||
<paper-item>[[localize('ui.duration.week', 'count', 1)]]</paper-item>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
selected="{{_periodIndex}}"
|
||||
>
|
||||
<paper-item
|
||||
>[[localize('ui.duration.day', 'count', 1)]]</paper-item
|
||||
>
|
||||
<paper-item
|
||||
>[[localize('ui.duration.day', 'count', 3)]]</paper-item
|
||||
>
|
||||
<paper-item
|
||||
>[[localize('ui.duration.week', 'count', 1)]]</paper-item
|
||||
>
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
|
||||
<ha-entity-picker
|
||||
<ha-entity-picker
|
||||
hass="[[hass]]"
|
||||
value="{{_entityId}}"
|
||||
label="[[localize('ui.components.entity.entity-picker.entity')]]"
|
||||
disabled="[[isLoading]]"
|
||||
on-change="_entityPicked"
|
||||
></ha-entity-picker>
|
||||
</div>
|
||||
|
||||
<ha-logbook
|
||||
hass="[[hass]]"
|
||||
value="{{_entityId}}"
|
||||
label="[[localize('ui.components.entity.entity-picker.entity')]]"
|
||||
disabled='[[isLoading]]'
|
||||
on-change='_entityPicked'
|
||||
></ha-entity-picker>
|
||||
entries="[[entries]]"
|
||||
hidden$="[[isLoading]]"
|
||||
></ha-logbook>
|
||||
</div>
|
||||
|
||||
<ha-logbook hass='[[hass]]' entries="[[entries]]" hidden$='[[isLoading]]'></ha-logbook>
|
||||
</div>
|
||||
</app-header-layout>
|
||||
</app-header-layout>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -97,25 +97,29 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
|
||||
!title && !show_header_toggle
|
||||
? html``
|
||||
: html`
|
||||
<div class='header'>
|
||||
<div class="name">${title}</div>
|
||||
${
|
||||
show_header_toggle === false
|
||||
? html``
|
||||
: html`
|
||||
<hui-entities-toggle
|
||||
.hass="${this._hass}"
|
||||
.entities="${this._configEntities!.map(
|
||||
(conf) => conf.entity
|
||||
)}"
|
||||
></hui-entities-toggle>`
|
||||
}
|
||||
</div>`
|
||||
<div class="header">
|
||||
<div class="name">${title}</div>
|
||||
${
|
||||
show_header_toggle === false
|
||||
? html``
|
||||
: html`
|
||||
<hui-entities-toggle
|
||||
.hass="${this._hass}"
|
||||
.entities="${
|
||||
this._configEntities!.map((conf) => conf.entity)
|
||||
}"
|
||||
></hui-entities-toggle>
|
||||
`
|
||||
}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
<div id="states">
|
||||
${this._configEntities!.map((entityConf) =>
|
||||
this.renderEntity(entityConf)
|
||||
)}
|
||||
${
|
||||
this._configEntities!.map((entityConf) =>
|
||||
this.renderEntity(entityConf)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
@ -169,7 +173,9 @@ class HuiEntitiesCard extends hassLocalizeLitMixin(LitElement)
|
||||
element.addEventListener("click", () => this._handleClick(entityConf));
|
||||
}
|
||||
|
||||
return html`<div>${element}</div>`;
|
||||
return html`
|
||||
<div>${element}</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleClick(entityConf: ConfigEntity): void {
|
||||
|
||||
@ -87,27 +87,31 @@ class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement)
|
||||
>
|
||||
${
|
||||
!stateObj
|
||||
? html`<div class="not-found">Entity not available: ${
|
||||
this._config.entity
|
||||
}</div>`
|
||||
: html`
|
||||
<paper-button>
|
||||
<div>
|
||||
<ha-icon
|
||||
data-domain="${computeStateDomain(stateObj)}"
|
||||
data-state="${stateObj.state}"
|
||||
.icon="${this._config.icon || stateIcon(stateObj)}"
|
||||
style="${styleMap({
|
||||
filter: this._computeBrightness(stateObj),
|
||||
color: this._computeColor(stateObj),
|
||||
})}"
|
||||
></ha-icon>
|
||||
<span>
|
||||
${this._config.name || computeStateName(stateObj)}
|
||||
</span>
|
||||
? html`
|
||||
<div class="not-found">
|
||||
Entity not available: ${this._config.entity}
|
||||
</div>
|
||||
</paper-button>
|
||||
`
|
||||
`
|
||||
: html`
|
||||
<paper-button>
|
||||
<div>
|
||||
<ha-icon
|
||||
data-domain="${computeStateDomain(stateObj)}"
|
||||
data-state="${stateObj.state}"
|
||||
.icon="${this._config.icon || stateIcon(stateObj)}"
|
||||
style="${
|
||||
styleMap({
|
||||
filter: this._computeBrightness(stateObj),
|
||||
color: this._computeColor(stateObj),
|
||||
})
|
||||
}"
|
||||
></ha-icon>
|
||||
<span>
|
||||
${this._config.name || computeStateName(stateObj)}
|
||||
</span>
|
||||
</div>
|
||||
</paper-button>
|
||||
`
|
||||
}
|
||||
</ha-card>
|
||||
`;
|
||||
@ -125,41 +129,41 @@ class HuiEntityButtonCard extends hassLocalizeLitMixin(LitElement)
|
||||
|
||||
private renderStyle(): TemplateResult {
|
||||
return html`
|
||||
<style>
|
||||
ha-icon {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
width: 40%;
|
||||
height: 40%;
|
||||
color: var(--paper-item-icon-color, #44739e);
|
||||
}
|
||||
ha-icon[data-domain=light][data-state=on],
|
||||
ha-icon[data-domain=switch][data-state=on],
|
||||
ha-icon[data-domain=binary_sensor][data-state=on],
|
||||
ha-icon[data-domain=fan][data-state=on],
|
||||
ha-icon[data-domain=sun][data-state=above_horizon] {
|
||||
color: var(--paper-item-icon-active-color, #FDD835);
|
||||
}
|
||||
ha-icon[data-state=unavailable] {
|
||||
color: var(--state-icon-unavailable-color);
|
||||
}
|
||||
state-badge {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
width:40%;
|
||||
height:40%;
|
||||
}
|
||||
paper-button {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
.not-found {
|
||||
flex: 1;
|
||||
background-color: yellow;
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
ha-icon {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
width: 40%;
|
||||
height: 40%;
|
||||
color: var(--paper-item-icon-color, #44739e);
|
||||
}
|
||||
ha-icon[data-domain="light"][data-state="on"],
|
||||
ha-icon[data-domain="switch"][data-state="on"],
|
||||
ha-icon[data-domain="binary_sensor"][data-state="on"],
|
||||
ha-icon[data-domain="fan"][data-state="on"],
|
||||
ha-icon[data-domain="sun"][data-state="above_horizon"] {
|
||||
color: var(--paper-item-icon-active-color, #fdd835);
|
||||
}
|
||||
ha-icon[data-state="unavailable"] {
|
||||
color: var(--state-icon-unavailable-color);
|
||||
}
|
||||
state-badge {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
width: 40%;
|
||||
height: 40%;
|
||||
}
|
||||
paper-button {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
.not-found {
|
||||
flex: 1;
|
||||
background-color: yellow;
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -31,8 +31,7 @@ class HuiErrorCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
return html`
|
||||
${this.renderStyle()}
|
||||
${this._config.error}
|
||||
${this.renderStyle()} ${this._config.error}
|
||||
<pre>${this._toStr(this._config.origConfig)}</pre>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -71,30 +71,33 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
return html`
|
||||
${this.renderStyle()}
|
||||
<ha-card @click="${this._handleClick}">
|
||||
${
|
||||
error
|
||||
? html`<div class="not-found">${error}</div>`
|
||||
: html`
|
||||
<div class='container'>
|
||||
<div class='gauge-a'></div>
|
||||
<div class='gauge-b'></div>
|
||||
<div class='gauge-c' id='gauge'></div>
|
||||
<div class='gauge-data'>
|
||||
<div id='percent'>${stateObj.state}
|
||||
${this._config.unit_of_measurement ||
|
||||
stateObj.attributes.unit_of_measurement ||
|
||||
""}
|
||||
</div>
|
||||
<div id='title'>${this._config.title}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
</ha-card>
|
||||
${this.renderStyle()}
|
||||
<ha-card @click="${this._handleClick}">
|
||||
${
|
||||
error
|
||||
? html`
|
||||
<div class="not-found">${error}</div>
|
||||
`
|
||||
: html`
|
||||
<div class="container">
|
||||
<div class="gauge-a"></div>
|
||||
<div class="gauge-b"></div>
|
||||
<div class="gauge-c" id="gauge"></div>
|
||||
<div class="gauge-data">
|
||||
<div id="percent">
|
||||
${stateObj.state}
|
||||
${
|
||||
this._config.unit_of_measurement ||
|
||||
stateObj.attributes.unit_of_measurement ||
|
||||
""
|
||||
}
|
||||
</div>
|
||||
<div id="title">${this._config.title}</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -142,30 +145,31 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
<style>
|
||||
ha-card {
|
||||
--base-unit: 50px;
|
||||
height: calc(var(--base-unit)*3);
|
||||
height: calc(var(--base-unit) * 3);
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
.container{
|
||||
.container {
|
||||
width: calc(var(--base-unit) * 4);
|
||||
height: calc(var(--base-unit) * 2);
|
||||
position: absolute;
|
||||
top: calc(var(--base-unit)*1.5);
|
||||
top: calc(var(--base-unit) * 1.5);
|
||||
left: 50%;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.gauge-a{
|
||||
.gauge-a {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
background-color: var(--primary-background-color);
|
||||
width: calc(var(--base-unit) * 4);
|
||||
height: calc(var(--base-unit) * 2);
|
||||
top: 0%;
|
||||
border-radius:calc(var(--base-unit) * 2.5) calc(var(--base-unit) * 2.5) 0px 0px ;
|
||||
border-radius: calc(var(--base-unit) * 2.5)
|
||||
calc(var(--base-unit) * 2.5) 0px 0px;
|
||||
}
|
||||
.gauge-b{
|
||||
.gauge-b {
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
background-color: var(--paper-card-background-color);
|
||||
@ -174,9 +178,10 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
top: calc(var(--base-unit) * 0.75);
|
||||
margin-left: calc(var(--base-unit) * 0.75);
|
||||
margin-right: auto;
|
||||
border-radius: calc(var(--base-unit) * 2.5) calc(var(--base-unit) * 2.5) 0px 0px ;
|
||||
border-radius: calc(var(--base-unit) * 2.5)
|
||||
calc(var(--base-unit) * 2.5) 0px 0px;
|
||||
}
|
||||
.gauge-c{
|
||||
.gauge-c {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
background-color: var(--label-badge-blue);
|
||||
@ -185,11 +190,12 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
top: calc(var(--base-unit) * 2);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 0px 0px calc(var(--base-unit) * 2) calc(var(--base-unit) * 2) ;
|
||||
border-radius: 0px 0px calc(var(--base-unit) * 2)
|
||||
calc(var(--base-unit) * 2);
|
||||
transform-origin: center top;
|
||||
transition: all 1.3s ease-in-out;
|
||||
}
|
||||
.gauge-data{
|
||||
.gauge-data {
|
||||
z-index: 4;
|
||||
color: var(--primary-text-color);
|
||||
line-height: calc(var(--base-unit) * 0.3);
|
||||
@ -201,12 +207,12 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
|
||||
margin-right: auto;
|
||||
transition: all 1s ease-out;
|
||||
}
|
||||
.gauge-data #percent{
|
||||
.gauge-data #percent {
|
||||
font-size: calc(var(--base-unit) * 0.55);
|
||||
}
|
||||
.gauge-data #title{
|
||||
.gauge-data #title {
|
||||
padding-top: calc(var(--base-unit) * 0.15);
|
||||
font-size: calc(var(--base-unit) * 0.30);
|
||||
font-size: calc(var(--base-unit) * 0.3);
|
||||
}
|
||||
.not-found {
|
||||
flex: 1;
|
||||
|
||||
@ -122,9 +122,11 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
|
||||
${this.renderStyle()}
|
||||
<ha-card .header="${title}">
|
||||
<div class="entities ${classMap({ "no-header": !title })}">
|
||||
${this._configEntities!.map((entityConf) =>
|
||||
this.renderEntity(entityConf)
|
||||
)}
|
||||
${
|
||||
this._configEntities!.map((entityConf) =>
|
||||
this.renderEntity(entityConf)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
@ -187,9 +189,12 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
|
||||
const stateObj = this.hass!.states[entityConf.entity];
|
||||
|
||||
if (!stateObj) {
|
||||
return html`<div class="entity not-found"><div class="name">${
|
||||
entityConf.entity
|
||||
}</div>Entity Not Available</div>`;
|
||||
return html`
|
||||
<div class="entity not-found">
|
||||
<div class="name">${entityConf.entity}</div>
|
||||
Entity Not Available
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`
|
||||
@ -202,11 +207,15 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
|
||||
>
|
||||
${
|
||||
this._config!.show_name !== false
|
||||
? html`<div class="name">${
|
||||
"name" in entityConf
|
||||
? entityConf.name
|
||||
: computeStateName(stateObj)
|
||||
}</div>`
|
||||
? html`
|
||||
<div class="name">
|
||||
${
|
||||
"name" in entityConf
|
||||
? entityConf.name
|
||||
: computeStateName(stateObj)
|
||||
}
|
||||
</div>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
<state-badge
|
||||
@ -215,11 +224,17 @@ export class HuiGlanceCard extends hassLocalizeLitMixin(LitElement)
|
||||
></state-badge>
|
||||
${
|
||||
this._config!.show_state !== false
|
||||
? html`<div>${computeStateDisplay(
|
||||
this.localize,
|
||||
stateObj,
|
||||
this.hass!.language
|
||||
)}</div>`
|
||||
? html`
|
||||
<div>
|
||||
${
|
||||
computeStateDisplay(
|
||||
this.localize,
|
||||
stateObj,
|
||||
this.hass!.language
|
||||
)
|
||||
}
|
||||
</div>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -19,7 +19,7 @@ class HuiHistoryGraphCard extends PolymerElement {
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-card header$='[[_config.title]]'>
|
||||
<ha-card header$="[[_config.title]]">
|
||||
<ha-state-history-data
|
||||
hass="[[hass]]"
|
||||
filter-type="recent-entity"
|
||||
|
||||
@ -43,10 +43,13 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
||||
return html`
|
||||
${this.renderStyle()}
|
||||
<ha-card .header="${this._config.title}">
|
||||
<div id="root"
|
||||
style="${styleMap({
|
||||
"padding-top": aspectRatio,
|
||||
})}"
|
||||
<div
|
||||
id="root"
|
||||
style="${
|
||||
styleMap({
|
||||
"padding-top": aspectRatio,
|
||||
})
|
||||
}"
|
||||
>
|
||||
<iframe src="${this._config.url}"></iframe>
|
||||
</div>
|
||||
|
||||
@ -81,37 +81,40 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
|
||||
${
|
||||
!stateObj
|
||||
? html`
|
||||
<div class="not-found">Entity not available: ${
|
||||
this._config.entity
|
||||
}</div>`
|
||||
: html`
|
||||
<div id="light"></div>
|
||||
<div id="tooltip">
|
||||
<div class="icon-state">
|
||||
<ha-icon
|
||||
data-state="${stateObj.state}"
|
||||
.icon="${stateIcon(stateObj)}"
|
||||
style="${styleMap({
|
||||
filter: this._computeBrightness(stateObj),
|
||||
color: this._computeColor(stateObj),
|
||||
})}"
|
||||
@ha-click="${() => this._handleClick(false)}"
|
||||
@ha-hold="${() => this._handleClick(true)}"
|
||||
.longPress="${longPress()}"
|
||||
></ha-icon>
|
||||
<div
|
||||
class="brightness"
|
||||
@ha-click="${() => this._handleClick(false)}"
|
||||
@ha-hold="${() => this._handleClick(true)}"
|
||||
.longPress="${longPress()}"
|
||||
></div>
|
||||
<div class="name">${this._config.name ||
|
||||
computeStateName(stateObj)}</div>
|
||||
<div class="not-found">
|
||||
Entity not available: ${this._config.entity}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
`
|
||||
: html`
|
||||
<div id="light"></div>
|
||||
<div id="tooltip">
|
||||
<div class="icon-state">
|
||||
<ha-icon
|
||||
data-state="${stateObj.state}"
|
||||
.icon="${stateIcon(stateObj)}"
|
||||
style="${
|
||||
styleMap({
|
||||
filter: this._computeBrightness(stateObj),
|
||||
color: this._computeColor(stateObj),
|
||||
})
|
||||
}"
|
||||
@ha-click="${() => this._handleClick(false)}"
|
||||
@ha-hold="${() => this._handleClick(true)}"
|
||||
.longPress="${longPress()}"
|
||||
></ha-icon>
|
||||
<div
|
||||
class="brightness"
|
||||
@ha-click="${() => this._handleClick(false)}"
|
||||
@ha-hold="${() => this._handleClick(true)}"
|
||||
.longPress="${longPress()}"
|
||||
></div>
|
||||
<div class="name">
|
||||
${this._config.name || computeStateName(stateObj)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
@ -153,7 +156,7 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
|
||||
|
||||
private renderStyle(): TemplateResult {
|
||||
return html`
|
||||
${roundSliderStyle}
|
||||
${roundSliderStyle}
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
@ -162,11 +165,8 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
--brightness-font-color: white;
|
||||
--brightness-font-text-shadow:
|
||||
-1px -1px 0 #000,
|
||||
1px -1px 0 #000,
|
||||
-1px 1px 0 #000,
|
||||
1px 1px 0 #000;
|
||||
--brightness-font-text-shadow: -1px -1px 0 #000, 1px -1px 0 #000,
|
||||
-1px 1px 0 #000, 1px 1px 0 #000;
|
||||
--name-font-size: 1.2rem;
|
||||
--brightness-font-size: 1.2rem;
|
||||
--rail-border-color: transparent;
|
||||
@ -185,35 +185,36 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: translate(0,25%);
|
||||
transform: translate(0, 25%);
|
||||
}
|
||||
#light {
|
||||
margin: 0 auto;
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
#light .rs-bar.rs-transition.rs-first, .rs-bar.rs-transition.rs-second{
|
||||
#light .rs-bar.rs-transition.rs-first,
|
||||
.rs-bar.rs-transition.rs-second {
|
||||
z-index: 20 !important;
|
||||
}
|
||||
#light .rs-range-color {
|
||||
#light .rs-range-color {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
#light .rs-path-color {
|
||||
background-color: var(--disabled-text-color);
|
||||
#light .rs-path-color {
|
||||
background-color: var(--disabled-text-color);
|
||||
}
|
||||
#light .rs-handle {
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
padding: 7px;
|
||||
border: 2px solid var(--disabled-text-color);
|
||||
#light .rs-handle {
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
padding: 7px;
|
||||
border: 2px solid var(--disabled-text-color);
|
||||
}
|
||||
#light .rs-handle.rs-focus {
|
||||
border-color:var(--primary-color);
|
||||
#light .rs-handle.rs-focus {
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
#light .rs-handle:after {
|
||||
border-color: var(--primary-color);
|
||||
background-color: var(--primary-color);
|
||||
#light .rs-handle:after {
|
||||
border-color: var(--primary-color);
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
#light .rs-border {
|
||||
#light .rs-border {
|
||||
border-color: var(--rail-border-color);
|
||||
}
|
||||
#light .rs-inner.rs-bg-color.rs-border,
|
||||
@ -227,10 +228,10 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
|
||||
color: var(--paper-item-icon-color, #44739e);
|
||||
cursor: pointer;
|
||||
}
|
||||
ha-icon[data-state=on] {
|
||||
color: var(--paper-item-icon-active-color, #FDD835);
|
||||
ha-icon[data-state="on"] {
|
||||
color: var(--paper-item-icon-active-color, #fdd835);
|
||||
}
|
||||
ha-icon[data-state=unavailable] {
|
||||
ha-icon[data-state="unavailable"] {
|
||||
color: var(--state-icon-unavailable-color);
|
||||
}
|
||||
.name {
|
||||
@ -245,12 +246,12 @@ export class HuiLightCard extends hassLocalizeLitMixin(LitElement)
|
||||
top: 10%;
|
||||
transform: translate(-50%);
|
||||
opacity: 0;
|
||||
transition: opacity .5s ease-in-out;
|
||||
-moz-transition: opacity .5s ease-in-out;
|
||||
-webkit-transition: opacity .5s ease-in-out;
|
||||
transition: opacity 0.5s ease-in-out;
|
||||
-moz-transition: opacity 0.5s ease-in-out;
|
||||
-webkit-transition: opacity 0.5s ease-in-out;
|
||||
cursor: pointer;
|
||||
color: var(--brightness-font-color);
|
||||
text-shadow: var(--brightness-font-text-shadow)
|
||||
text-shadow: var(--brightness-font-text-shadow);
|
||||
}
|
||||
.show_brightness {
|
||||
opacity: 1;
|
||||
|
||||
@ -68,7 +68,6 @@ class HuiMapCard extends PolymerElement {
|
||||
></paper-icon-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -42,9 +42,11 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard {
|
||||
${this.renderStyle()}
|
||||
<ha-card .header="${this._config.title}">
|
||||
<ha-markdown
|
||||
class="markdown ${classMap({
|
||||
"no-header": !this._config.title,
|
||||
})}"
|
||||
class="markdown ${
|
||||
classMap({
|
||||
"no-header": !this._config.title,
|
||||
})
|
||||
}"
|
||||
.content="${this._config.content}"
|
||||
></ha-markdown>
|
||||
</ha-card>
|
||||
|
||||
@ -24,8 +24,11 @@ class HuiPictureCard extends NavigateMixin(PolymerElement) {
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-card on-click="_cardClicked" clickable$='[[_computeClickable(_config)]]'>
|
||||
<img src='[[_config.image]]' />
|
||||
<ha-card
|
||||
on-click="_cardClicked"
|
||||
clickable$="[[_computeClickable(_config)]]"
|
||||
>
|
||||
<img src="[[_config.image]]" />
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -56,10 +56,11 @@ class HuiPictureElementsCard extends LitElement implements LovelaceCard {
|
||||
${this.renderStyle()}
|
||||
<ha-card .header="${this._config.title}">
|
||||
<div id="root">
|
||||
<img src="${this._config.image}">
|
||||
${this._config.elements.map((elementConfig: LovelaceElementConfig) =>
|
||||
this._createHuiElement(elementConfig)
|
||||
)}
|
||||
<img src="${this._config.image}" /> ${
|
||||
this._config.elements.map((elementConfig: LovelaceElementConfig) =>
|
||||
this._createHuiElement(elementConfig)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</ha-card>
|
||||
`;
|
||||
|
||||
@ -52,7 +52,7 @@ class HuiPictureEntityCard extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
}
|
||||
</style>
|
||||
|
||||
<ha-card id='card'>
|
||||
<ha-card id="card">
|
||||
<hui-image
|
||||
hass="[[hass]]"
|
||||
image="[[_config.image]]"
|
||||
@ -65,17 +65,13 @@ class HuiPictureEntityCard extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
<div class="footer both">
|
||||
<div>[[_name]]</div>
|
||||
<div>[[_state]]</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showName(_config)]]">
|
||||
<div class="footer">
|
||||
[[_name]]
|
||||
</div>
|
||||
<div class="footer">[[_name]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_showState(_config)]]">
|
||||
<div class="footer state">
|
||||
[[_state]]
|
||||
</div>
|
||||
<div class="footer state">[[_state]]</div>
|
||||
</template>
|
||||
</ha-card>
|
||||
`;
|
||||
|
||||
@ -59,7 +59,7 @@ class HuiPictureGlanceCard extends NavigateMixin(
|
||||
ha-icon {
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
color: #A9A9A9;
|
||||
color: #a9a9a9;
|
||||
}
|
||||
ha-icon.state-on {
|
||||
color: white;
|
||||
@ -68,8 +68,8 @@ class HuiPictureGlanceCard extends NavigateMixin(
|
||||
|
||||
<ha-card>
|
||||
<hui-image
|
||||
class$='[[_computeImageClass(_config)]]'
|
||||
on-click='_handleImageClick'
|
||||
class$="[[_computeImageClass(_config)]]"
|
||||
on-click="_handleImageClick"
|
||||
hass="[[hass]]"
|
||||
image="[[_config.image]]"
|
||||
state-image="[[_config.state_image]]"
|
||||
@ -82,7 +82,10 @@ class HuiPictureGlanceCard extends NavigateMixin(
|
||||
<div class="title">[[_config.title]]</div>
|
||||
</template>
|
||||
<div>
|
||||
<template is="dom-repeat" items="[[_computeVisible(_entitiesDialog, hass.states)]]">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[_computeVisible(_entitiesDialog, hass.states)]]"
|
||||
>
|
||||
<ha-icon
|
||||
on-click="_openDialog"
|
||||
class$="[[_computeButtonClass(item.entity, hass.states)]]"
|
||||
@ -92,7 +95,10 @@ class HuiPictureGlanceCard extends NavigateMixin(
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<template is="dom-repeat" items="[[_computeVisible(_entitiesToggle, hass.states)]]">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[_computeVisible(_entitiesToggle, hass.states)]]"
|
||||
>
|
||||
<ha-icon
|
||||
on-click="_callService"
|
||||
class$="[[_computeButtonClass(item.entity, hass.states)]]"
|
||||
|
||||
@ -62,20 +62,20 @@ class HuiSensorCard extends EventsMixin(LitElement) {
|
||||
render({ _config, _entity, _line } = this) {
|
||||
return html`
|
||||
${this._style()}
|
||||
<ha-card @click=${this._handleClick}>
|
||||
<div class='flex'>
|
||||
<div class='icon'>
|
||||
<ha-icon .icon=${this._computeIcon(_entity)}></ha-icon>
|
||||
<ha-card @click="${this._handleClick}">
|
||||
<div class="flex">
|
||||
<div class="icon">
|
||||
<ha-icon .icon="${this._computeIcon(_entity)}"></ha-icon>
|
||||
</div>
|
||||
<div class='header'>
|
||||
<span class='name'>${this._computeName(_entity)}</span>
|
||||
<div class="header">
|
||||
<span class="name">${this._computeName(_entity)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='flex info'>
|
||||
<span id='value'>${_entity.state}</span>
|
||||
<span id='measurement'>${this._computeUom(_entity)}</span>
|
||||
<div class="flex info">
|
||||
<span id="value">${_entity.state}</span>
|
||||
<span id="measurement">${this._computeUom(_entity)}</span>
|
||||
</div>
|
||||
<div class='graph'>
|
||||
<div class="graph">
|
||||
<div>
|
||||
${
|
||||
_line
|
||||
@ -89,7 +89,8 @@ class HuiSensorCard extends EventsMixin(LitElement) {
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>`;
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
_handleClick() {
|
||||
@ -225,7 +226,7 @@ class HuiSensorCard extends EventsMixin(LitElement) {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
opacity: .8;
|
||||
opacity: 0.8;
|
||||
position: relative;
|
||||
}
|
||||
.name {
|
||||
@ -235,7 +236,7 @@ class HuiSensorCard extends EventsMixin(LitElement) {
|
||||
font-weight: 500;
|
||||
max-height: 1.4rem;
|
||||
margin-top: 2px;
|
||||
opacity: .8;
|
||||
opacity: 0.8;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 1;
|
||||
@ -268,8 +269,8 @@ class HuiSensorCard extends EventsMixin(LitElement) {
|
||||
display: inline-block;
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.2em;
|
||||
margin-top: .1em;
|
||||
opacity: .6;
|
||||
margin-top: 0.1em;
|
||||
opacity: 0.6;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.graph {
|
||||
@ -283,7 +284,8 @@ class HuiSensorCard extends EventsMixin(LitElement) {
|
||||
align-self: flex-end;
|
||||
margin: auto 8px;
|
||||
}
|
||||
</style>`;
|
||||
</style>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -79,31 +79,33 @@ class HuiShoppingListCard extends hassLocalizeLitMixin(LitElement)
|
||||
return html`
|
||||
${this.renderStyle()}
|
||||
<ha-card .header="${this._config.title}">
|
||||
${repeat(
|
||||
this._items!,
|
||||
(item) => item.id,
|
||||
(item, index) =>
|
||||
html`
|
||||
<div class="editRow">
|
||||
<paper-checkbox
|
||||
slot="item-icon"
|
||||
id=${index}
|
||||
?checked=${item.complete}
|
||||
.itemId=${item.id}
|
||||
@click=${this._completeItem}
|
||||
tabindex='0'
|
||||
></paper-checkbox>
|
||||
<paper-item-body>
|
||||
<paper-input
|
||||
no-label-float
|
||||
.value='${item.name}'
|
||||
.itemId=${item.id}
|
||||
@change=${this._saveEdit}
|
||||
></paper-input>
|
||||
</paper-item-body>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
${
|
||||
repeat(
|
||||
this._items!,
|
||||
(item) => item.id,
|
||||
(item, index) =>
|
||||
html`
|
||||
<div class="editRow">
|
||||
<paper-checkbox
|
||||
slot="item-icon"
|
||||
id="${index}"
|
||||
?checked="${item.complete}"
|
||||
.itemId="${item.id}"
|
||||
@click="${this._completeItem}"
|
||||
tabindex="0"
|
||||
></paper-checkbox>
|
||||
<paper-item-body>
|
||||
<paper-input
|
||||
no-label-float
|
||||
.value="${item.name}"
|
||||
.itemId="${item.id}"
|
||||
@change="${this._saveEdit}"
|
||||
></paper-input>
|
||||
</paper-item-body>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
}
|
||||
</ha-card>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -56,9 +56,7 @@ export abstract class HuiStackCard extends LitElement implements LovelaceCard {
|
||||
|
||||
return html`
|
||||
${this.renderStyle()}
|
||||
<div id="root">
|
||||
${this._cards}
|
||||
</div>
|
||||
<div id="root">${this._cards}</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@ -97,9 +97,11 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
||||
${stateObj.attributes.current_temperature}
|
||||
${
|
||||
stateObj.attributes.current_temperature
|
||||
? html`<span class="uom">${
|
||||
this.hass.config.unit_system.temperature
|
||||
}</span>`
|
||||
? html`
|
||||
<span class="uom"
|
||||
>${this.hass.config.unit_system.temperature}</span
|
||||
>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
</span>
|
||||
@ -182,156 +184,157 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
||||
|
||||
private renderStyle(): TemplateResult {
|
||||
return html`
|
||||
${roundSliderStyle}
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
ha-card {
|
||||
overflow: hidden;
|
||||
--rail-border-color: transparent;
|
||||
--auto-color: green;
|
||||
--cool-color: #2b9af9;
|
||||
--heat-color: #FF8100;
|
||||
--off-color: #8a8a8a;
|
||||
--unknown-color: #bac;
|
||||
}
|
||||
#root {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.auto {
|
||||
--mode-color: var(--auto-color);
|
||||
}
|
||||
.cool {
|
||||
--mode-color: var(--cool-color);
|
||||
}
|
||||
.heat {
|
||||
--mode-color: var(--heat-color);
|
||||
}
|
||||
.off {
|
||||
--mode-color: var(--off-color);
|
||||
}
|
||||
.unknown-mode {
|
||||
--mode-color: var(--unknown-color);
|
||||
}
|
||||
.no-title {
|
||||
--title-margin-top: 33% !important;
|
||||
}
|
||||
.large {
|
||||
--thermostat-padding-top: 25px;
|
||||
--thermostat-margin-bottom: 25px;
|
||||
--title-font-size: 28px;
|
||||
--title-margin-top: 20%;
|
||||
--climate-info-margin-top: 17%;
|
||||
--modes-margin-top: 2%;
|
||||
--set-temperature-font-size: 25px;
|
||||
--current-temperature-font-size: 71px;
|
||||
--current-temperature-margin-top: 10%;
|
||||
--current-temperature-text-padding-left: 15px;
|
||||
--uom-font-size: 20px;
|
||||
--uom-margin-left: -18px;
|
||||
--current-mode-font-size: 18px;
|
||||
--set-temperature-padding-bottom: 5px;
|
||||
}
|
||||
.small {
|
||||
--thermostat-padding-top: 15px;
|
||||
--thermostat-margin-bottom: 15px;
|
||||
--title-font-size: 18px;
|
||||
--title-margin-top: 20%;
|
||||
--climate-info-margin-top: 7.5%;
|
||||
--modes-margin-top: 1%;
|
||||
--set-temperature-font-size: 16px;
|
||||
--current-temperature-font-size: 25px;
|
||||
--current-temperature-margin-top: 5%;
|
||||
--current-temperature-text-padding-left: 7px;
|
||||
--uom-font-size: 12px;
|
||||
--uom-margin-left: -5px;
|
||||
--current-mode-font-size: 14px;
|
||||
--set-temperature-padding-bottom: 0px;
|
||||
}
|
||||
#thermostat {
|
||||
margin: 0 auto var(--thermostat-margin-bottom);
|
||||
padding-top: var(--thermostat-padding-top);
|
||||
}
|
||||
#thermostat .rs-range-color {
|
||||
background-color: var(--mode-color, var(--disabled-text-color));
|
||||
}
|
||||
#thermostat .rs-path-color {
|
||||
${roundSliderStyle}
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
ha-card {
|
||||
overflow: hidden;
|
||||
--rail-border-color: transparent;
|
||||
--auto-color: green;
|
||||
--cool-color: #2b9af9;
|
||||
--heat-color: #ff8100;
|
||||
--off-color: #8a8a8a;
|
||||
--unknown-color: #bac;
|
||||
}
|
||||
#root {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.auto {
|
||||
--mode-color: var(--auto-color);
|
||||
}
|
||||
.cool {
|
||||
--mode-color: var(--cool-color);
|
||||
}
|
||||
.heat {
|
||||
--mode-color: var(--heat-color);
|
||||
}
|
||||
.off {
|
||||
--mode-color: var(--off-color);
|
||||
}
|
||||
.unknown-mode {
|
||||
--mode-color: var(--unknown-color);
|
||||
}
|
||||
.no-title {
|
||||
--title-margin-top: 33% !important;
|
||||
}
|
||||
.large {
|
||||
--thermostat-padding-top: 25px;
|
||||
--thermostat-margin-bottom: 25px;
|
||||
--title-font-size: 28px;
|
||||
--title-margin-top: 20%;
|
||||
--climate-info-margin-top: 17%;
|
||||
--modes-margin-top: 2%;
|
||||
--set-temperature-font-size: 25px;
|
||||
--current-temperature-font-size: 71px;
|
||||
--current-temperature-margin-top: 10%;
|
||||
--current-temperature-text-padding-left: 15px;
|
||||
--uom-font-size: 20px;
|
||||
--uom-margin-left: -18px;
|
||||
--current-mode-font-size: 18px;
|
||||
--set-temperature-padding-bottom: 5px;
|
||||
}
|
||||
.small {
|
||||
--thermostat-padding-top: 15px;
|
||||
--thermostat-margin-bottom: 15px;
|
||||
--title-font-size: 18px;
|
||||
--title-margin-top: 20%;
|
||||
--climate-info-margin-top: 7.5%;
|
||||
--modes-margin-top: 1%;
|
||||
--set-temperature-font-size: 16px;
|
||||
--current-temperature-font-size: 25px;
|
||||
--current-temperature-margin-top: 5%;
|
||||
--current-temperature-text-padding-left: 7px;
|
||||
--uom-font-size: 12px;
|
||||
--uom-margin-left: -5px;
|
||||
--current-mode-font-size: 14px;
|
||||
--set-temperature-padding-bottom: 0px;
|
||||
}
|
||||
#thermostat {
|
||||
margin: 0 auto var(--thermostat-margin-bottom);
|
||||
padding-top: var(--thermostat-padding-top);
|
||||
}
|
||||
#thermostat .rs-range-color {
|
||||
background-color: var(--mode-color, var(--disabled-text-color));
|
||||
}
|
||||
#thermostat .rs-path-color {
|
||||
background-color: var(--disabled-text-color);
|
||||
}
|
||||
#thermostat .rs-handle {
|
||||
}
|
||||
#thermostat .rs-handle {
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
padding: 7px;
|
||||
border: 2px solid var(--disabled-text-color);
|
||||
}
|
||||
#thermostat .rs-handle.rs-focus {
|
||||
}
|
||||
#thermostat .rs-handle.rs-focus {
|
||||
border-color: var(--mode-color, var(--disabled-text-color));
|
||||
}
|
||||
#thermostat .rs-handle:after {
|
||||
}
|
||||
#thermostat .rs-handle:after {
|
||||
border-color: var(--mode-color, var(--disabled-text-color));
|
||||
background-color: var(--mode-color, var(--disabled-text-color));
|
||||
}
|
||||
#thermostat .rs-border {
|
||||
border-color: var(--rail-border-color);
|
||||
}
|
||||
#thermostat .rs-bar.rs-transition.rs-first, .rs-bar.rs-transition.rs-second{
|
||||
z-index: 20 !important;
|
||||
}
|
||||
#thermostat .rs-inner.rs-bg-color.rs-border,
|
||||
#thermostat .rs-overlay.rs-transition.rs-bg-color {
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
}
|
||||
#tooltip {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
z-index: 15;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
#set-temperature {
|
||||
font-size: var(--set-temperature-font-size);
|
||||
padding-bottom: var(--set-temperature-padding-bottom);
|
||||
}
|
||||
.title {
|
||||
font-size: var(--title-font-size);
|
||||
margin-top: var(--title-margin-top);
|
||||
}
|
||||
.climate-info {
|
||||
margin-top: var(--climate-info-margin-top);
|
||||
}
|
||||
.current-mode {
|
||||
font-size: var(--current-mode-font-size);
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.modes {
|
||||
margin-top: var(--modes-margin-top);
|
||||
}
|
||||
.modes ha-icon {
|
||||
color: var(--disabled-text-color);
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
.modes ha-icon.selected-icon {
|
||||
color: var(--mode-color);
|
||||
}
|
||||
.current-temperature {
|
||||
margin-top: var(--current-temperature-margin-top);
|
||||
font-size: var(--current-temperature-font-size);
|
||||
}
|
||||
.current-temperature-text {
|
||||
padding-left: var(--current-temperature-text-padding-left);
|
||||
}
|
||||
.uom {
|
||||
font-size: var(--uom-font-size);
|
||||
vertical-align: top;
|
||||
margin-left: var(--uom-margin-left);
|
||||
}
|
||||
</style>
|
||||
}
|
||||
#thermostat .rs-border {
|
||||
border-color: var(--rail-border-color);
|
||||
}
|
||||
#thermostat .rs-bar.rs-transition.rs-first,
|
||||
.rs-bar.rs-transition.rs-second {
|
||||
z-index: 20 !important;
|
||||
}
|
||||
#thermostat .rs-inner.rs-bg-color.rs-border,
|
||||
#thermostat .rs-overlay.rs-transition.rs-bg-color {
|
||||
background-color: var(--paper-card-background-color, white);
|
||||
}
|
||||
#tooltip {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
z-index: 15;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
#set-temperature {
|
||||
font-size: var(--set-temperature-font-size);
|
||||
padding-bottom: var(--set-temperature-padding-bottom);
|
||||
}
|
||||
.title {
|
||||
font-size: var(--title-font-size);
|
||||
margin-top: var(--title-margin-top);
|
||||
}
|
||||
.climate-info {
|
||||
margin-top: var(--climate-info-margin-top);
|
||||
}
|
||||
.current-mode {
|
||||
font-size: var(--current-mode-font-size);
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.modes {
|
||||
margin-top: var(--modes-margin-top);
|
||||
}
|
||||
.modes ha-icon {
|
||||
color: var(--disabled-text-color);
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
.modes ha-icon.selected-icon {
|
||||
color: var(--mode-color);
|
||||
}
|
||||
.current-temperature {
|
||||
margin-top: var(--current-temperature-margin-top);
|
||||
font-size: var(--current-temperature-font-size);
|
||||
}
|
||||
.current-temperature-text {
|
||||
padding-left: var(--current-temperature-text-padding-left);
|
||||
}
|
||||
.uom {
|
||||
font-size: var(--uom-font-size);
|
||||
vertical-align: top;
|
||||
margin-left: var(--uom-margin-left);
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
}
|
||||
|
||||
@ -372,12 +375,14 @@ export class HuiThermostatCard extends hassLocalizeLitMixin(LitElement)
|
||||
if (!modeIcons[mode]) {
|
||||
return html``;
|
||||
}
|
||||
return html`<ha-icon
|
||||
class="${classMap({ "selected-icon": currentMode === mode })}"
|
||||
.mode="${mode}"
|
||||
.icon="${modeIcons[mode]}"
|
||||
@click="${this._handleModeClick}"
|
||||
></ha-icon>`;
|
||||
return html`
|
||||
<ha-icon
|
||||
class="${classMap({ "selected-icon": currentMode === mode })}"
|
||||
.mode="${mode}"
|
||||
.icon="${modeIcons[mode]}"
|
||||
@click="${this._handleModeClick}"
|
||||
></ha-icon>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleModeClick(e: MouseEvent): void {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user