Polymer 3 modulize (#1154)

* Version bump to 20180510.1

* Fix hass util

* Fix translations

* Bye paper-time-input

* Add webpack config

* Add webpack to package.json

* Fix translation import

* Disable web animations polyfill bad import

* Disable importHref import

* Update webpack config to build authorize.js

* Build translations json

* Build frontend correctly

* Run eslint --fix

* Load markdown JS on demand (#1155)

* Add HTML imports (#1160)

* Fix localize (#1161)

* Fix Roboto in build (#1162)

* Load web animations polyfill (#1163)

* P3: Fix chart js (#1164)

* P3: Fix Chart JS

* Update timeline package

* P3: panel resolver (#1165)

* WIP

* Initial importing of panels

* Fix panel resolver

* Fix automation and script editor (#1166)

* Expose Polymer and Polymer.Element on window (#1167)

* Remove unused import

* eslint --fix

* Es5 build (#1168)

* Build for ES5

* Fix build_frontend

* Remove stale comment

* Migrate to use paper-material-styles (#1170)

* Send parsed date to history/logbook (#1171)

* Fork app storage behavior (#1172)

* Add paper input with type time (#1173)

* Fix authorize

* Lint

* Sort imports

* Lint

* Remove eslint-html

* Do not lint authorize.html

* Fix polymer lint

* Try chrome 62 for wct

* P3: Add patched iconset (#1175)

* Add patched iconset

* Lint

* Test with latest Chrome again

* Use less window.hassUtil

* Teporarily use my fecha fork

* Import correct intl.messageFormat

* Update wct-browser-legacy to 1.0.0

* Include polyfill in right place

* Fix IntlMessageFormat

* Fix test not having a global scope

* Rollup <_<

* Fork app-localize-behavior

* Disable wct tests

* Lint
This commit is contained in:
Paulus Schoutsen 2018-05-15 13:31:47 -04:00 committed by GitHub
parent 205d6a8347
commit a4afc2e37a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
274 changed files with 12972 additions and 10037 deletions

View File

@ -1,12 +1,12 @@
{
"extends": "./.eslintrc-hound.json",
"plugins": [
"html",
"react"
],
"env": {
"browser": true
},
"parser": "babel-eslint",
"rules": {
"import/no-unresolved": 2,
"linebreak-style": 0

View File

@ -3,24 +3,23 @@ language: node_js
cache:
yarn: true
directories:
- bower_components
install:
- yarn install
- ./node_modules/.bin/bower install
- bower_components
install: yarn install
script:
- npm run build
- npm run test
- xvfb-run wct
- if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then wct --plugin sauce; fi
# - xvfb-run wct --module-resolution=node --npm
# - 'if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then wct --module-resolution=node --npm --plugin sauce; fi'
services:
- docker
before_deploy:
- docker pull lokalise/lokalise-cli@sha256:2198814ebddfda56ee041a4b427521757dd57f75415ea9693696a64c550cef21
- 'docker pull lokalise/lokalise-cli@sha256:2198814ebddfda56ee041a4b427521757dd57f75415ea9693696a64c550cef21'
deploy:
provider: script
script: script/travis_deploy
on:
'on':
branch: master
dist: trusty
addons:
sauce_connect: true

View File

@ -1,4 +1,5 @@
const gulp = require('gulp');
const path = require('path');
const replace = require('gulp-batch-replace');
const rename = require('gulp-rename');
@ -11,8 +12,12 @@ const {
const es5Extra = "<script src='/frontend_es5/custom-elements-es5-adapter.js'></script>";
async function buildAuth(es6) {
let stream = await bundledStreamFromHTML('src/authorize.html');
stream = stream.pipe(replace([['<!--EXTRA_SCRIPTS-->', es6 ? '' : es5Extra]]));
const frontendPath = es6 ? 'hass_frontend_latest' : 'hass_frontend_es5';
const stream = gulp.src(path.resolve(config.polymer_dir, 'src/authorize.html'))
.pipe(replace([
['<!--EXTRA_SCRIPTS-->', es6 ? '' : es5Extra],
['/home-assistant-polymer/build/webpack/ha-authorize.js', `/${frontendPath}/authorize.js`],
]));
return minifyStream(stream, /* es6= */ es6)
.pipe(rename('authorize.html'))

View File

@ -31,6 +31,7 @@ function renamePanel(path) {
}
function build(es6) {
return;
const strategy = composeStrategies([
generateShellMergeStrategy(polymerConfig.shell),
stripImportsStrategy([

View File

@ -8,8 +8,7 @@ const { minifyStream } = require('../common/transform');
const buildReplaces = {
'/home-assistant-polymer/build/core.js': 'core.js',
'/home-assistant-polymer/src/home-assistant.html': 'frontend.html',
'/home-assistant-polymer/src/resources/ha-chart-scripts.html': 'ha-chart-scripts.html',
'/home-assistant-polymer/build/webpack/app.js': 'app.js',
};
function generateIndex(es6) {

View File

@ -29,22 +29,13 @@ const staticFingerprinted = [
const staticFingerprintedEs6 = [
'core.js',
'frontend.html',
'ha-chart-scripts.html',
'app.js',
];
const staticFingerprintedEs5 = [
'compatibility.js',
'core.js',
'frontend.html',
'ha-chart-scripts.html',
];
// These panels will always be registered inside HA and thus can
// be safely assumed to be able to preload.
const panelsFingerprinted = [
'dev-event', 'dev-info', 'dev-service', 'dev-state', 'dev-template',
'dev-mqtt', 'kiosk',
'app.js',
];
function processStatic(fn, rootDir, urlDir) {

View File

@ -248,8 +248,7 @@ gulp.task(taskName, ['build-translation-fingerprints'], function () {
fragments: TRANSLATION_FRAGMENTS,
translations: data,
})))
.pipe(insert.wrap('<script>\nwindow.translationMetadata = ', ';\n</script>'))
.pipe(rename('translationMetadata.html'))
.pipe(rename('translationMetadata.json'))
.pipe(gulp.dest(workDir));
});
tasks.push(taskName);

View File

@ -1,13 +1,14 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../../src/components/hassio-card-content.js';
import '../../src/resources/hassio-style.js';
import '../../src/util/hass-mixins.js';
<link rel='import' href='../../src/components/hassio-card-content.html'>
<link rel='import' href='../../src/resources/hassio-style.html'>
<dom-module id="hassio-addon-repository">
<template>
class HassioAddonRepository extends window.hassMixins.NavigateMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style hassio-style">
paper-card {
cursor: pointer;
@ -17,35 +18,27 @@
color: var(--primary-text-color);
}
</style>
<template is='dom-if' if='[[addons.length]]'>
<div class='card-group'>
<div class='title'>
<template is="dom-if" if="[[addons.length]]">
<div class="card-group">
<div class="title">
[[repo.name]]
<div class='description'>
<div class="description">
Maintained by [[repo.maintainer]]
<a class='repo' href='[[repo.url]]' target='_blank'>[[repo.url]]</a>
<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
title='[[addon.name]]'
description='[[addon.description]]'
icon='[[computeIcon(addon)]]'
icon-title='[[computeIconTitle(addon)]]'
icon-class='[[computeIconClass(addon)]]'
></hassio-card-content>
<template is="dom-repeat" items="[[addons]]" as="addon" sort="sortAddons">
<paper-card on-click="addonTapped">
<div class="card-content">
<hassio-card-content 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>
</template>
</dom-module>
`;
}
<script>
class HassioAddonRepository extends window.hassMixins.NavigateMixin(Polymer.Element) {
static get is() { return 'hassio-addon-repository'; }
static get properties() {
@ -79,4 +72,3 @@ class HassioAddonRepository extends window.hassMixins.NavigateMixin(Polymer.Elem
}
customElements.define(HassioAddonRepository.is, HassioAddonRepository);
</script>

View File

@ -1,33 +1,26 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../../src/util/hass-mixins.js';
import './hassio-addon-repository.js';
import './hassio-repositories-editor.js';
<link rel="import" href="./hassio-repositories-editor.html">
<link rel="import" href="./hassio-addon-repository.html">
<dom-module id="hassio-addon-store">
<template>
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>
<hassio-repositories-editor hass="[[hass]]" repos="[[repos]]"></hassio-repositories-editor>
<template is='dom-repeat' items='[[repos]]' as='repo' sort='sortRepos'>
<hassio-addon-repository
repo='[[repo]]'
addons='[[computeAddons(repo.slug)]]'
></hassio-addon-repository>
<template is="dom-repeat" items="[[repos]]" as="repo" sort="sortRepos">
<hassio-addon-repository repo="[[repo]]" addons="[[computeAddons(repo.slug)]]"></hassio-addon-repository>
</template>
</template>
</dom-module>
`;
}
<script>
class HassioAddonStore extends Polymer.Element {
static get is() { return 'hassio-addon-store'; }
static get properties() {
@ -90,4 +83,3 @@ class HassioAddonStore extends Polymer.Element {
}
customElements.define(HassioAddonStore.is, HassioAddonStore);
</script>

View File

@ -1,108 +0,0 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel='import' href='../../bower_components/paper-input/paper-input.html'>
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
<link rel='import' href='../../src/components/hassio-card-content.html'>
<link rel='import' href='../../src/resources/hassio-style.html'>
<dom-module id="hassio-repositories-editor">
<template>
<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>
<template id='list' is='dom-repeat' items='[[repoList]]' as='repo' sort='sortRepos'>
<paper-card>
<div class='card-content'>
<hassio-card-content
title='[[repo.name]]'
description='[[repo.url]]'
icon='mdi: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 add'>
<iron-icon icon='mdi: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>
</template>
</dom-module>
<script>
class HassioRepositoriesEditor extends Polymer.Element {
static get is() { return 'hassio-repositories-editor'; }
static get properties() {
return {
hass: Object,
repos: {
type: Array,
observer: 'reposChanged',
},
repoList: Array,
repoUrl: String,
};
}
reposChanged(repos) {
this.repoList = repos.filter(repo => repo.slug !== 'core' && repo.slug !== 'local');
this.repoUrl = '';
}
sortRepos(a, b) {
return a.name < b.name ? -1 : 1;
}
computeRemoveRepoData(repoList, url) {
const list = repoList.filter(repo => repo.url !== url).map(repo => repo.url);
return { addons_repositories: list };
}
computeAddRepoData(repoList, url) {
const list = repoList.map(repo => repo.url);
list.push(url);
return { addons_repositories: list };
}
}
customElements.define(HassioRepositoriesEditor.is, HassioRepositoriesEditor);
</script>

View File

@ -0,0 +1,93 @@
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../src/components/buttons/ha-call-api-button.js';
import '../../src/components/hassio-card-content.js';
import '../../src/resources/hassio-style.js';
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:
</div>
</div>
<template id="list" is="dom-repeat" items="[[repoList]]" as="repo" sort="sortRepos">
<paper-card>
<div class="card-content">
<hassio-card-content title="[[repo.name]]" description="[[repo.url]]" icon="mdi: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 add">
<iron-icon icon="mdi: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>
`;
}
static get is() { return 'hassio-repositories-editor'; }
static get properties() {
return {
hass: Object,
repos: {
type: Array,
observer: 'reposChanged',
},
repoList: Array,
repoUrl: String,
};
}
reposChanged(repos) {
this.repoList = repos.filter(repo => repo.slug !== 'core' && repo.slug !== 'local');
this.repoUrl = '';
}
sortRepos(a, b) {
return a.name < b.name ? -1 : 1;
}
computeRemoveRepoData(repoList, url) {
const list = repoList.filter(repo => repo.url !== url).map(repo => repo.url);
return { addons_repositories: list };
}
computeAddRepoData(repoList, url) {
const list = repoList.map(repo => repo.url);
list.push(url);
return { addons_repositories: list };
}
}
customElements.define(HassioRepositoriesEditor.is, HassioRepositoriesEditor);

View File

@ -1,16 +1,19 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
<link rel='import' href='../../bower_components/neon-animation/web-animations.html'>
import 'web-animations-js/web-animations-next-lite.min.js';
<link rel='import' href='../../src/resources/ha-style.html'>
<link rel='import' href='../../src/util/hass-mixins.html'>
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="hassio-addon-audio">
<template>
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
class HassioAddonAudio extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style">
:host,
paper-card,
@ -28,38 +31,34 @@
text-align: right;
}
</style>
<paper-card heading='Audio'>
<paper-card heading="Audio">
<div class="card-content">
<template is='dom-if' if='[[error]]'>
<div class='errors'>[[error]]</div>
<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 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 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>
<paper-button on-click="_saveSettings">Save</paper-button>
</div>
</paper-card>
</template>
</dom-module>
`;
}
<script>
class HassioAddonAudio extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-addon-audio'; }
static get properties() {
@ -116,4 +115,3 @@ class HassioAddonAudio extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HassioAddonAudio.is, HassioAddonAudio);
</script>

View File

@ -1,12 +1,14 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
import '../../src/components/buttons/ha-call-api-button.js';
<dom-module id="hassio-addon-config">
<template>
class HassioAddonConfig extends PolymerElement {
static get template() {
return html`
<style include="ha-style">
:host {
display: block;
@ -30,31 +32,21 @@
color: var(--google-red-500);
}
</style>
<paper-card heading='Config'>
<paper-card heading="Config">
<div class="card-content">
<template is='dom-if' if='[[error]]'>
<div class='errors'>[[error]]</div>
<template is="dom-if" if="[[error]]">
<div class="errors">[[error]]</div>
</template>
<iron-autogrow-textarea id='config' value="{{config}}"></iron-autogrow-textarea>
<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>
<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>
</template>
</dom-module>
`;
}
<script>
class HassioAddonConfig extends Polymer.Element {
static get is() { return 'hassio-addon-config'; }
static get properties() {
@ -106,4 +98,3 @@ class HassioAddonConfig extends Polymer.Element {
}
customElements.define(HassioAddonConfig.is, HassioAddonConfig);
</script>

View File

@ -1,275 +0,0 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel='import' href='../../bower_components/paper-card/paper-card.html'>
<link rel='import' href='../../bower_components/paper-toggle-button/paper-toggle-button.html'>
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
<link rel='import' href='../../src/components/ha-markdown.html'>
<link rel='import' href='../../src/resources/ha-style.html'>
<link rel='import' href='../../src/components/hassio-card-content.html'>
<link rel='import' href='../../src/util/hass-mixins.html'>
<dom-module id="hassio-addon-info">
<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;
}
</style>
<template is='dom-if' if='[[computeUpdateAvailable(addon)]]'>
<paper-card heading='Update available! 🎉'>
<div class='card-content'>
<hassio-card-content
title='[[addon.name]] [[addon.last_version]] is available'
description='You are currently running version [[addon.version]]'
icon='mdi: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='mdi:circle'
></iron-icon>
</template>
<template is='dom-if' if='[[!isRunning]]'>
<iron-icon
title='Add-on is stopped'
class='stopped'
icon='mdi: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>
</paper-card>
</template>
</template>
</dom-module>
<script>
class HassioAddonInfo extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-addon-info'; }
static get properties() {
return {
hass: Object,
addon: Object,
addonSlug: String,
isRunning: {
type: Boolean,
computed: 'computeIsRunning(addon)',
},
};
}
computeIsRunning(addon) {
return addon && addon.state === 'started';
}
computeUpdateAvailable(addon) {
return addon && !addon.detached && addon.version && addon.version !== addon.last_version;
}
pathWebui(webui) {
return webui && webui.replace('[HOST]', document.location.hostname);
}
computeShowWebUI(webui, isRunning) {
return webui && isRunning;
}
computeStartOnBoot(state) {
return state === 'auto';
}
startOnBootToggled() {
const data = { boot: this.addon.boot === 'auto' ? 'manual' : 'auto' };
this.hass.callApi('POST', `hassio/addons/${this.addonSlug}/options`, data);
}
autoUpdateToggled() {
const data = { auto_update: !this.addon.auto_update };
this.hass.callApi('POST', `hassio/addons/${this.addonSlug}/options`, data);
}
openChangelog() {
this.hass.callApi('get', `hassio/addons/${this.addonSlug}/changelog`)
.then(
resp => resp
, () => 'Error getting changelog'
).then((content) => {
this.fire('hassio-markdown-dialog', {
title: 'Changelog',
content: content,
});
});
}
_unistallClicked() {
if (!confirm('Are you sure you want to uninstall this add-on?')) {
return;
}
const path = `hassio/addons/${this.addonSlug}/uninstall`;
const eventData = {
path: path,
};
this.hass.callApi('post', path).then((resp) => {
eventData.success = true;
eventData.response = resp;
}, (resp) => {
eventData.success = false;
eventData.response = resp;
}).then(() => {
this.fire('hass-api-called', eventData);
});
}
}
customElements.define(HassioAddonInfo.is, HassioAddonInfo);
</script>

View File

@ -0,0 +1,225 @@
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../src/components/buttons/ha-call-api-button.js';
import '../../src/components/ha-markdown.js';
import '../../src/components/hassio-card-content.js';
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
class HassioAddonInfo extends window.hassMixins.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;
}
</style>
<template is="dom-if" if="[[computeUpdateAvailable(addon)]]">
<paper-card heading="Update available! 🎉">
<div class="card-content">
<hassio-card-content title="[[addon.name]] [[addon.last_version]] is available" description="You are currently running version [[addon.version]]" icon="mdi: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="mdi:circle"></iron-icon>
</template>
<template is="dom-if" if="[[!isRunning]]">
<iron-icon title="Add-on is stopped" class="stopped" icon="mdi: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>
</paper-card>
</template>
`;
}
static get is() { return 'hassio-addon-info'; }
static get properties() {
return {
hass: Object,
addon: Object,
addonSlug: String,
isRunning: {
type: Boolean,
computed: 'computeIsRunning(addon)',
},
};
}
computeIsRunning(addon) {
return addon && addon.state === 'started';
}
computeUpdateAvailable(addon) {
return addon && !addon.detached && addon.version && addon.version !== addon.last_version;
}
pathWebui(webui) {
return webui && webui.replace('[HOST]', document.location.hostname);
}
computeShowWebUI(webui, isRunning) {
return webui && isRunning;
}
computeStartOnBoot(state) {
return state === 'auto';
}
startOnBootToggled() {
const data = { boot: this.addon.boot === 'auto' ? 'manual' : 'auto' };
this.hass.callApi('POST', `hassio/addons/${this.addonSlug}/options`, data);
}
autoUpdateToggled() {
const data = { auto_update: !this.addon.auto_update };
this.hass.callApi('POST', `hassio/addons/${this.addonSlug}/options`, data);
}
openChangelog() {
this.hass.callApi('get', `hassio/addons/${this.addonSlug}/changelog`)
.then(
resp => resp
, () => 'Error getting changelog'
).then((content) => {
this.fire('hassio-markdown-dialog', {
title: 'Changelog',
content: content,
});
});
}
_unistallClicked() {
if (!confirm('Are you sure you want to uninstall this add-on?')) {
return;
}
const path = `hassio/addons/${this.addonSlug}/uninstall`;
const eventData = {
path: path,
};
this.hass.callApi('post', path).then((resp) => {
eventData.success = true;
eventData.response = resp;
}, (resp) => {
eventData.success = false;
eventData.response = resp;
}).then(() => {
this.fire('hass-api-called', eventData);
});
}
}
customElements.define(HassioAddonInfo.is, HassioAddonInfo);

View File

@ -1,30 +1,30 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/resources/ha-style.html'>
import '../../src/resources/ha-style.js';
<dom-module id="hassio-addon-logs">
<template>
class HassioAddonLogs extends PolymerElement {
static get template() {
return html`
<style include="ha-style">
:host,
paper-card {
display: block;
}
</style>
<paper-card heading='Log'>
<paper-card heading="Log">
<div class="card-content">
<pre>[[log]]</pre>
</div>
<div class="card-actions">
<paper-button on-click='refresh'>Refresh</paper-button>
<paper-button on-click="refresh">Refresh</paper-button>
</div>
</paper-card>
</template>
</dom-module>
`;
}
<script>
class HassioAddonLogs extends Polymer.Element {
static get is() { return 'hassio-addon-logs'; }
static get properties() {
@ -56,4 +56,3 @@ class HassioAddonLogs extends Polymer.Element {
}
customElements.define(HassioAddonLogs.is, HassioAddonLogs);
</script>

View File

@ -1,14 +1,15 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel='import' href='../../src/resources/ha-style.html'>
import '../../src/components/buttons/ha-call-api-button.js';
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
<dom-module id="hassio-addon-network">
<template>
class HassioAddonNetwork extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style">
:host {
display: block;
@ -25,52 +26,37 @@
@apply --layout-justified;
}
</style>
<paper-card heading='Network'>
<paper-card heading="Network">
<div class="card-content">
<template is='dom-if' if='[[error]]'>
<div class='errors'>[[error]]</div>
<template is="dom-if" if="[[error]]">
<div class="errors">[[error]]</div>
</template>
<table>
<tr>
<tbody><tr>
<th>Container</th>
<th>Host</th>
</tr>
<template
is='dom-repeat'
items='[[config]]'
>
<template is="dom-repeat" items="[[config]]">
<tr>
<td>
[[item.container]]
</td>
<td>
<paper-input
value='{{item.host}}'
no-label-float
></paper-input>
<paper-input value="{{item.host}}" no-label-float=""></paper-input>
</td>
</tr>
</template>
</table>
</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>
<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>
</template>
</dom-module>
`;
}
<script>
class HassioAddonNetwork extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-addon-network'; }
static get properties() {
@ -122,4 +108,3 @@ class HassioAddonNetwork extends window.hassMixins.EventsMixin(Polymer.Element)
}
customElements.define(HassioAddonNetwork.is, HassioAddonNetwork);
</script>

View File

@ -1,165 +0,0 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/app-route/app-route.html'>
<link rel='import' href='../../bower_components/app-layout/app-header-layout/app-header-layout.html'>
<link rel='import' href='../../bower_components/app-layout/app-header/app-header.html'>
<link rel='import' href='../../bower_components/app-layout/app-toolbar/app-toolbar.html'>
<link rel='import' href='../../bower_components/paper-icon-button/paper-icon-button.html'>
<link rel='import' href='../../src/components/ha-menu-button.html'>
<link rel='import' href='../../src/resources/ha-style.html'>
<link rel="import" href="./hassio-addon-info.html">
<link rel="import" href="./hassio-addon-config.html">
<link rel="import" href="./hassio-addon-audio.html">
<link rel="import" href="./hassio-addon-network.html">
<link rel="import" href="./hassio-addon-logs.html">
<link rel='import' href='../hassio-markdown-dialog.html'>
<dom-module id="hassio-addon-view">
<template>
<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;
max-width: 600px;
margin: 0 auto;
}
hassio-addon-info,
hassio-addon-network,
hassio-addon-audio,
hassio-addon-config {
margin-bottom: 24px;
}
</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 narrow='[[narrow]]' show-menu='[[showMenu]]'></ha-menu-button>
<paper-icon-button
icon='mdi: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.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>
<hassio-markdown-dialog
title='[[markdownTitle]]'
content='[[markdownContent]]'
></hassio-markdown-dialog>
</template>
</dom-module>
<script>
class HassioAddonView extends Polymer.Element {
static get is() { return 'hassio-addon-view'; }
static get properties() {
return {
hass: Object,
showMenu: Boolean,
narrow: Boolean,
route: Object,
routeData: {
type: Object,
observer: 'routeDataChanged',
},
routeMatches: Boolean,
addon: Object,
markdownTitle: String,
markdownContent: {
type: String,
value: '',
},
};
}
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener('hassio-markdown-dialog', ev => this.openMarkdown(ev));
}
apiCalled(ev) {
const path = ev.detail.path;
if (!path) return;
if (path.substr(path.lastIndexOf('/') + 1) === 'uninstall') {
this.backTapped();
} else {
this.routeDataChanged(this.routeData);
}
}
routeDataChanged(routeData) {
if (!this.routeMatches || !routeData || !routeData.slug) return;
this.hass.callApi('get', `hassio/addons/${routeData.slug}/info`)
.then((info) => {
this.addon = info.data;
}, () => {
this.addon = null;
});
}
backTapped() {
history.back();
}
openMarkdown(ev) {
this.setProperties({
markdownTitle: ev.detail.title,
markdownContent: ev.detail.content,
});
this.shadowRoot.querySelector('hassio-markdown-dialog').openDialog();
}
}
customElements.define(HassioAddonView.is, HassioAddonView);
</script>

View File

@ -0,0 +1,134 @@
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/app-route/app-route.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
import '../hassio-markdown-dialog.js';
import './hassio-addon-audio.js';
import './hassio-addon-config.js';
import './hassio-addon-info.js';
import './hassio-addon-logs.js';
import './hassio-addon-network.js';
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;
max-width: 600px;
margin: 0 auto;
}
hassio-addon-info,
hassio-addon-network,
hassio-addon-audio,
hassio-addon-config {
margin-bottom: 24px;
}
</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 narrow="[[narrow]]" show-menu="[[showMenu]]"></ha-menu-button>
<paper-icon-button icon="mdi: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.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>
<hassio-markdown-dialog title="[[markdownTitle]]" content="[[markdownContent]]"></hassio-markdown-dialog>
`;
}
static get is() { return 'hassio-addon-view'; }
static get properties() {
return {
hass: Object,
showMenu: Boolean,
narrow: Boolean,
route: Object,
routeData: {
type: Object,
observer: 'routeDataChanged',
},
routeMatches: Boolean,
addon: Object,
markdownTitle: String,
markdownContent: {
type: String,
value: '',
},
};
}
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
this.addEventListener('hassio-markdown-dialog', ev => this.openMarkdown(ev));
}
apiCalled(ev) {
const path = ev.detail.path;
if (!path) return;
if (path.substr(path.lastIndexOf('/') + 1) === 'uninstall') {
this.backTapped();
} else {
this.routeDataChanged(this.routeData);
}
}
routeDataChanged(routeData) {
if (!this.routeMatches || !routeData || !routeData.slug) return;
this.hass.callApi('get', `hassio/addons/${routeData.slug}/info`)
.then((info) => {
this.addon = info.data;
}, () => {
this.addon = null;
});
}
backTapped() {
history.back();
}
openMarkdown(ev) {
this.setProperties({
markdownTitle: ev.detail.title,
markdownContent: ev.detail.content,
});
this.shadowRoot.querySelector('hassio-markdown-dialog').openDialog();
}
}
customElements.define(HassioAddonView.is, HassioAddonView);

View File

@ -1,45 +1,39 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/paper-card/paper-card.html'>
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel='import' href='../../src/components/hassio-card-content.html'>
<link rel='import' href='../../src/resources/hassio-style.html'>
import '../../src/components/hassio-card-content.js';
import '../../src/resources/hassio-style.js';
import '../../src/util/hass-mixins.js';
<dom-module id='hassio-addons'>
<template>
<style include='ha-style hassio-style'>
class HassioAddons extends window.hassMixins.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]]'>
<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 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
title='[[addon.name]]'
description='[[addon.description]]'
icon='[[computeIcon(addon)]]'
icon-title='[[computeIconTitle(addon)]]'
icon-class='[[computeIconClass(addon)]]'
></hassio-card-content>
<template is="dom-repeat" items="[[addons]]" as="addon" sort="sortAddons">
<paper-card on-click="addonTapped">
<div class="card-content">
<hassio-card-content 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>
</dom-module>
`;
}
<script>
class HassioAddons extends window.hassMixins.NavigateMixin(Polymer.Element) {
static get is() { return 'hassio-addons'; }
static get properties() {
@ -79,4 +73,3 @@ class HassioAddons extends window.hassMixins.NavigateMixin(Polymer.Element) {
}
customElements.define(HassioAddons.is, HassioAddons);
</script>

View File

@ -1,40 +0,0 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="./hassio-addons.html">
<link rel="import" href="./hassio-hass-update.html">
<dom-module id="hassio-dashboard">
<template>
<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>
</template>
</dom-module>
<script>
class HassioDashboard extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-dashboard'; }
static get properties() {
return {
hass: Object,
supervisorInfo: Object,
hassInfo: Object,
};
}
}
customElements.define(HassioDashboard.is, HassioDashboard);
</script>

View File

@ -0,0 +1,33 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import './hassio-addons.js';
import './hassio-hass-update.js';
class HassioDashboard extends window.hassMixins.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>
`;
}
static get is() { return 'hassio-dashboard'; }
static get properties() {
return {
hass: Object,
supervisorInfo: Object,
hassInfo: Object,
};
}
}
customElements.define(HassioDashboard.is, HassioDashboard);

View File

@ -1,93 +0,0 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
<link rel='import' href='../../src/components/hassio-card-content.html'>
<link rel='import' href='../../src/resources/hassio-style.html'>
<dom-module id="hassio-hass-update">
<template>
<style include="ha-style hassio-style">
paper-card {
display: block;
height: 100%;
margin-bottom: 32px;
}
.errors {
color: var(--google-red-500);
margin-top: 16px;
}
</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
title='Home Assistant [[hassInfo.last_version]] is available'
description='You are currently running version [[hassInfo.version]]'
icon='mdi:home-assistant'
icon-class='hassupdate'
></hassio-card-content>
<template is='dom-if' if='[[error]]'>
<div class='error'>Error: [[error]]</div>
</template>
</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>
</template>
</template>
</dom-module>
<script>
class HassioHassUpdate extends Polymer.Element {
static get is() { return 'hassio-hass-update'; }
static get properties() {
return {
hass: Object,
hassInfo: Object,
error: String,
};
}
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
}
apiCalled(ev) {
if (ev.detail.success) {
this.errors = null;
return;
}
const response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
} else {
this.errors = response.body;
}
}
computeUpdateAvailable(hassInfo) {
return hassInfo.version !== hassInfo.last_version;
}
}
customElements.define(HassioHassUpdate.is, HassioHassUpdate);
</script>

View File

@ -0,0 +1,81 @@
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../src/components/buttons/ha-call-api-button.js';
import '../../src/components/hassio-card-content.js';
import '../../src/resources/hassio-style.js';
class HassioHassUpdate extends PolymerElement {
static get template() {
return html`
<style include="ha-style hassio-style">
paper-card {
display: block;
height: 100%;
margin-bottom: 32px;
}
.errors {
color: var(--google-red-500);
margin-top: 16px;
}
</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 title="Home Assistant [[hassInfo.last_version]] is available" description="You are currently running version [[hassInfo.version]]" icon="mdi:home-assistant" icon-class="hassupdate"></hassio-card-content>
<template is="dom-if" if="[[error]]">
<div class="error">Error: [[error]]</div>
</template>
</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>
</template>
`;
}
static get is() { return 'hassio-hass-update'; }
static get properties() {
return {
hass: Object,
hassInfo: Object,
error: String,
};
}
ready() {
super.ready();
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
}
apiCalled(ev) {
if (ev.detail.success) {
this.errors = null;
return;
}
const response = ev.detail.response;
if (typeof response.body === 'object') {
this.errors = response.body.message || 'Unknown error';
} else {
this.errors = response.body;
}
}
computeUpdateAvailable(hassInfo) {
return hassInfo.version !== hassInfo.last_version;
}
}
customElements.define(HassioHassUpdate.is, HassioHassUpdate);

View File

@ -1,21 +1,17 @@
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="./hassio-main.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="hassio-app">
<template>
<template is='dom-if' if='[[hass]]'>
<hassio-main
hass='[[hass]]'
narrow='[[narrow]]'
show-menu='[[showMenu]]'
route='[[route]]'
></hassio-main>
import './hassio-main.js';
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>
</dom-module>
`;
}
<script>
class HassioApp extends Polymer.Element {
static get is() { return 'hassio-app'; }
static get properties() {
@ -49,4 +45,3 @@ class HassioApp extends Polymer.Element {
}
customElements.define(HassioApp.is, HassioApp);
</script>

View File

@ -1,7 +1,6 @@
<link rel="import" href="../bower_components/polymer/polymer-element.html">
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<script>
class HassioData extends Polymer.Element {
class HassioData extends PolymerElement {
static get is() { return 'hassio-data'; }
static get properties() {
@ -61,4 +60,3 @@ class HassioData extends Polymer.Element {
}
customElements.define(HassioData.is, HassioData);
</script>

View File

@ -1,132 +0,0 @@
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="../bower_components/app-route/app-route.html">
<link rel="import" href="../src/layouts/hass-loading-screen.html">
<link rel='import' href='../src/util/hass-util.html'>
<link rel='import' href='./hassio-data.html'>
<link rel='import' href='./hassio-pages-with-tabs.html'>
<link rel='import' href='./addon-view/hassio-addon-view.html'>
<dom-module id="hassio-main">
<template>
<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]]'>
<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>
</dom-module>
<script>
class HassioMain extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-main'; }
static get properties() {
return {
hass: Object,
narrow: Boolean,
showMenu: Boolean,
route: {
type: Object,
// Fake route object
value: {
prefix: '/hassio',
path: '/dashboard',
__queryParams: {}
},
observer: 'routeChanged',
},
routeData: Object,
supervisorInfo: Object,
hostInfo: Object,
hassInfo: Object,
loaded: {
type: Boolean,
computed: 'computeIsLoaded(supervisorInfo, hostInfo, hassInfo)',
},
};
}
ready() {
super.ready();
window.hassUtil.applyThemesOnElement(this, this.hass.themes, this.hass.selectedTheme, true);
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
}
connectedCallback() {
super.connectedCallback();
this.routeChanged(this.route);
}
apiCalled(ev) {
if (ev.detail.success) {
let tries = 1;
const tryUpdate = () => {
this.$.data.refresh().catch(function () {
tries += 1;
setTimeout(tryUpdate, Math.min(tries, 5) * 1000);
});
};
tryUpdate();
}
}
computeIsLoaded(supervisorInfo, hostInfo, hassInfo) {
return (supervisorInfo !== null &&
hostInfo !== null &&
hassInfo !== null);
}
routeChanged(route) {
if (route.path === '' && route.prefix === '/hassio') {
history.replaceState(null, null, '/hassio/dashboard');
this.fire('location-changed');
}
}
equalsAddon(page) {
return page && page === 'addon';
}
}
customElements.define(HassioMain.is, HassioMain);
</script>

104
hassio/hassio-main.js Normal file
View File

@ -0,0 +1,104 @@
import '@polymer/app-route/app-route.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../src/layouts/hass-loading-screen.js';
import '../src/util/hass-util.js';
import './addon-view/hassio-addon-view.js';
import './hassio-data.js';
import './hassio-pages-with-tabs.js';
class HassioMain extends window.hassMixins.EventsMixin(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>
<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>
<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 is() { return 'hassio-main'; }
static get properties() {
return {
hass: Object,
narrow: Boolean,
showMenu: Boolean,
route: {
type: Object,
// Fake route object
value: {
prefix: '/hassio',
path: '/dashboard',
__queryParams: {}
},
observer: 'routeChanged',
},
routeData: Object,
supervisorInfo: Object,
hostInfo: Object,
hassInfo: Object,
loaded: {
type: Boolean,
computed: 'computeIsLoaded(supervisorInfo, hostInfo, hassInfo)',
},
};
}
ready() {
super.ready();
window.hassUtil.applyThemesOnElement(this, this.hass.themes, this.hass.selectedTheme, true);
this.addEventListener('hass-api-called', ev => this.apiCalled(ev));
}
connectedCallback() {
super.connectedCallback();
this.routeChanged(this.route);
}
apiCalled(ev) {
if (ev.detail.success) {
let tries = 1;
const tryUpdate = () => {
this.$.data.refresh().catch(function () {
tries += 1;
setTimeout(tryUpdate, Math.min(tries, 5) * 1000);
});
};
tryUpdate();
}
}
computeIsLoaded(supervisorInfo, hostInfo, hassInfo) {
return (supervisorInfo !== null &&
hostInfo !== null &&
hassInfo !== null);
}
routeChanged(route) {
if (route.path === '' && route.prefix === '/hassio') {
history.replaceState(null, null, '/hassio/dashboard');
this.fire('location-changed');
}
}
equalsAddon(page) {
return page && page === 'addon';
}
}
customElements.define(HassioMain.is, HassioMain);

View File

@ -1,15 +1,17 @@
<link rel='import' href='../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../bower_components/paper-dialog/paper-dialog.html'>
<link rel='import' href='../bower_components/app-layout/app-toolbar/app-toolbar.html'>
<link rel='import' href='../bower_components/paper-icon-button/paper-icon-button.html'>
<link rel='import' href='../bower_components/paper-dialog-scrollable/paper-dialog-scrollable.html'>
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';
import '@polymer/paper-dialog/paper-dialog.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../src/components/ha-markdown.html'>
<link rel='import' href='../src/resources/ha-style.html'>
import '../src/components/ha-markdown.js';
import '../src/resources/ha-style.js';
<dom-module id='hassio-markdown-dialog'>
<template>
<style include='ha-style-dialog'>
class HassioMarkdownDialog extends PolymerElement {
static get template() {
return html`
<style include="ha-style-dialog">
paper-dialog {
min-width: 350px;
font-size: 14px;
@ -48,26 +50,18 @@
}
}
</style>
<paper-dialog
id='dialog'
with-backdrop
>
<paper-dialog id="dialog" with-backdrop="">
<app-toolbar>
<paper-icon-button
icon='mdi:close'
dialog-dismiss
></paper-icon-button>
<div main-title>[[title]]</div>
<paper-icon-button icon="mdi:close" dialog-dismiss=""></paper-icon-button>
<div main-title="">[[title]]</div>
</app-toolbar>
<paper-dialog-scrollable>
<ha-markdown content='[[content]]'></ha-markdown>
<ha-markdown content="[[content]]"></ha-markdown>
</paper-dialog-scrollable>
</paper-dialog>
</template>
</dom-module>
`;
}
<script>
class HassioMarkdownDialog extends Polymer.Element {
static get is() { return 'hassio-markdown-dialog'; }
static get properties() {
@ -82,4 +76,3 @@ class HassioMarkdownDialog extends Polymer.Element {
}
}
customElements.define(HassioMarkdownDialog.is, HassioMarkdownDialog);
</script>

View File

@ -1,163 +0,0 @@
<link rel='import' href='../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../bower_components/app-layout/app-header-layout/app-header-layout.html'>
<link rel='import' href='../bower_components/app-layout/app-header/app-header.html'>
<link rel='import' href='../bower_components/app-layout/app-toolbar/app-toolbar.html'>
<link rel='import' href='../bower_components/paper-tabs/paper-tabs.html'>
<link rel='import' href='../bower_components/paper-tabs/paper-tab.html'>
<link rel='import' href='../bower_components/paper-icon-button/paper-icon-button.html'>
<link rel='import' href='../src/components/ha-menu-button.html'>
<link rel='import' href='../src/util/hass-mixins.html'>
<link rel='import' href='../src/resources/ha-style.html'>
<link rel='import' href='./dashboard/hassio-dashboard.html'>
<link rel='import' href='./snapshots/hassio-snapshots.html'>
<link rel='import' href='./snapshots/hassio-snapshot.html'>
<link rel='import' href='./addon-store/hassio-addon-store.html'>
<link rel='import' href='./system/hassio-system.html'>
<link rel='import' href='./hassio-markdown-dialog.html'>
<dom-module id='hassio-pages-with-tabs'>
<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 has-scrolling-region>
<app-header fixed slot='header'>
<app-toolbar>
<ha-menu-button 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='mdi: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-snapshot
hass='[[hass]]'
snapshot-slug='{{snapshotSlug}}'
snapshot-deleted='{{snapshotDeleted}}'
></hassio-snapshot>
</template>
</template>
</dom-module>
<script>
class HassioPagesWithTabs extends window.hassMixins.NavigateMixin(Polymer.Element) {
static get is() { return 'hassio-pages-with-tabs'; }
static get properties() {
return {
hass: Object,
showMenu: Boolean,
narrow: Boolean,
page: String,
supervisorInfo: Object,
hostInfo: Object,
hassInfo: Object,
snapshotSlug: String,
snapshotDeleted: Boolean,
markdownTitle: String,
markdownContent: {
type: String,
value: '',
},
};
}
ready() {
super.ready();
this.addEventListener('hassio-markdown-dialog', ev => this.openMarkdown(ev));
}
handlePageSelected(ev) {
const newPage = ev.detail.item.getAttribute('page-name');
if (newPage !== this.page) {
this.navigate(`/hassio/${newPage}`);
}
}
equals(a, b) {
return a === b;
}
showRefreshButton(page) {
return page === 'store' || page === 'snapshots';
}
refreshClicked() {
if (this.page === 'snapshots') {
this.shadowRoot.querySelector('hassio-snapshots').refreshData();
} else {
this.shadowRoot.querySelector('hassio-addon-store').refreshData();
}
}
openMarkdown(ev) {
this.setProperties({
markdownTitle: ev.detail.title,
markdownContent: ev.detail.content,
});
this.shadowRoot.querySelector('hassio-markdown-dialog').openDialog();
}
}
customElements.define(HassioPagesWithTabs.is, HassioPagesWithTabs);
</script>

View File

@ -0,0 +1,131 @@
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-tabs/paper-tab.js';
import '@polymer/paper-tabs/paper-tabs.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../src/components/ha-menu-button.js';
import '../src/resources/ha-style.js';
import '../src/util/hass-mixins.js';
import './addon-store/hassio-addon-store.js';
import './dashboard/hassio-dashboard.js';
import './hassio-markdown-dialog.js';
import './snapshots/hassio-snapshot.js';
import './snapshots/hassio-snapshots.js';
import './system/hassio-system.js';
class HassioPagesWithTabs extends window.hassMixins.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 has-scrolling-region="">
<app-header fixed="" slot="header">
<app-toolbar>
<ha-menu-button 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="mdi: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, &quot;dashboard&quot;)]]">
<hassio-dashboard hass="[[hass]]" supervisor-info="[[supervisorInfo]]" hass-info="[[hassInfo]]"></hassio-dashboard>
</template>
<template is="dom-if" if="[[equals(page, &quot;snapshots&quot;)]]">
<hassio-snapshots hass="[[hass]]" installed-addons="[[supervisorInfo.addons]]" snapshot-slug="{{snapshotSlug}}" snapshot-deleted="{{snapshotDeleted}}"></hassio-snapshots>
</template>
<template is="dom-if" if="[[equals(page, &quot;store&quot;)]]">
<hassio-addon-store hass="[[hass]]"></hassio-addon-store>
</template>
<template is="dom-if" if="[[equals(page, &quot;system&quot;)]]">
<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, &quot;snapshots&quot;)]]">
<hassio-snapshot hass="[[hass]]" snapshot-slug="{{snapshotSlug}}" snapshot-deleted="{{snapshotDeleted}}"></hassio-snapshot>
</template>
`;
}
static get is() { return 'hassio-pages-with-tabs'; }
static get properties() {
return {
hass: Object,
showMenu: Boolean,
narrow: Boolean,
page: String,
supervisorInfo: Object,
hostInfo: Object,
hassInfo: Object,
snapshotSlug: String,
snapshotDeleted: Boolean,
markdownTitle: String,
markdownContent: {
type: String,
value: '',
},
};
}
ready() {
super.ready();
this.addEventListener('hassio-markdown-dialog', ev => this.openMarkdown(ev));
}
handlePageSelected(ev) {
const newPage = ev.detail.item.getAttribute('page-name');
if (newPage !== this.page) {
this.navigate(`/hassio/${newPage}`);
}
}
equals(a, b) {
return a === b;
}
showRefreshButton(page) {
return page === 'store' || page === 'snapshots';
}
refreshClicked() {
if (this.page === 'snapshots') {
this.shadowRoot.querySelector('hassio-snapshots').refreshData();
} else {
this.shadowRoot.querySelector('hassio-addon-store').refreshData();
}
}
openMarkdown(ev) {
this.setProperties({
markdownTitle: ev.detail.title,
markdownContent: ev.detail.content,
});
this.shadowRoot.querySelector('hassio-markdown-dialog').openDialog();
}
}
customElements.define(HassioPagesWithTabs.is, HassioPagesWithTabs);

View File

@ -16,20 +16,21 @@
<body>
<hassio-app></hassio-app>
<script>
function addScript(src) {
var e = document.createElement('script');
e.src = src;
document.head.appendChild(e);
}
var webComponentsSupported = (
'customElements' in window &&
'import' in document.createElement('link') &&
'content' in document.createElement('template'));
if (!webComponentsSupported) {
addScript('/static/webcomponents-lite.js');
}
function addScript(src) {
var e = document.createElement('script');
e.src = src;
document.head.appendChild(e);
}
var webComponentsSupported = (
'customElements' in window &&
'import' in document.createElement('link') &&
'content' in document.createElement('template'));
if (!webComponentsSupported) {
addScript('/static/webcomponents-bundle.js');
}
</script>
<link rel='import' href='./hassio-app.html'>
<!-- This is broken. -->
<script src="./hassio-app.js"></script>
<link rel='import' href='/static/mdi.html' async>
</body>
</html>

View File

@ -1,17 +1,19 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/paper-dialog/paper-dialog.html'>
<link rel='import' href='../../bower_components/paper-dialog-scrollable/paper-dialog-scrollable.html'>
<link rel='import' href='../../bower_components/app-layout/app-toolbar/app-toolbar.html'>
<link rel='import' href='../../bower_components/paper-icon-button/paper-icon-button.html'>
<link rel='import' href='../../bower_components/paper-checkbox/paper-checkbox.html'>
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
<link rel="import" href='../../bower_components/paper-input/paper-input.html'>
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';
import '@polymer/paper-dialog/paper-dialog.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/resources/ha-style.html'>
import '../../src/resources/ha-style.js';
<dom-module id='hassio-snapshot'>
<template>
<style include='ha-style-dialog'>
class HassioSnapshot extends PolymerElement {
static get template() {
return html`
<style include="ha-style-dialog">
paper-dialog {
min-width: 350px;
font-size: 14px;
@ -54,72 +56,58 @@
color: var(--google-red-500);
}
</style>
<paper-dialog id='dialog' with-backdrop on-iron-overlay-closed='_dialogClosed'>
<paper-dialog id="dialog" with-backdrop="" on-iron-overlay-closed="_dialogClosed">
<app-toolbar>
<paper-icon-button
icon='mdi:close'
dialog-dismiss
></paper-icon-button>
<div main-title>[[_computeName(snapshot)]]</div>
<paper-icon-button icon="mdi:close" dialog-dismiss=""></paper-icon-button>
<div main-title="">[[_computeName(snapshot)]]</div>
</app-toolbar>
<div class='details'>
[[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])<br/>
<div class="details">
[[_computeType(snapshot.type)]] ([[_computeSize(snapshot.size)]])<br>
[[_formatDatetime(snapshot.date)]]
</div>
<div>Home Assistant:</div>
<paper-checkbox checked='{{restoreHass}}'>
<paper-checkbox checked="{{restoreHass}}">
Home Assistant [[snapshot.homeassistant]]
</paper-checkbox>
<template is='dom-if' if='[[snapshot.addons.length]]'>
<template is="dom-if" if="[[snapshot.addons.length]]">
<div>Folders:</div>
<template is='dom-repeat' items='[[snapshot.folders]]'>
<paper-checkbox checked='{{item.checked}}'>
<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]]'>
<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}}'>
<template is="dom-repeat" items="[[snapshot.addons]]" sort="_sortAddons">
<paper-checkbox checked="{{item.checked}}">
[[item.name]]
<span class='details'>([[item.version]])</span>
<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 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 is="dom-if" if="[[error]]">
<p class="error">Error: [[error]]</p>
</template>
<div class='buttons'>
<paper-icon-button
icon='mdi:delete'
on-click='_deleteClicked'
class='warning'
title='Delete snapshot'
></paper-icon-button>
<a href='[[_computeDownloadUrl(snapshotSlug)]]' download='[[_computeDownloadName(snapshot)]]'>
<paper-icon-button
icon='mdi:download'
class='download'
title='Download snapshot'
></paper-icon-button>
<div class="buttons">
<paper-icon-button icon="mdi:delete" on-click="_deleteClicked" class="warning" title="Delete snapshot"></paper-icon-button>
<a href="[[_computeDownloadUrl(snapshotSlug)]]" download="[[_computeDownloadName(snapshot)]]">
<paper-icon-button icon="mdi: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 &amp; restore</paper-button>
<paper-button on-click="_partialRestoreClicked">Restore selected</paper-button>
<template is="dom-if" if="[[_isFullSnapshot(snapshot.type)]]">
<paper-button on-click="_fullRestoreClicked">Wipe &amp; restore</paper-button>
</template>
</div>
</paper-dialog>
</template>
</dom-module>
`;
}
<script>
class HassioSnapshot extends Polymer.Element {
static get is() { return 'hassio-snapshot'; }
static get properties() {
@ -267,4 +255,3 @@ class HassioSnapshot extends Polymer.Element {
}
}
customElements.define(HassioSnapshot.is, HassioSnapshot);
</script>

View File

@ -1,19 +1,20 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel='import' href='../../bower_components/paper-radio-group/paper-radio-group.html'>
<link rel='import' href='../../bower_components/paper-radio-button/paper-radio-button.html'>
<link rel='import' href='../../bower_components/paper-checkbox/paper-checkbox.html'>
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-radio-button/paper-radio-button.js';
import '@polymer/paper-radio-group/paper-radio-group.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../../src/components/hassio-card-content.js';
import '../../src/resources/hassio-style.js';
import '../../src/util/hass-mixins.js';
<link rel='import' href='../../src/components/hassio-card-content.html'>
<link rel='import' href='../../src/resources/hassio-style.html'>
<dom-module id="hassio-snapshots">
<template>
<style include='ha-style hassio-style'>
class HassioSnapshots extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style hassio-style">
paper-radio-group {
display: block;
}
@ -30,83 +31,75 @@
cursor: pointer;
}
</style>
<div class='content'>
<div class='card-group'>
<div class='title'>
<div class="content">
<div class="card-group">
<div class="title">
Create snapshot
<div class='description'>
<div class="description">
Snapshots allow you to easily backup and
restore all data of your Hass.io instance.
</div>
</div>
<paper-card>
<div class='card-content'>
<paper-input autofocus label='Name' value='{{snapshotName}}'></paper-input>
<div class="card-content">
<paper-input autofocus="" label="Name" value="{{snapshotName}}"></paper-input>
Type:
<paper-radio-group selected='{{snapshotType}}'>
<paper-radio-button name='full'>
<paper-radio-group selected="{{snapshotType}}">
<paper-radio-button name="full">
Full snapshot
</paper-radio-button>
<paper-radio-button name='partial'>
<paper-radio-button name="partial">
Partial snapshot
</paper-radio-button>
</paper-radio-group>
<template is='dom-if' if='[[!_fullSelected(snapshotType)]]'>
<template is="dom-if" if="[[!_fullSelected(snapshotType)]]">
Folders:
<template is='dom-repeat' items='[[folderList]]'>
<paper-checkbox checked='{{item.checked}}'>
<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}}'>
<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>
<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 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 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]]'>
<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>
<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
title='[[_computeName(snapshot)]]'
description='[[_computeDetails(snapshot)]]'
datetime='[[snapshot.date]]'
icon='[[_computeIcon(snapshot.type)]]'
icon-class='snapshot'
></hassio-card-content>
<template is="dom-repeat" items="[[snapshots]]" as="snapshot" sort="_sortSnapshots">
<paper-card class="pointer" on-click="_snapshotClicked">
<div class="card-content">
<hassio-card-content 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>
</template>
</dom-module>
`;
}
<script>
class HassioSnapshots extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-snapshots'; }
static get properties() {
@ -269,4 +262,3 @@ class HassioSnapshots extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HassioSnapshots.is, HassioSnapshots);
</script>

View File

@ -1,12 +1,14 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
import '../../src/components/buttons/ha-call-api-button.js';
import '../../src/util/hass-mixins.js';
<dom-module id="hassio-host-info">
<template>
class HassioHostInfo extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
paper-card {
display: inline-block;
@ -43,8 +45,8 @@
<paper-card>
<div class="card-content">
<h2>Host system</h2>
<table class='info'>
<tr>
<table class="info">
<tbody><tr>
<td>Hostname</td>
<td>[[data.hostname]]</td>
</tr>
@ -56,44 +58,27 @@
<td>Deployment</td>
<td>[[data.deployment]]</td>
</tr>
</table>
<paper-button
raised
on-click='_showHardware'
class='info'
>Show hardware</paper-button>
<template is='dom-if' if='[[errors]]'>
<div class='errors'>Error: [[errors]]</div>
</tbody></table>
<paper-button raised="" on-click="_showHardware" class="info">Show hardware</paper-button>
<template is="dom-if" if="[[errors]]">
<div class="errors">Error: [[errors]]</div>
</template>
</div>
<div class="card-actions">
<template is='dom-if' if='[[computeRebootAvailable(data)]]'>
<ha-call-api-button
class='warning'
hass='[[hass]]'
path="hassio/host/reboot"
>Reboot</ha-call-api-button>
<template is="dom-if" if="[[computeRebootAvailable(data)]]">
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/host/reboot">Reboot</ha-call-api-button>
</template>
<template is='dom-if' if='[[computeShutdownAvailable(data)]]'>
<ha-call-api-button
class='warning'
hass='[[hass]]'
path="hassio/host/shutdown"
>Shutdown</ha-call-api-button>
<template is="dom-if" if="[[computeShutdownAvailable(data)]]">
<ha-call-api-button class="warning" hass="[[hass]]" path="hassio/host/shutdown">Shutdown</ha-call-api-button>
</template>
<template is='dom-if' if='[[computeUpdateAvailable(data)]]'>
<ha-call-api-button
hass='[[hass]]'
path="hassio/host/update"
>Update</ha-call-api-button>
<template is="dom-if" if="[[computeUpdateAvailable(data)]]">
<ha-call-api-button hass="[[hass]]" path="hassio/host/update">Update</ha-call-api-button>
</template>
</div>
</paper-card>
</template>
</dom-module>
`;
}
<script>
class HassioHostInfo extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-host-info'; }
static get properties() {
@ -170,4 +155,3 @@ class HassioHostInfo extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HassioHostInfo.is, HassioHostInfo);
</script>

View File

@ -1,12 +1,14 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel="import" href="../../src/components/buttons/ha-call-api-button.html">
import '../../src/components/buttons/ha-call-api-button.js';
import '../../src/util/hass-mixins.js';
<dom-module id="hassio-supervisor-info">
<template>
class HassioSupervisorInfo extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
paper-card {
display: inline-block;
@ -37,8 +39,8 @@
<paper-card>
<div class="card-content">
<h2>Hass.io supervisor</h2>
<table class='info'>
<tr>
<table class="info">
<tbody><tr>
<td>Version</td>
<td>
[[data.version]]
@ -48,49 +50,33 @@
<td>Latest version</td>
<td>[[data.last_version]]</td>
</tr>
<template is='dom-if' if='[[!_equals(data.channel, "stable")]]'>
<template is="dom-if" if="[[!_equals(data.channel, &quot;stable&quot;)]]">
<tr>
<td>Channel</td>
<td>[[data.channel]]</td>
</tr>
</template>
</table>
<template is='dom-if' if='[[errors]]'>
<div class='errors'>Error: [[errors]]</div>
</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>
<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 is="dom-if" if="[[_equals(data.channel, &quot;beta&quot;)]]">
<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 is="dom-if" if="[[_equals(data.channel, &quot;stable&quot;)]]">
<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>
</template>
</dom-module>
`;
}
<script>
class HassioSupervisorInfo extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'hassio-supervisor-info'; }
static get properties() {
@ -167,4 +153,3 @@ This inludes beta releases for:
}
customElements.define(HassioSupervisorInfo.is, HassioSupervisorInfo);
</script>

View File

@ -1,27 +1,27 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel='import' href='../../bower_components/paper-card/paper-card.html'>
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="hassio-supervisor-log">
<template>
class HassioSupervisorLog extends PolymerElement {
static get template() {
return html`
<style include="ha-style">
paper-card {
display: block;
}
</style>
<paper-card>
<div class='card-content'>
<div class="card-content">
<pre>[[log]]</pre>
</div>
<div class='card-actions'>
<paper-button on-click='refreshTapped'>Refresh</paper-button>
<div class="card-actions">
<paper-button on-click="refreshTapped">Refresh</paper-button>
</div>
</paper-card>
</template>
</dom-module>
`;
}
<script>
class HassioSupervisorLog extends Polymer.Element {
static get is() { return 'hassio-supervisor-log'; }
static get properties() {
@ -51,4 +51,3 @@ class HassioSupervisorLog extends Polymer.Element {
}
customElements.define(HassioSupervisorLog.is, HassioSupervisorLog);
</script>

View File

@ -1,54 +0,0 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="./hassio-host-info.html">
<link rel="import" href="./hassio-supervisor-info.html">
<link rel='import' href='./hassio-supervisor-log.html'>
<dom-module id="hassio-system">
<template>
<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>
</template>
</dom-module>
<script>
class HassioSystem extends Polymer.Element {
static get is() { return 'hassio-system'; }
static get properties() {
return {
hass: Object,
supervisorInfo: Object,
hostInfo: Object,
};
}
}
customElements.define(HassioSystem.is, HassioSystem);
</script>

View File

@ -0,0 +1,45 @@
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import './hassio-host-info.js';
import './hassio-supervisor-info.js';
import './hassio-supervisor-log.js';
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>
`;
}
static get is() { return 'hassio-system'; }
static get properties() {
return {
hass: Object,
supervisorInfo: Object,
hostInfo: Object,
};
}
}
customElements.define(HassioSystem.is, HassioSystem);

View File

@ -87,27 +87,23 @@
if (!webComponentsSupported) {
var e = document.createElement('script');
e.onerror = initError;
e.src = '/static/webcomponents-lite.js';
e.src = '/static/webcomponents-bundle.js';
if ('import' in document.createElement('link')) {
document.write(e.outerHTML);
} else {
document.head.appendChild(e);
}
}
if ('serviceWorker' in navigator) {
/* if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('/service_worker.js');
});
}
window.CHART_SCRIPT = '/home-assistant-polymer/src/resources/ha-chart-scripts.html';
} */
</script>
<!--<script src='/home-assistant-polymer/build/_demo_data_compiled.js'></script>-->
<!--EXTRA_SCRIPTS-->
<script src='/home-assistant-polymer/build/core.js'></script>
<link rel='import' href='/home-assistant-polymer/src/home-assistant.html' onerror='initError()'>
{% if panel_url -%}
<link rel='import' href='{{ panel_url }}' async>
{% endif -%}
<script src='/home-assistant-polymer/build/webpack/app.js'></script>
<link rel='import' href='/home-assistant-polymer/hass_frontend/mdi.html' async>
{% for extra_url in extra_urls -%}
<link rel='import' href='{{ extra_url }}' async>

View File

@ -1,48 +1,104 @@
{
"name": "home-assistant-polymer",
"version": "1.0.0",
"description": "A frontend for Home Assistant using the Polymer framework",
"repository": {
"type": "git",
"url": "https://github.com/home-assistant/home-assistant-polymer"
},
"name": "home-assistant-frontend",
"version": "1.0.0",
"scripts": {
"clean": "rm -rf build/* build-temp/* build-es5/* build-temp-es5/* build-translations/*",
"gulp": "gulp",
"build": "BUILD_DEV=0 gulp",
"build": "BUILD_DEV=0 gulp && NODE_ENV=production webpack -p",
"build_demo": "BUILD_DEV=0 BUILD_DEMO=1 gulp",
"dev": "npm run gulp ru_all gen-service-worker",
"dev-watch": "npm run gulp watch_ru_all gen-service-worker",
"dev-es5": "npm run gulp ru_all_es5 gen-service-worker-es5",
"dev-watch-es5": "npm run gulp watch_ru_all_es5 gen-service-worker-es5",
"lint_js": "eslint src panels js hassio test-mocha --ext js,html",
"lint_html": "find src panels hassio -name '*.html' | grep -v hassio/index.html | xargs polymer lint --input",
"lint_js": "eslint src panels js hassio test-mocha",
"lint_html": "polymer lint",
"mocha": "node_modules/.bin/mocha --opts test-mocha/mocha.opts",
"test": "npm run lint_js && npm run lint_html && npm run mocha"
},
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
"license": "Apache-2.0",
"dependencies": {
"@polymer/app-layout": "^3.0.0-pre.18",
"@polymer/app-localize-behavior": "^3.0.0-pre.18",
"@polymer/app-route": "^3.0.0-pre.18",
"@polymer/app-storage": "^3.0.0-pre.18",
"@polymer/font-roboto": "^3.0.0-pre.18",
"@polymer/font-roboto-local": "^3.0.0-pre.19",
"@polymer/iron-autogrow-textarea": "^3.0.0-pre.18",
"@polymer/iron-flex-layout": "^3.0.0-pre.18",
"@polymer/iron-icon": "^3.0.0-pre.18",
"@polymer/iron-iconset-svg": "^3.0.0-pre.19",
"@polymer/iron-image": "^3.0.0-pre.18",
"@polymer/iron-input": "^3.0.0-pre.18",
"@polymer/iron-label": "^3.0.0-pre.18",
"@polymer/iron-media-query": "^3.0.0-pre.18",
"@polymer/iron-pages": "^3.0.0-pre.18",
"@polymer/iron-resizable-behavior": "^3.0.0-pre.19",
"@polymer/neon-animation": "^3.0.0-pre.18",
"@polymer/paper-button": "^3.0.0-pre.18",
"@polymer/paper-card": "^3.0.0-pre.18",
"@polymer/paper-checkbox": "^3.0.0-pre.18",
"@polymer/paper-dialog": "^3.0.0-pre.18",
"@polymer/paper-dialog-behavior": "^3.0.0-pre.19",
"@polymer/paper-dialog-scrollable": "^3.0.0-pre.18",
"@polymer/paper-drawer-panel": "^3.0.0-pre.18",
"@polymer/paper-dropdown-menu": "^3.0.0-pre.18",
"@polymer/paper-fab": "^3.0.0-pre.18",
"@polymer/paper-icon-button": "^3.0.0-pre.18",
"@polymer/paper-input": "^3.0.0-pre.18",
"@polymer/paper-item": "^3.0.0-pre.18",
"@polymer/paper-listbox": "^3.0.0-pre.18",
"@polymer/paper-menu-button": "^3.0.0-pre.18",
"@polymer/paper-progress": "^3.0.0-pre.18",
"@polymer/paper-radio-button": "^3.0.0-pre.18",
"@polymer/paper-radio-group": "^3.0.0-pre.18",
"@polymer/paper-ripple": "^3.0.0-pre.19",
"@polymer/paper-scroll-header-panel": "^3.0.0-pre.18",
"@polymer/paper-slider": "^3.0.0-pre.18",
"@polymer/paper-spinner": "^3.0.0-pre.18",
"@polymer/paper-styles": "^3.0.0-pre.18",
"@polymer/paper-tabs": "^3.0.0-pre.18",
"@polymer/paper-toast": "^3.0.0-pre.18",
"@polymer/paper-toggle-button": "^3.0.0-pre.18",
"@polymer/polymer": "^3.0.0",
"@vaadin/vaadin-combo-box": "4.0.1-pre.1",
"@vaadin/vaadin-date-picker": "3.0.0-pre.3",
"@webcomponents/shadycss": "^1.0.0",
"@webcomponents/webcomponentsjs": "^2.0.0",
"chart.js": "~2.7.2",
"chartjs-chart-timeline": "0.2.0",
"es6-object-assign": "^1.1.0",
"fecha": "^2.3.3",
"home-assistant-js-websocket": "^1.2.1",
"intl-messageformat": "^2.2.0",
"leaflet": "^1.0.2",
"marked": "^0.3.19",
"mdn-polyfills": "^5.5.0",
"moment": "^2.20.0",
"preact": "^8.2.6",
"unfetch": "^3.0.0"
"unfetch": "^3.0.0",
"web-animations-js": "^2.3.1",
"xss": "^0.3.8"
},
"devDependencies": {
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.4",
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-env": "^1.6.1",
"bower": "^1.8.2",
"chai": "^4.1.2",
"css-slam": "^2.0.2",
"del": "^3.0.0",
"eslint": "^4.11.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-html": "^4.0.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-react": "^7.0.0",
"gulp": "^3.9.1",
@ -71,7 +127,7 @@
"polymer-analyzer": "^2.3.0",
"polymer-build": "^2.1.0",
"polymer-bundler": "^3.1.0",
"polymer-cli": "^1.5.6",
"polymer-cli": "^1.7.0",
"pump": "^3.0.0",
"reify": "^0.14.1",
"require-dir": "^1.0.0",
@ -86,6 +142,19 @@
"sw-precache": "^5.2.0",
"uglify-es": "^3.1.9",
"uglify-js": "^3.1.9",
"web-component-tester": "^6.4.0"
}
"wct-browser-legacy": "^1.0.0",
"web-component-tester": "^6.6.0",
"webpack": "^4.8.1",
"webpack-cli": "^2.1.3"
},
"resolutions": {
"inherits": "2.0.3",
"samsam": "1.1.3",
"supports-color": "3.1.2",
"type-detect": "1.0.0",
"@webcomponents/webcomponentsjs": "2.0.0-beta.2",
"@vaadin/vaadin-overlay": "3.0.2-pre.2",
"fecha": "https://github.com/balloob/fecha/archive/51d14fd0eb4781e2ecf265d1c3080706259133b5.tar.gz"
},
"main": "src/home-assistant.js"
}

View File

@ -1,32 +1,38 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../../../bower_components/paper-radio-button/paper-radio-button.html">
<link rel="import" href="../../../bower_components/paper-radio-group/paper-radio-group.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu-light.html">
<link rel="import" href="../../../bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="../../../bower_components/paper-menu-button/paper-menu-button.html">
<link rel="import" href="../../../bower_components/paper-fab/paper-fab.html">
<link rel="import" href="../../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu-light.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-input/paper-textarea.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import '@polymer/paper-menu-button/paper-menu-button.js';
import '@polymer/paper-radio-button/paper-radio-button.js';
import '@polymer/paper-radio-group/paper-radio-group.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/components/entity/ha-entity-picker.html'>
<link rel='import' href='../../../src/components/ha-combo-box.html'>
<link rel='import' href='../../../src/components/ha-markdown.html'>
<link rel='import' href='../../../src/components/ha-service-picker.html'>
<link rel='import' href='../../../src/layouts/ha-app-layout.html'>
<link rel='import' href='../../../src/util/hass-mixins.html'>
import '../../../src/components/entity/ha-entity-picker.js';
import '../../../src/components/ha-combo-box.js';
import '../../../src/components/ha-markdown.js';
import '../../../src/components/ha-service-picker.js';
import '../../../src/layouts/ha-app-layout.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-js.js';
import '../ha-config-section.js';
<link rel="import" href="../ha-config-section.html">
<link rel="import" href="../ha-config-js.html">
<dom-module id="ha-automation-editor">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaAutomationEditor extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style include="ha-style">
.errors {
padding: 20px;
@ -83,42 +89,25 @@
}
</style>
<ha-app-layout has-scrolling-region>
<app-header slot="header" fixed>
<ha-app-layout has-scrolling-region="">
<app-header slot="header" fixed="">
<app-toolbar>
<paper-icon-button
icon='mdi:arrow-left'
on-click='backTapped'
></paper-icon-button>
<div main-title>[[name]]</div>
<paper-icon-button icon="mdi:arrow-left" on-click="backTapped"></paper-icon-button>
<div main-title="">[[name]]</div>
</app-toolbar>
</app-header>
<div class='content'>
<template is='dom-if' if='[[errors]]'>
<div class='errors'>[[errors]]</div>
<div class="content">
<template is="dom-if" if="[[errors]]">
<div class="errors">[[errors]]</div>
</template>
<div id='root'></div>
<div id="root"></div>
</div>
<paper-fab slot="fab"
is-wide$='[[isWide]]'
dirty$='[[dirty]]'
icon='mdi:content-save'
title="[[localize('ui.panel.config.automation.editor.save')]]"
on-click='saveAutomation'
></paper-fab>
<paper-fab slot="fab" is-wide\$="[[isWide]]" dirty\$="[[dirty]]" icon="mdi:content-save" title="[[localize('ui.panel.config.automation.editor.save')]]" on-click="saveAutomation"></paper-fab>
</ha-app-layout>
`;
}
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaAutomationEditor extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-automation-editor'; }
static get properties() {
@ -296,4 +285,3 @@ class HaAutomationEditor extends
}
customElements.define(HaAutomationEditor.is, HaAutomationEditor);
</script>

View File

@ -1,20 +1,26 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/paper-fab/paper-fab.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/layouts/ha-app-layout.html'>
<link rel='import' href='../../../src/components/ha-markdown.html'>
<link rel='import' href='../../../src/util/hass-mixins.html'>
import '../../../src/components/ha-markdown.js';
import '../../../src/layouts/ha-app-layout.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
<link rel="import" href="../ha-config-section.html">
<dom-module id="ha-automation-picker">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaAutomationPicker extends
window.hassMixins.LocalizeMixin(window.hassMixins.NavigateMixin(PolymerElement)) {
static get template() {
return html`
<style include="ha-style">
:host {
display: block;
@ -45,61 +51,43 @@
}
</style>
<ha-app-layout has-scrolling-region>
<app-header slot="header" fixed>
<ha-app-layout has-scrolling-region="">
<app-header slot="header" fixed="">
<app-toolbar>
<paper-icon-button
icon='mdi:arrow-left'
on-click='_backTapped'
></paper-icon-button>
<div main-title>[[localize('ui.panel.config.automation.caption')]]</div>
<paper-icon-button icon="mdi: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-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'>
<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'>
<template is="dom-repeat" items="[[automations]]" as="automation">
<paper-item>
<paper-item-body two-line on-click='automationTapped'>
<paper-item-body two-line="" on-click="automationTapped">
<div>[[computeName(automation)]]</div>
<div secondary>[[computeDescription(automation)]]</div>
<div secondary="">[[computeDescription(automation)]]</div>
</paper-item-body>
<iron-icon icon='mdi:chevron-right'></iron-icon>
<iron-icon icon="mdi:chevron-right"></iron-icon>
</paper-item>
</template>
</paper-card>
</ha-config-section>
<paper-fab slot="fab"
is-wide$='[[isWide]]'
icon='mdi:plus'
title="[[localize('ui.panel.config.automation.picker.add_automation')]]"
on-click='addAutomation'
></paper-fab>
<paper-fab slot="fab" is-wide\$="[[isWide]]" icon="mdi:plus" title="[[localize('ui.panel.config.automation.picker.add_automation')]]" on-click="addAutomation"></paper-fab>
</ha-app-layout>
`;
}
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaAutomationPicker extends
window.hassMixins.LocalizeMixin(window.hassMixins.NavigateMixin(Polymer.Element)) {
static get is() { return 'ha-automation-picker'; }
static get properties() {
@ -151,4 +139,3 @@ class HaAutomationPicker extends
}
customElements.define(HaAutomationPicker.is, HaAutomationPicker);
</script>

View File

@ -1,52 +1,32 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel='import' href='../../../bower_components/app-route/app-route.html'>
import '@polymer/app-route/app-route.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="./ha-automation-picker.html">
<link rel="import" href="./ha-automation-editor.html">
import './ha-automation-editor.js';
import './ha-automation-picker.js';
<dom-module id="ha-config-automation">
<template>
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>
<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 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 is="dom-if" if="[[showEditor]]" restamp="">
<ha-automation-editor hass="[[hass]]" automation="[[automation]]" is-wide="[[isWide]]" creating-new="[[_creatingNew]]"></ha-automation-editor>
</template>
</template>
</dom-module>
`;
}
<script>
class HaConfigAutomation extends Polymer.Element {
static get is() { return 'ha-config-automation'; }
static get properties() {
@ -124,4 +104,3 @@ class HaConfigAutomation extends Polymer.Element {
}
customElements.define(HaConfigAutomation.is, HaConfigAutomation);
</script>

View File

@ -1,17 +1,18 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href='../../../bower_components/paper-card/paper-card.html'>
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href='../../../bower_components/paper-button/paper-button.html'>
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-item/paper-item-body.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/layouts/hass-subpage.html">
<link rel="import" href="../../../src/util/hass-mixins.html">
<link rel="import" href='../../../src/resources/ha-style.html'>
<link rel="import" href='../../../src/components/buttons/ha-call-api-button.html'>
import '../../../src/components/buttons/ha-call-api-button.js';
import '../../../src/layouts/hass-subpage.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
<link rel="import" href="../ha-config-section.html">
<dom-module id="ha-config-cloud-account">
<template>
class HaConfigCloudAccount extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
padding-bottom: 24px;
@ -49,59 +50,53 @@
color: var(--primary-color);
}
</style>
<hass-subpage header='Cloud Account'>
<div class='content'>
<ha-config-section
is-wide='[[isWide]]'
>
<span slot='header'>Home Assistant Cloud</span>
<span slot='introduction'>
<hass-subpage header="Cloud Account">
<div class="content">
<ha-config-section is-wide="[[isWide]]">
<span slot="header">Home Assistant Cloud</span>
<span slot="introduction">
Thank you for supporting Home Assistant. It's because of people like you that we are able to run this project and make a great home automation experience for everyone. Thank you!
</span>
<paper-card heading='Account'>
<div class='account-row'>
<paper-item-body two-line>
<paper-card heading="Account">
<div class="account-row">
<paper-item-body two-line="">
[[account.email]]
<div secondary class='wrap'>
<span class='nowrap'>Subscription expires on </span>
<span class='nowrap'>[[_formatExpiration(account.sub_exp)]]</span>
<div secondary="" class="wrap">
<span class="nowrap">Subscription expires on </span>
<span class="nowrap">[[_formatExpiration(account.sub_exp)]]</span>
</div>
</paper-item-body>
<paper-button
on-click='handleLogout'
>Sign out</paper-button>
<paper-button on-click="handleLogout">Sign out</paper-button>
</div>
<div class='account-row'>
<div class="account-row">
<paper-item-body>
Cloud connection status
</paper-item-body>
<div class='status'>[[account.cloud]]</div>
<div class="status">[[account.cloud]]</div>
</div>
</paper-card>
</ha-config-section>
<ha-config-section
is-wide='[[isWide]]'
>
<span slot='header'>Integrations</span>
<span slot='introduction'>
<ha-config-section is-wide="[[isWide]]">
<span slot="header">Integrations</span>
<span slot="introduction">
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.
</span>
<paper-card heading='Alexa'>
<paper-card heading="Alexa">
<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.
<ul>
<li>
<a href='https://alexa.amazon.com/spa/index.html#skills/dp/B0772J1QKB/?ref=skill_dsk_skb_sr_2' target='_blank'>
<a href="https://alexa.amazon.com/spa/index.html#skills/dp/B0772J1QKB/?ref=skill_dsk_skb_sr_2" target="_blank">
Activate the Home Assistant skill for Alexa
</a>
</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>
@ -110,38 +105,33 @@
</div>
</paper-card>
<paper-card heading='Google Assistant'>
<paper-card heading="Google Assistant">
<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.
<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>
<p><em>This integration requires a Google Assistant-enabled device like the Google Home or Android phone.</em></p>
</div>
<div class='card-actions'>
<ha-call-api-button
hass='[[hass]]'
path='cloud/google_actions/sync'
>Sync devices</ha-call-api-button>
<div class="card-actions">
<ha-call-api-button hass="[[hass]]" path="cloud/google_actions/sync">Sync devices</ha-call-api-button>
</div>
</paper-card>
</ha-config-section>
</div>
</hass-subpage>
</template>
</dom-module>
`;
}
<script>
class HaConfigCloudAccount extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-config-cloud-account'; }
static get properties() {
@ -182,4 +172,3 @@ class HaConfigCloudAccount extends window.hassMixins.EventsMixin(Polymer.Element
}
customElements.define(HaConfigCloudAccount.is, HaConfigCloudAccount);
</script>

View File

@ -1,14 +1,16 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href='../../../bower_components/paper-card/paper-card.html'>
<link rel="import" href='../../../bower_components/paper-input/paper-input.html'>
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/layouts/hass-subpage.html">
<link rel="import" href="../../../src/util/hass-mixins.html">
<link rel="import" href='../../../src/resources/ha-style.html'>
<link rel="import" href='../../../src/components/buttons/ha-progress-button.html'>
import '../../../src/components/buttons/ha-progress-button.js';
import '../../../src/layouts/hass-subpage.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
<dom-module id="ha-config-cloud-forgot-password">
<template>
class HaConfigCloudForgotPassword extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
padding-bottom: 24px;
@ -40,38 +42,25 @@
}
</style>
<hass-subpage header="Forgot Password">
<div class='content'>
<div class="content">
<paper-card>
<div class='card-content'>
<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 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 class="card-actions">
<ha-progress-button on-click="_handleEmailPasswordReset" progress="[[_requestInProgress]]">Send reset email</ha-progress-button>
</div>
</paper-card>
</div>
</hass-subpage>
</template>
</dom-module>
`;
}
<script>
class HaConfigCloudForgotPassword extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-config-cloud-forgot-password'; }
static get properties() {
@ -131,4 +120,3 @@ class HaConfigCloudForgotPassword extends window.hassMixins.EventsMixin(Polymer.
}
customElements.define(HaConfigCloudForgotPassword.is, HaConfigCloudForgotPassword);
</script>

View File

@ -1,21 +1,23 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href='../../../bower_components/paper-card/paper-card.html'>
<link rel="import" href='../../../bower_components/paper-button/paper-button.html'>
<link rel="import" href='../../../bower_components/paper-icon-button/paper-icon-button.html'>
<link rel="import" href='../../../bower_components/paper-input/paper-input.html'>
<link rel="import" href='../../../bower_components/paper-ripple/paper-ripple.html'>
<link rel="import" href='../../../bower_components/paper-item/paper-item.html'>
<link rel="import" href='../../../bower_components/paper-item/paper-item-body.html'>
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-ripple/paper-ripple.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/layouts/hass-subpage.html">
<link rel="import" href="../../../src/util/hass-mixins.html">
<link rel="import" href='../../../src/resources/ha-style.html'>
<link rel="import" href='../../../src/components/buttons/ha-progress-button.html'>
import '../../../src/components/buttons/ha-progress-button.js';
import '../../../src/layouts/hass-subpage.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
<link rel="import" href="../ha-config-section.html">
<dom-module id="ha-config-cloud-login">
<template>
class HaConfigCloudLogin extends
window.hassMixins.NavigateMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
padding-bottom: 24px;
@ -57,80 +59,51 @@
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>
<span slot='introduction'>
<hass-subpage header="Cloud Login">
<div class="content">
<ha-config-section is-wide="[[isWide]]">
<span slot="header">Home Assistant Cloud</span>
<span slot="introduction">
The Home Assistant Cloud allows your local Home Assistant instance to connect with cloud-only services like Amazon Alexa.
<p><a href='https://www.home-assistant.io/components/cloud/' target='_blank'>Learn more</a></p>
<p><a href="https://www.home-assistant.io/components/cloud/" target="_blank">Learn more</a></p>
</span>
<paper-card hidden$='[[!flashMessage]]'>
<div class='card-content flash-msg'>
<paper-card hidden\$="[[!flashMessage]]">
<div class="card-content flash-msg">
[[flashMessage]]
<paper-icon-button
icon='mdi:close'
on-click='_dismissFlash'
>Dismiss</paper-icon-button>
<paper-ripple id='flashRipple' noink></paper-ripple>
<paper-icon-button icon="mdi:close" on-click="_dismissFlash">Dismiss</paper-icon-button>
<paper-ripple id="flashRipple" noink=""></paper-ripple>
</div>
</paper-card>
<paper-card>
<div class='card-content'>
<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 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 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>
<paper-item on-click="_handleRegister">
<paper-item-body two-line="">
Create Account
<div secondary>Get up and running quickly.</div>
<div secondary="">Get up and running quickly.</div>
</paper-item-body>
<iron-icon icon='mdi:chevron-right'></iron-icon>
<iron-icon icon="mdi:chevron-right"></iron-icon>
</paper-item>
</paper-card>
</ha-config-section>
</div>
</hass-subpage>
</template>
</dom-module>
`;
}
<script>
class HaConfigCloudLogin extends
window.hassMixins.NavigateMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-config-cloud-login'; }
static get properties() {
@ -260,4 +233,3 @@ class HaConfigCloudLogin extends
}
customElements.define(HaConfigCloudLogin.is, HaConfigCloudLogin);
</script>

View File

@ -1,16 +1,17 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href='../../../bower_components/paper-card/paper-card.html'>
<link rel="import" href='../../../bower_components/paper-input/paper-input.html'>
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/layouts/hass-subpage.html">
<link rel="import" href="../../../src/util/hass-mixins.html">
<link rel="import" href='../../../src/resources/ha-style.html'>
<link rel="import" href='../../../src/components/buttons/ha-progress-button.html'>
import '../../../src/components/buttons/ha-progress-button.js';
import '../../../src/layouts/hass-subpage.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
<link rel="import" href="../ha-config-section.html">
<dom-module id="ha-config-cloud-register">
<template>
class HaConfigCloudRegister extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
a {
color: var(--primary-color);
@ -41,67 +42,41 @@
}
</style>
<hass-subpage header="Register Account">
<div class='content'>
<ha-config-section
is-wide='[[isWide]]'
>
<span slot='header'>Register with the Home Assistant Cloud</span>
<span slot='introduction'>
<div class="content">
<ha-config-section is-wide="[[isWide]]">
<span slot="header">Register with the Home Assistant Cloud</span>
<span slot="introduction">
Register today to easily connect with the Home Assistant Cloud. This will allow you to unlock great new services and functionality, like Amazon Alexa integration.
<p>
By registering an account you agree to the following terms and conditions.
<ul>
<li><a href='https://home-assistant.io/tos/' target='_blank'>Terms and Conditions</a></li>
<li><a href='https://home-assistant.io/privacy/' target='_blank'>Privacy Policy</a></li>
</p><ul>
<li><a href="https://home-assistant.io/tos/" target="_blank">Terms and Conditions</a></li>
<li><a href="https://home-assistant.io/privacy/" target="_blank">Privacy Policy</a></li>
</ul>
</p>
<p></p>
</span>
<paper-card>
<div class='card-content'>
<div class='header'>
<div class="card-content">
<div class="header">
<h1>Register</h1>
<div class='error' hidden$='[[!_error]]'>[[_error]]</div>
<div class="error" hidden\$="[[!_error]]">[[_error]]</div>
</div>
<paper-input
autofocus
id='email'
label='Email address'
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='Your password needs to be at least 8 characters'
></paper-input>
<paper-input autofocus="" id="email" label="Email address" 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="Your password needs to be at least 8 characters"></paper-input>
</div>
<div class='card-actions'>
<ha-progress-button
on-click='_handleRegister'
progress='[[_requestInProgress]]'
>Create Account</ha-progress-button>
<button
class='link'
hidden='[[_requestInProgress]]'
on-click='_handleResendVerifyEmail'
>Resend confirmation email</button>
<div class="card-actions">
<ha-progress-button on-click="_handleRegister" progress="[[_requestInProgress]]">Create Account</ha-progress-button>
<button class="link" hidden="[[_requestInProgress]]" on-click="_handleResendVerifyEmail">Resend confirmation email</button>
</div>
</paper-card>
</ha-config-section>
</div>
</hass-subpage>
</template>
</dom-module>
`;
}
<script>
class HaConfigCloudRegister extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-config-cloud-register'; }
static get properties() {
@ -209,4 +184,3 @@ class HaConfigCloudRegister extends window.hassMixins.EventsMixin(Polymer.Elemen
}
customElements.define(HaConfigCloudRegister.is, HaConfigCloudRegister);
</script>

View File

@ -1,133 +0,0 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../../bower_components/app-route/app-route.html'>
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../ha-config-section.html">
<link rel="import" href="./ha-config-cloud-login.html">
<link rel="import" href="./ha-config-cloud-register.html">
<link rel="import" href="./ha-config-cloud-forgot-password.html">
<link rel="import" href="./ha-config-cloud-account.html">
<dom-module id="ha-config-cloud">
<template>
<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]]'
account='[[account]]'
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, "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>
</dom-module>
<script>
{
const LOGGED_IN_URLS = [
'/cloud/account',
];
const NOT_LOGGED_IN_URLS = [
'/cloud/login',
'/cloud/register',
'/cloud/forgot-password',
];
class HaConfigCloud extends window.hassMixins.NavigateMixin(Polymer.Element) {
static get is() { return 'ha-config-cloud'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
loadingAccount: {
type: Boolean,
value: false
},
account: {
type: Object,
},
_flashMessage: {
type: String,
value: '',
},
route: Object,
_routeData: Object,
_routeTail: Object,
_loginEmail: String,
};
}
static get observers() {
return [
'_checkRoute(route, account)'
];
}
ready() {
super.ready();
this.addEventListener('cloud-done', (ev) => {
this._flashMessage = ev.detail.flashMessage;
this.navigate('/config/cloud/login');
});
}
_checkRoute(route) {
if (!route || route.path.substr(0, 6) !== '/cloud') return;
this._debouncer = Polymer.Debouncer.debounce(
this._debouncer,
Polymer.Async.timeOut.after(0),
() => {
if (!this.account && !NOT_LOGGED_IN_URLS.includes(route.path)) {
this.navigate('/config/cloud/login', true);
} else if (this.account && !LOGGED_IN_URLS.includes(route.path)) {
this.navigate('/config/cloud/account', true);
}
}
);
}
_equals(a, b) {
return a === b;
}
}
customElements.define(HaConfigCloud.is, HaConfigCloud);
}
</script>

View File

@ -0,0 +1,109 @@
import '@polymer/app-route/app-route.js';
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
import './ha-config-cloud-account.js';
import './ha-config-cloud-forgot-password.js';
import './ha-config-cloud-login.js';
import './ha-config-cloud-register.js';
{
const LOGGED_IN_URLS = [
'/cloud/account',
];
const NOT_LOGGED_IN_URLS = [
'/cloud/login',
'/cloud/register',
'/cloud/forgot-password',
];
class HaConfigCloud extends window.hassMixins.NavigateMixin(PolymerElement) {
static get template() {
return html`
<app-route route="[[route]]" pattern="/cloud/:page" data="{{_routeData}}" tail="{{_routeTail}}"></app-route>
<template is="dom-if" if="[[_equals(_routeData.page, &quot;account&quot;)]]" restamp="">
<ha-config-cloud-account hass="[[hass]]" account="[[account]]" is-wide="[[isWide]]"></ha-config-cloud-account>
</template>
<template is="dom-if" if="[[_equals(_routeData.page, &quot;login&quot;)]]" 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, &quot;register&quot;)]]" 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, &quot;forgot-password&quot;)]]" restamp="">
<ha-config-cloud-forgot-password page-name="forgot-password" hass="[[hass]]" email="{{_loginEmail}}"></ha-config-cloud-forgot-password>
</template>
`;
}
static get is() { return 'ha-config-cloud'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
loadingAccount: {
type: Boolean,
value: false
},
account: {
type: Object,
},
_flashMessage: {
type: String,
value: '',
},
route: Object,
_routeData: Object,
_routeTail: Object,
_loginEmail: String,
};
}
static get observers() {
return [
'_checkRoute(route, account)'
];
}
ready() {
super.ready();
this.addEventListener('cloud-done', (ev) => {
this._flashMessage = ev.detail.flashMessage;
this.navigate('/config/cloud/login');
});
}
_checkRoute(route) {
if (!route || route.path.substr(0, 6) !== '/cloud') return;
this._debouncer = Debouncer.debounce(
this._debouncer,
timeOut.after(0),
() => {
if (!this.account && !NOT_LOGGED_IN_URLS.includes(route.path)) {
this.navigate('/config/cloud/login', true);
} else if (this.account && !LOGGED_IN_URLS.includes(route.path)) {
this.navigate('/config/cloud/account', true);
}
}
);
}
_equals(a, b) {
return a === b;
}
}
customElements.define(HaConfigCloud.is, HaConfigCloud);
}

View File

@ -1,20 +1,26 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../../bower_components/paper-button/paper-button.html'>
<link rel='import' href='../../../bower_components/paper-card/paper-card.html'>
<link rel='import' href='../../../bower_components/paper-item/paper-item-body.html'>
<link rel='import' href='../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-item/paper-item-body.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel='import' href='../../../src/resources/ha-style.html'>
<link rel='import' href='../../../src/layouts/hass-subpage.html'>
import '../../../src/layouts/hass-subpage.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
import './ha-config-flow.js';
<link rel='import' href='../ha-config-section.html'>
<link rel='import' href='./ha-config-flow.html'>
<dom-module id="ha-config-entries">
<template>
<style include='iron-flex ha-style'>
{
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigManager extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style include="iron-flex ha-style">
paper-button {
color: var(--primary-color);
font-weight: 500;
@ -30,79 +36,66 @@
}
</style>
<hass-subpage header='Integrations'>
<template is='dom-if' if='[[_progress.length]]'>
<ha-config-section is-wide='[[isWide]]'>
<span slot='header'>In Progress</span>
<hass-subpage header="Integrations">
<template is="dom-if" if="[[_progress.length]]">
<ha-config-section is-wide="[[isWide]]">
<span slot="header">In Progress</span>
<paper-card>
<template is='dom-repeat' items='[[_progress]]'>
<div class='config-entry-row'>
<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'>Configure</paper-button>
<paper-button on-click="_continueFlow">Configure</paper-button>
</div>
</template>
</paper-card>
</ha-config-section>
</template>
<ha-config-section is-wide='[[isWide]]'>
<span slot='header'>Configured</span>
<ha-config-section is-wide="[[isWide]]">
<span slot="header">Configured</span>
<paper-card>
<template is='dom-if' if='[[!_entries.length]]'>
<div class='config-entry-row'>
<template is="dom-if" if="[[!_entries.length]]">
<div class="config-entry-row">
<paper-item-body>
Nothing configured yet
</paper-item-body>
</div>
</template>
<template is='dom-repeat' items='[[_entries]]'>
<div class='config-entry-row'>
<paper-item-body three-line>
<template is="dom-repeat" items="[[_entries]]">
<div class="config-entry-row">
<paper-item-body three-line="">
[[item.title]]
<div secondary>Integration: [[_computeIntegrationTitle(localize, item.domain)]]</div>
<div secondary>Added by: [[item.source]]</div>
<div secondary>State: [[item.state]]</div>
<div secondary="">Integration: [[_computeIntegrationTitle(localize, item.domain)]]</div>
<div secondary="">Added by: [[item.source]]</div>
<div secondary="">State: [[item.state]]</div>
</paper-item-body>
<paper-button on-click='_removeEntry'>Remove</paper-button>
<paper-button on-click="_removeEntry">Remove</paper-button>
</div>
</template>
</paper-card>
</ha-config-section>
<ha-config-section is-wide='[[isWide]]'>
<span slot='header'>Available</span>
<ha-config-section is-wide="[[isWide]]">
<span slot="header">Available</span>
<paper-card>
<template is='dom-repeat' items='[[_handlers]]'>
<div class='config-entry-row'>
<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'>Configure</paper-button>
<paper-button on-click="_createFlow">Configure</paper-button>
</div>
</template>
</paper-card>
</ha-config-section>
</hass-subpage>
<ha-config-flow
hass='[[hass]]'
flow-id='[[_flowId]]'
step='{{_flowStep}}'
on-flow-closed='_flowClose'
></ha-config-flow>
</template>
</dom-module>
<ha-config-flow hass="[[hass]]" flow-id="[[_flowId]]" step="{{_flowStep}}" on-flow-closed="_flowClose"></ha-config-flow>
`;
}
<script>
{
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigManager extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-config-entries'; }
static get properties() {
@ -209,4 +202,3 @@
customElements.define(HaConfigManager.is, HaConfigManager);
}
</script>

View File

@ -1,16 +1,23 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../../bower_components/paper-dialog/paper-dialog.html'>
<link rel='import' href='../../../bower_components/paper-dialog-scrollable/paper-dialog-scrollable.html'>
<link rel="import" href='../../../bower_components/paper-button/paper-button.html'>
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';
import '@polymer/paper-dialog/paper-dialog.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href='../../../src/components/ha-markdown.html'>
<link rel='import' href='../../../src/resources/ha-style.html'>
<link rel="import" href='../../../src/components/ha-form.html'>
import '../../../src/components/ha-form.js';
import '../../../src/components/ha-markdown.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
<dom-module id="ha-config-flow">
<template>
<style include='ha-style-dialog'>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigFlow extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style include="ha-style-dialog">
.error {
color: red;
}
@ -22,73 +29,55 @@
margin: 0 auto;
}
</style>
<paper-dialog
id='dialog'
with-backdrop
opened='[[step]]'
on-opened-changed='_openedChanged'
>
<paper-dialog id="dialog" with-backdrop="" opened="[[step]]" on-opened-changed="_openedChanged">
<h2>
<template is='dom-if' if='[[_equals(step.type, "abort")]]'>
<template is="dom-if" if="[[_equals(step.type, &quot;abort&quot;)]]">
Aborted
</template>
<template is='dom-if' if='[[_equals(step.type, "create_entry")]]'>
<template is="dom-if" if="[[_equals(step.type, &quot;create_entry&quot;)]]">
Success!
</template>
<template is='dom-if' if='[[_equals(step.type, "form")]]'>
<template is="dom-if" if="[[_equals(step.type, &quot;form&quot;)]]">
[[_computeStepTitle(localize, step)]]
</template>
</h2>
<paper-dialog-scrollable>
<template is='dom-if' if='[[!step]]'>
<template is="dom-if" if="[[!step]]">
Loading flow.
</template>
<template is='dom-if' if='[[step]]'>
<template is='dom-if' if='[[_equals(step.type, "abort")]]'>
<template is="dom-if" if="[[step]]">
<template is="dom-if" if="[[_equals(step.type, &quot;abort&quot;)]]">
<p>[[_computeStepAbortedReason(localize, step)]]</p>
</template>
<template is='dom-if' if='[[_equals(step.type, "create_entry")]]'>
<template is="dom-if" if="[[_equals(step.type, &quot;create_entry&quot;)]]">
<p>Created config for [[step.title]]</p>
</template>
<template is='dom-if' if='[[_equals(step.type, "form")]]'>
<template is='dom-if' if='[[_computeStepDescription(localize, step)]]'>
<ha-markdown content='[[_computeStepDescription(localize, step)]]'></ha-markdown>
<template is="dom-if" if="[[_equals(step.type, &quot;form&quot;)]]">
<template is="dom-if" if="[[_computeStepDescription(localize, step)]]">
<ha-markdown content="[[_computeStepDescription(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>
<ha-form data="{{stepData}}" 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>
<div class="buttons">
<template is="dom-if" if="[[_equals(step.type, &quot;abort&quot;)]]">
<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 is="dom-if" if="[[_equals(step.type, &quot;create_entry&quot;)]]">
<paper-button on-click="_flowDone">Close</paper-button>
</template>
<template is='dom-if' if='[[_equals(step.type, "form")]]'>
<paper-button on-click='_submitStep'>Submit</paper-button>
<template is="dom-if" if="[[_equals(step.type, &quot;form&quot;)]]">
<paper-button on-click="_submitStep">Submit</paper-button>
</template>
</div>
</paper-dialog>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigFlow extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-config-flow'; }
static get properties() {
@ -204,4 +193,3 @@ class HaConfigFlow extends
}
customElements.define(HaConfigFlow.is, HaConfigFlow);
</script>

View File

@ -1,121 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../src/resources/ha-style.html">
<link rel='import' href='../../../src/layouts/ha-app-layout.html'>
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="./ha-config-section-core.html">
<link rel="import" href="./ha-config-section-push-notifications.html">
<link rel="import" href="./ha-config-section-translation.html">
<link rel="import" href="./ha-config-section-themes.html">
<dom-module id="ha-config-core">
<template>
<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;
}
.narrow .border {
max-width: 640px;
}
</style>
<ha-app-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<paper-icon-button
icon='mdi:arrow-left'
on-click='_backTapped'
></paper-icon-button>
<div main-title>[[localize('ui.panel.config.core.caption')]]</div>
</app-toolbar>
</app-header>
<div class$='[[computeClasses(isWide)]]'>
<ha-config-section-core
is-wide='[[isWide]]'
hass='[[hass]]'
></ha-config-section-core>
<template is='dom-if' if='[[pushSupported]]'>
<div class='border'></div>
<ha-config-section-push-notifications
is-wide='[[isWide]]'
hass='[[hass]]'
push-supported='{{pushSupported}}'
></ha-config-section-push-notifications>
</template>
<template is='dom-if' if='[[computeIsTranslationLoaded(hass)]]'>
<div class='border'></div>
<ha-config-section-translation
is-wide='[[isWide]]'
hass='[[hass]]'
></ha-config-section-translation>
</template>
<template is='dom-if' if='[[computeIsThemesLoaded(hass)]]'>
<div class='border'></div>
<ha-config-section-themes
is-wide='[[isWide]]'
hass='[[hass]]'
></ha-config-section-themes>
</template>
</div>
</ha-app-layout>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigCore extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-config-core'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
pushSupported: {
type: Boolean,
value: true,
},
};
}
computeClasses(isWide) {
return isWide ? 'content' : 'content narrow';
}
computeIsZwaveLoaded(hass) {
return window.hassUtil.isComponentLoaded(hass, 'config.zwave');
}
computeIsTranslationLoaded(hass) {
return hass.translationMetadata &&
Object.keys(hass.translationMetadata.translations).length;
}
computeIsThemesLoaded(hass) {
return hass.themes && hass.themes.themes &&
Object.keys(hass.themes.themes).length;
}
_backTapped() {
history.back();
}
}
customElements.define(HaConfigCore.is, HaConfigCore);
</script>

View File

@ -0,0 +1,103 @@
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/layouts/ha-app-layout.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import './ha-config-section-core.js';
import './ha-config-section-push-notifications.js';
import './ha-config-section-themes.js';
import './ha-config-section-translation.js';
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigCore extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<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;
}
.narrow .border {
max-width: 640px;
}
</style>
<ha-app-layout has-scrolling-region="">
<app-header slot="header" fixed="">
<app-toolbar>
<paper-icon-button icon="mdi:arrow-left" on-click="_backTapped"></paper-icon-button>
<div main-title="">[[localize('ui.panel.config.core.caption')]]</div>
</app-toolbar>
</app-header>
<div class\$="[[computeClasses(isWide)]]">
<ha-config-section-core is-wide="[[isWide]]" hass="[[hass]]"></ha-config-section-core>
<template is="dom-if" if="[[pushSupported]]">
<div class="border"></div>
<ha-config-section-push-notifications is-wide="[[isWide]]" hass="[[hass]]" push-supported="{{pushSupported}}"></ha-config-section-push-notifications>
</template>
<template is="dom-if" if="[[computeIsTranslationLoaded(hass)]]">
<div class="border"></div>
<ha-config-section-translation is-wide="[[isWide]]" hass="[[hass]]"></ha-config-section-translation>
</template>
<template is="dom-if" if="[[computeIsThemesLoaded(hass)]]">
<div class="border"></div>
<ha-config-section-themes is-wide="[[isWide]]" hass="[[hass]]"></ha-config-section-themes>
</template>
</div>
</ha-app-layout>
`;
}
static get is() { return 'ha-config-core'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
pushSupported: {
type: Boolean,
value: true,
},
};
}
computeClasses(isWide) {
return isWide ? 'content' : 'content narrow';
}
computeIsZwaveLoaded(hass) {
return window.hassUtil.isComponentLoaded(hass, 'config.zwave');
}
computeIsTranslationLoaded(hass) {
return hass.translationMetadata &&
Object.keys(hass.translationMetadata.translations).length;
}
computeIsThemesLoaded(hass) {
return hass.themes && hass.themes.themes &&
Object.keys(hass.themes.themes).length;
}
_backTapped() {
history.back();
}
}
customElements.define(HaConfigCore.is, HaConfigCore);

View File

@ -1,17 +1,20 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
<link rel="import" href="../../../src/resources/ha-style.html">
<link rel='import' href='../../../src/util/hass-mixins.html'>
import '../../../src/components/buttons/ha-call-service-button.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
<link rel="import" href="../ha-config-section.html">
<dom-module id="ha-config-section-core">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigSectionCore extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
.validate-container {
@apply --layout-vertical;
@ -42,112 +45,76 @@
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>
<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'>
<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'>
<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'>
<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 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'>
<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'>
<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>
<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'>
<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')]]
<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 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 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 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'>
<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')]]
<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 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>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigSectionCore extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-config-section-core'; }
static get properties() {
@ -207,4 +174,3 @@ class HaConfigSectionCore extends window.hassMixins.LocalizeMixin(Polymer.Elemen
}
customElements.define(HaConfigSectionCore.is, HaConfigSectionCore);
</script>

View File

@ -1,59 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/iron-label/iron-label.html">
<link rel="import" href="../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../ha-config-section.html">
<link rel='import' href='../../../src/components/ha-push-notifications-toggle.html'>
<dom-module id="ha-config-section-push-notifications">
<template>
<style include="iron-flex iron-flex-alignment iron-positioning">
ha-push-notifications-toggle {
margin-left: 16px;
}
</style>
<ha-config-section is-wide='[[isWide]]'>
<span slot='header'>[[localize('ui.panel.config.core.section.push_notifications.header')]]</span>
<span slot='introduction'>
[[localize('ui.panel.config.core.section.push_notifications.introduction')]]
</span>
<paper-card>
<div class='card-content'>
<iron-label class='horizontal layout'>
[[localize('ui.panel.config.core.section.push_notifications.push_notifications')]]
<ha-push-notifications-toggle
hass='[[hass]]'
push-supported='{{pushSupported}}'
></ha-push-notifications-toggle>
</iron-label>
</div>
</paper-card>
</ha-config-section>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigSectionPushNotifications extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-config-section-push-notifications'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
pushSupported: {
type: Boolean,
notify: true,
},
};
}
}
customElements.define(HaConfigSectionPushNotifications.is, HaConfigSectionPushNotifications);
</script>

View File

@ -0,0 +1,54 @@
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/iron-label/iron-label.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/components/ha-push-notifications-toggle.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigSectionPushNotifications extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex iron-flex-alignment iron-positioning">
ha-push-notifications-toggle {
margin-left: 16px;
}
</style>
<ha-config-section is-wide="[[isWide]]">
<span slot="header">[[localize('ui.panel.config.core.section.push_notifications.header')]]</span>
<span slot="introduction">
[[localize('ui.panel.config.core.section.push_notifications.introduction')]]
</span>
<paper-card>
<div class="card-content">
<iron-label class="horizontal layout">
[[localize('ui.panel.config.core.section.push_notifications.push_notifications')]]
<ha-push-notifications-toggle hass="[[hass]]" push-supported="{{pushSupported}}"></ha-push-notifications-toggle>
</iron-label>
</div>
</paper-card>
</ha-config-section>
`;
}
static get is() { return 'ha-config-section-push-notifications'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
pushSupported: {
type: Boolean,
notify: true,
},
};
}
}
customElements.define(HaConfigSectionPushNotifications.is, HaConfigSectionPushNotifications);

View File

@ -1,28 +1,32 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../ha-config-section.html">
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
<dom-module id="ha-config-section-themes">
<template>
<ha-config-section is-wide='[[isWide]]'>
<span slot='header'>[[localize('ui.panel.config.core.section.themes.header')]]</span>
<span slot='introduction'>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigSectionThemes extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<ha-config-section is-wide="[[isWide]]">
<span slot="header">[[localize('ui.panel.config.core.section.themes.header')]]</span>
<span slot="introduction">
[[localize('ui.panel.config.core.section.themes.introduction')]]
</span>
<paper-card>
<div class='card-content'>
<paper-dropdown-menu label="[[localize('ui.panel.config.core.section.themes.header')]]" dynamic-align>
<paper-listbox
slot="dropdown-content"
selected='{{selectedTheme}}'
>
<template is='dom-repeat' items='[[themes]]' as='theme'>
<div class="card-content">
<paper-dropdown-menu label="[[localize('ui.panel.config.core.section.themes.header')]]" dynamic-align="">
<paper-listbox slot="dropdown-content" selected="{{selectedTheme}}">
<template is="dom-repeat" items="[[themes]]" as="theme">
<paper-item>[[theme]]</paper-item>
</template>
</paper-listbox>
@ -30,16 +34,9 @@
</div>
</paper-card>
</ha-config-section>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigSectionThemes extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-config-section-themes'; }
static get properties() {
@ -95,4 +92,3 @@ class HaConfigSectionThemes extends
}
customElements.define(HaConfigSectionThemes.is, HaConfigSectionThemes);
</script>

View File

@ -1,42 +1,42 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../ha-config-section.html">
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
<dom-module id="ha-config-section-translation">
<template>
<ha-config-section is-wide='[[isWide]]'>
<span slot='header'>[[localize('ui.panel.config.core.section.translation.header')]]</span>
<span slot='introduction'>
[[localize('ui.panel.config.core.section.translation.introduction')]]
</span>
<paper-card>
<div class='card-content'>
<paper-dropdown-menu label="[[localize('ui.panel.config.core.section.translation.language')]]" dynamic-align>
<paper-listbox slot="dropdown-content" attr-for-selected="language-tag" selected="{{languageSelection}}">
<template is='dom-repeat' items='[[languages]]'>
<paper-item language-tag$="[[item.tag]]">[[item.nativeName]]</paper-item>
</template>
</paper-listbox>
></paper-dropdown-menu>
</div>
</paper-card>
</ha-config-section>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigSectionTranslation extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<ha-config-section is-wide="[[isWide]]">
<span slot="header">[[localize('ui.panel.config.core.section.translation.header')]]</span>
<span slot="introduction">
[[localize('ui.panel.config.core.section.translation.introduction')]]
</span>
<paper-card>
<div class="card-content">
<paper-dropdown-menu label="[[localize('ui.panel.config.core.section.translation.language')]]" dynamic-align="">
<paper-listbox slot="dropdown-content" attr-for-selected="language-tag" selected="{{languageSelection}}">
<template is="dom-repeat" items="[[languages]]">
<paper-item language-tag\$="[[item.tag]]">[[item.nativeName]]</paper-item>
</template>
</paper-listbox>
&gt;</paper-dropdown-menu>
</div>
</paper-card>
</ha-config-section>
`;
}
static get is() { return 'ha-config-section-translation'; }
static get properties() {
@ -84,4 +84,3 @@ class HaConfigSectionTranslation extends
}
customElements.define(HaConfigSectionTranslation.is, HaConfigSectionTranslation);
</script>

View File

@ -1,93 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../src/util/hass-util.html">
<link rel="import" href="../../../src/resources/ha-style.html">
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="./ha-form-customize.html">
<link rel="import" href="../ha-config-section.html">
<link rel="import" href="../ha-entity-config.html">
<dom-module id="ha-config-customize">
<template>
<style include="ha-style">
</style>
<app-header-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<paper-icon-button
icon='mdi: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>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigCustomize extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-config-customize'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
entities: {
type: Array,
computed: 'computeEntities(hass)',
},
entityConfig: {
type: Object,
value: {
component: 'ha-form-customize',
computeSelectCaption: stateObj =>
window.hassUtil.computeStateName(stateObj) + ' (' + window.hassUtil.computeDomain(stateObj) + ')'
}
},
};
}
computeClasses(isWide) {
return isWide ? 'content' : 'content narrow';
}
_backTapped() {
history.back();
}
computeEntities(hass) {
return Object.keys(hass.states)
.map(key => hass.states[key])
.sort(window.hassUtil.sortByName);
}
}
customElements.define(HaConfigCustomize.is, HaConfigCustomize);
</script>

View File

@ -0,0 +1,84 @@
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import '../../../src/util/hass-util.js';
import '../ha-config-section.js';
import '../ha-entity-config.js';
import './ha-form-customize.js';
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigCustomize extends window.hassMixins.LocalizeMixin(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="mdi: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>
`;
}
static get is() { return 'ha-config-customize'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
entities: {
type: Array,
computed: 'computeEntities(hass)',
},
entityConfig: {
type: Object,
value: {
component: 'ha-form-customize',
computeSelectCaption: stateObj =>
window.hassUtil.computeStateName(stateObj) + ' (' + window.hassUtil.computeDomain(stateObj) + ')'
}
},
};
}
computeClasses(isWide) {
return isWide ? 'content' : 'content narrow';
}
_backTapped() {
history.back();
}
computeEntities(hass) {
return Object.keys(hass.states)
.map(key => hass.states[key])
.sort(window.hassUtil.sortByName);
}
}
customElements.define(HaConfigCustomize.is, HaConfigCustomize);

View File

@ -1,17 +1,18 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel='import' href="../../../bower_components/paper-icon-button/paper-icon-button.html">
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/util/hass-attributes-util.html">
import '../../../src/util/hass-attributes-util.js';
import '../ha-form-style.js';
import './types/ha-customize-array.js';
import './types/ha-customize-boolean.js';
import './types/ha-customize-icon.js';
import './types/ha-customize-key-value.js';
import './types/ha-customize-string.js';
<link rel="import" href="../ha-form-style.html">
<link rel="import" href="./types/ha-customize-array.html">
<link rel="import" href="./types/ha-customize-boolean.html">
<link rel="import" href="./types/ha-customize-icon.html">
<link rel="import" href="./types/ha-customize-key-value.html">
<link rel="import" href="./types/ha-customize-string.html">
<dom-module id="ha-customize-attribute">
<template>
class HaCustomizeAttribute extends PolymerElement {
static get template() {
return html`
<style include="ha-form-style">
:host {
display: block;
@ -26,13 +27,11 @@
right: 0;
}
</style>
<div id='wrapper' class='form-group'></div>
<div id="wrapper" class="form-group"></div>
<paper-icon-button class="button" icon="[[getIcon(item.secondary)]]" on-click="tapButton"></paper-icon-button>
</template>
</dom-module>
`;
}
<script>
class HaCustomizeAttribute extends Polymer.Element {
static get is() { return 'ha-customize-attribute'; }
static get properties() {
@ -82,4 +81,3 @@ class HaCustomizeAttribute extends Polymer.Element {
}
}
customElements.define(HaCustomizeAttribute.is, HaCustomizeAttribute);
</script>

View File

@ -1,36 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/polymer/lib/mixins/mutable-data.html">
<link rel="import" href="./ha-customize-attribute.html">
<dom-module id="ha-form-customize-attributes">
<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>
</template>
</dom-module>
<script>
class HaFormCustomizeAttributes extends Polymer.MutableData(Polymer.Element) {
static get is() { return 'ha-form-customize-attributes'; }
static get properties() {
return {
attributes: {
type: Array,
notify: true,
},
};
}
}
customElements.define(HaFormCustomizeAttributes.is, HaFormCustomizeAttributes);
</script>

View File

@ -0,0 +1,33 @@
import { MutableData } from '@polymer/polymer/lib/mixins/mutable-data.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import './ha-customize-attribute.js';
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>
`;
}
static get is() { return 'ha-form-customize-attributes'; }
static get properties() {
return {
attributes: {
type: Array,
notify: true,
},
};
}
}
customElements.define(HaFormCustomizeAttributes.is, HaFormCustomizeAttributes);

View File

@ -1,15 +1,16 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/util/hass-util.html">
<link rel="import" href="../../../src/util/hass-attributes-util.html">
import '../../../src/util/hass-attributes-util.js';
import '../../../src/util/hass-util.js';
import './ha-form-customize-attributes.js';
<link rel="import" href="./ha-form-customize-attributes.html">
<dom-module id="ha-form-customize">
<template>
class HaFormCustomize extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style ha-form-style">
.warning {
color: red;
@ -19,59 +20,50 @@
padding-left: 20px;
}
</style>
<template is='dom-if' if='[[computeShowWarning(localConfig, globalConfig)]]'>
<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]]'>
<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]]'>
<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]]'>
<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]]'>
<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'>
<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>
</dom-module>
`;
}
<script>
class HaFormCustomize extends Polymer.Element {
static get is() { return 'ha-form-customize'; }
static get properties() {
@ -275,4 +267,3 @@ class HaFormCustomize extends Polymer.Element {
}
}
customElements.define(HaFormCustomize.is, HaFormCustomize);
</script>

View File

@ -1,36 +1,29 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../../../bower_components/paper-item/paper-item.html'>
<link rel="import" href="../../../../src/util/hass-mixins.html">
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='ha-customize-array'>
<template>
import '../../../../src/util/hass-mixins.js';
class HaCustomizeArray extends window.hassMixins.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-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>
</template>
</dom-module>
`;
}
<script>
class HaCustomizeArray extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-customize-array'; }
static get properties() {
@ -59,4 +52,3 @@ class HaCustomizeArray extends window.hassMixins.EventsMixin(Polymer.Element) {
}
}
customElements.define(HaCustomizeArray.is, HaCustomizeArray);
</script>

View File

@ -1,29 +0,0 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../../../bower_components/paper-checkbox/paper-checkbox.html'>
<dom-module id='ha-customize-boolean'>
<template>
<paper-checkbox
disabled='[[item.secondary]]'
checked="{{item.value}}"
>
[[item.description]]
</paper-checkbox>
</template>
</dom-module>
<script>
class HaCustomizeBoolean extends Polymer.Element {
static get is() { return 'ha-customize-boolean'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
}
customElements.define(HaCustomizeBoolean.is, HaCustomizeBoolean);
</script>

View File

@ -0,0 +1,25 @@
import '@polymer/paper-checkbox/paper-checkbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
class HaCustomizeBoolean extends PolymerElement {
static get template() {
return html`
<paper-checkbox disabled="[[item.secondary]]" checked="{{item.value}}">
[[item.description]]
</paper-checkbox>
`;
}
static get is() { return 'ha-customize-boolean'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
}
customElements.define(HaCustomizeBoolean.is, HaCustomizeBoolean);

View File

@ -1,42 +0,0 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../../../bower_components/iron-icon/iron-icon.html'>
<link rel='import' href='../../../../bower_components/paper-input/paper-input.html'>
<dom-module id='ha-customize-icon'>
<template>
<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
auto-validate pattern="(mdi:.*)?" error-message="Must start with 'mdi:'"
disabled='[[item.secondary]]'
label='icon'
value='{{item.value}}'>
</paper-input>
</template>
</dom-module>
<script>
class HaCustomizeIcon extends Polymer.Element {
static get is() { return 'ha-customize-icon'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
}
customElements.define(HaCustomizeIcon.is, HaCustomizeIcon);
</script>

View File

@ -0,0 +1,37 @@
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
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 auto-validate="" pattern="(mdi:.*)?" error-message="Must start with 'mdi:'" disabled="[[item.secondary]]" label="icon" value="{{item.value}}">
</paper-input>
`;
}
static get is() { return 'ha-customize-icon'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
}
customElements.define(HaCustomizeIcon.is, HaCustomizeIcon);

View File

@ -1,45 +0,0 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../../../bower_components/paper-input/paper-input.html'>
<dom-module id='ha-customize-key-value'>
<template>
<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>
</template>
</dom-module>
<script>
class HaCustomizeKeyValue extends Polymer.Element {
static get is() { return 'ha-customize-key-value'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
}
customElements.define(HaCustomizeKeyValue.is, HaCustomizeKeyValue);
</script>

View File

@ -0,0 +1,37 @@
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
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>
`;
}
static get is() { return 'ha-customize-key-value'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
}
customElements.define(HaCustomizeKeyValue.is, HaCustomizeKeyValue);

View File

@ -1,32 +0,0 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../../../bower_components/paper-input/paper-input.html'>
<dom-module id='ha-customize-string'>
<template>
<paper-input
disabled='[[item.secondary]]'
label='[[getLabel(item)]]'
value='{{item.value}}'>
</paper-input>
</template>
</dom-module>
<script>
class HaCustomizeString extends Polymer.Element {
static get is() { return 'ha-customize-string'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
getLabel(item) {
return item.description + (item.type === 'json' ? ' (JSON formatted)' : '');
}
}
customElements.define(HaCustomizeString.is, HaCustomizeString);
</script>

View File

@ -0,0 +1,28 @@
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
class HaCustomizeString extends PolymerElement {
static get template() {
return html`
<paper-input disabled="[[item.secondary]]" label="[[getLabel(item)]]" value="{{item.value}}">
</paper-input>
`;
}
static get is() { return 'ha-customize-string'; }
static get properties() {
return {
item: {
type: Object,
notifies: true,
}
};
}
getLabel(item) {
return item.description + (item.type === 'json' ? ' (JSON formatted)' : '');
}
}
customElements.define(HaCustomizeString.is, HaCustomizeString);

View File

@ -1,54 +0,0 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../../../src/util/hass-mixins.html">
<dom-module id="ha-config-cloud-menu">
<template>
<style include="iron-flex">
paper-card {
display: block;
}
paper-item {
cursor: pointer;
}
</style>
<paper-card>
<paper-item on-click='_navigate'>
<paper-item-body two-line>
Home Assistant Cloud
<template is='dom-if' if='[[account]]'>
<div secondary>Logged in as [[account.email]]</div>
</template>
<template is='dom-if' if='[[!account]]'>
<div secondary>Not logged in</div>
</template>
</paper-item-body>
<iron-icon icon='mdi:chevron-right'></iron-icon>
</paper-item>
</paper-card>
</template>
</dom-module>
<script>
class HaConfigCloudMenu extends window.hassMixins.NavigateMixin(Polymer.Element) {
static get is() { return 'ha-config-cloud-menu'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
account: Object,
};
}
_navigate() {
this.navigate('/config/cloud');
}
}
customElements.define(HaConfigCloudMenu.is, HaConfigCloudMenu);
</script>

View File

@ -0,0 +1,53 @@
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/util/hass-mixins.js';
class HaConfigCloudMenu extends window.hassMixins.NavigateMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex">
paper-card {
display: block;
}
paper-item {
cursor: pointer;
}
</style>
<paper-card>
<paper-item on-click="_navigate">
<paper-item-body two-line="">
Home Assistant Cloud
<template is="dom-if" if="[[account]]">
<div secondary="">Logged in as [[account.email]]</div>
</template>
<template is="dom-if" if="[[!account]]">
<div secondary="">Not logged in</div>
</template>
</paper-item-body>
<iron-icon icon="mdi:chevron-right"></iron-icon>
</paper-item>
</paper-card>
`;
}
static get is() { return 'ha-config-cloud-menu'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
account: Object,
};
}
_navigate() {
this.navigate('/config/cloud');
}
}
customElements.define(HaConfigCloudMenu.is, HaConfigCloudMenu);

View File

@ -1,83 +0,0 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../src/components/ha-menu-button.html">
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../ha-config-section.html">
<link rel="import" href="./ha-config-navigation.html">
<link rel="import" href="./ha-config-cloud-menu.html">
<link rel="import" href="./ha-config-entries-menu.html">
<dom-module id="ha-config-dashboard">
<template>
<style include="iron-flex ha-style">
.content {
padding-bottom: 32px;
}
</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>[[localize('panel.configuration')]]</div>
</app-toolbar>
</app-header>
<div class='content'>
<ha-config-section
is-wide='[[isWide]]'
>
<span slot='header'>[[localize('ui.panel.config.header')]]</span>
<span slot='introduction'>[[localize('ui.panel.config.introduction')]]</span>
<template is='dom-if' if='[[computeIsLoaded(hass, "cloud")]]'>
<ha-config-cloud-menu
hass='[[hass]]'
account='[[account]]'
></ha-config-cloud-menu>
</template>
<template is='dom-if' if='[[computeIsLoaded(hass, "config.config_entries")]]'>
<ha-config-entries-menu
hass='[[hass]]'
></ha-config-entries-menu>
</template>
<ha-config-navigation
hass='[[hass]]'
></ha-config-navigation>
</ha-config-section>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigDashboard extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-config-dashboard'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
account: Object,
narrow: Boolean,
showMenu: Boolean,
};
}
computeIsLoaded(hass, component) {
return window.hassUtil.isComponentLoaded(hass, component);
}
}
customElements.define(HaConfigDashboard.is, HaConfigDashboard);
</script>

View File

@ -0,0 +1,71 @@
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/components/ha-menu-button.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
import './ha-config-cloud-menu.js';
import './ha-config-entries-menu.js';
import './ha-config-navigation.js';
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigDashboard extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
padding-bottom: 32px;
}
</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="">[[localize('panel.configuration')]]</div>
</app-toolbar>
</app-header>
<div class="content">
<ha-config-section is-wide="[[isWide]]">
<span slot="header">[[localize('ui.panel.config.header')]]</span>
<span slot="introduction">[[localize('ui.panel.config.introduction')]]</span>
<template is="dom-if" if="[[computeIsLoaded(hass, &quot;cloud&quot;)]]">
<ha-config-cloud-menu hass="[[hass]]" account="[[account]]"></ha-config-cloud-menu>
</template>
<template is="dom-if" if="[[computeIsLoaded(hass, &quot;config.config_entries&quot;)]]">
<ha-config-entries-menu hass="[[hass]]"></ha-config-entries-menu>
</template>
<ha-config-navigation hass="[[hass]]"></ha-config-navigation>
</ha-config-section>
</div>
</app-header-layout>
`;
}
static get is() { return 'ha-config-dashboard'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
account: Object,
narrow: Boolean,
showMenu: Boolean,
};
}
computeIsLoaded(hass, component) {
return window.hassUtil.isComponentLoaded(hass, component);
}
}
customElements.define(HaConfigDashboard.is, HaConfigDashboard);

View File

@ -1,49 +0,0 @@
<link rel="import" href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../../../src/util/hass-mixins.html">
<dom-module id="ha-config-entries-menu">
<template>
<style include="iron-flex">
paper-card {
display: block;
}
paper-item {
cursor: pointer;
}
</style>
<paper-card>
<paper-item on-click='_navigate'>
<paper-item-body two-line>
Integrations
<div secondary>EXPERIMENTAL Manage connected devices and services</div>
</paper-item-body>
<iron-icon icon='mdi:chevron-right'></iron-icon>
</paper-item>
</paper-card>
</template>
</dom-module>
<script>
class HaConfigEntriesMenu extends window.hassMixins.NavigateMixin(Polymer.Element) {
static get is() { return 'ha-config-entries-menu'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
account: Object,
};
}
_navigate() {
this.navigate('/config/integrations');
}
}
customElements.define(HaConfigEntriesMenu.is, HaConfigEntriesMenu);
</script>

View File

@ -0,0 +1,48 @@
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/util/hass-mixins.js';
class HaConfigEntriesMenu extends window.hassMixins.NavigateMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex">
paper-card {
display: block;
}
paper-item {
cursor: pointer;
}
</style>
<paper-card>
<paper-item on-click="_navigate">
<paper-item-body two-line="">
Integrations
<div secondary="">EXPERIMENTAL Manage connected devices and services</div>
</paper-item-body>
<iron-icon icon="mdi:chevron-right"></iron-icon>
</paper-item>
</paper-card>
`;
}
static get is() { return 'ha-config-entries-menu'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
account: Object,
};
}
_navigate() {
this.navigate('/config/integrations');
}
}
customElements.define(HaConfigEntriesMenu.is, HaConfigEntriesMenu);

View File

@ -1,38 +1,12 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/iron-icon/iron-icon.html">
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/util/hass-mixins.html'>
import '../../../src/util/hass-mixins.js';
<dom-module id="ha-config-navigation">
<template>
<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='mdi:chevron-right'></iron-icon>
</paper-item>
</template>
</template>
</paper-card>
</template>
</dom-module>
<script>
{
const CORE_PAGES = [
'core',
@ -43,7 +17,33 @@
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaConfigNavigation extends
window.hassMixins.LocalizeMixin(window.hassMixins.NavigateMixin(Polymer.Element)) {
window.hassMixins.LocalizeMixin(window.hassMixins.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="mdi:chevron-right"></iron-icon>
</paper-item>
</template>
</template>
</paper-card>
`;
}
static get is() { return 'ha-config-navigation'; }
static get properties() {
@ -84,4 +84,3 @@
customElements.define(HaConfigNavigation.is, HaConfigNavigation);
}
</script>

View File

@ -1 +0,0 @@
<script src='../../build-temp/panel-config.js'></script>

View File

@ -0,0 +1 @@

View File

@ -1,8 +1,11 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../src/resources/ha-style.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="ha-config-section">
<template>
import '../../src/resources/ha-style.js';
class HaConfigSection extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
padding: 28px 20px 0;
@ -52,22 +55,20 @@
max-width: 500px;
}
</style>
<div class$='[[computeContentClasses(isWide)]]'>
<div class='header'><slot name="header"></slot></div>
<div class$='[[computeClasses(isWide)]]'>
<div class='intro'>
<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'>
<div class="panel flex-auto">
<slot></slot>
</div>
</div>
</div>
</template>
</dom-module>
`;
}
<script>
class HaConfigSection extends Polymer.Element {
static get is() { return 'ha-config-section'; }
static get properties() {
@ -106,4 +107,3 @@ class HaConfigSection extends Polymer.Element {
}
customElements.define(HaConfigSection.is, HaConfigSection);
</script>

View File

@ -1,13 +1,15 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
<link rel="import" href="../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="../../bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import '@polymer/paper-spinner/paper-spinner.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="ha-entity-config">
<template>
class HaEntityConfig extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
paper-card {
display: block;
@ -34,61 +36,44 @@
}
</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'>
<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)]]'>
<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>
<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 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>
<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>
`;
}
</template>
</dom-module>
<script>
class HaEntityConfig extends Polymer.Element {
static get is() { return 'ha-entity-config'; }
static get properties() {
@ -214,4 +199,3 @@ class HaEntityConfig extends Polymer.Element {
}
customElements.define(HaEntityConfig.is, HaEntityConfig);
</script>

View File

@ -1,4 +1,7 @@
<dom-module id='ha-form-style'>
const documentContainer = document.createElement('template');
documentContainer.setAttribute('style', 'display: none;');
documentContainer.innerHTML = `<dom-module id="ha-form-style">
<template>
<style>
.form-group {
@ -25,4 +28,6 @@
}
</style>
</template>
</dom-module>
</dom-module>`;
document.head.appendChild(documentContainer.content);

View File

@ -1,21 +1,24 @@
<link rel="import" href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/iron-media-query/iron-media-query.html'>
<link rel='import' href='../../bower_components/app-route/app-route.html'>
import '@polymer/app-route/app-route.js';
import '@polymer/iron-media-query/iron-media-query.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../src/layouts/hass-error-screen.html">
<link rel="import" href="../../src/util/hass-mixins.html">
import '../../build-temp/panel-config.js';
import '../../src/layouts/hass-error-screen.js';
import '../../src/util/hass-mixins.js';
import './automation/ha-config-automation.js';
import './cloud/ha-config-cloud.js';
import './config-entries/ha-config-entries.js';
import './core/ha-config-core.js';
import './customize/ha-config-customize.js';
import './dashboard/ha-config-dashboard.js';
import './script/ha-config-script.js';
import './zwave/ha-config-zwave.js';
<link rel="import" href="./dashboard/ha-config-dashboard.html">
<link rel="import" href="./core/ha-config-core.html">
<link rel="import" href="./cloud/ha-config-cloud.html">
<link rel="import" href="./automation/ha-config-automation.html">
<link rel="import" href="./script/ha-config-script.html">
<link rel="import" href="./zwave/ha-config-zwave.html">
<link rel="import" href="./customize/ha-config-customize.html">
<link rel="import" href="./config-entries/ha-config-entries.html">
<dom-module id="ha-panel-config">
<template>
class HaPanelConfig extends window.hassMixins.NavigateMixin(PolymerElement) {
static get template() {
return html`
<app-route
route='[[route]]'
pattern='/:page'
@ -97,11 +100,9 @@
is-wide='[[isWide]]'
></ha-config-entries>
</template>
</template>
</dom-module>
`;
}
<script>
class HaPanelConfig extends window.hassMixins.NavigateMixin(Polymer.Element) {
static get is() { return 'ha-panel-config'; }
static get properties() {
@ -154,4 +155,3 @@ class HaPanelConfig extends window.hassMixins.NavigateMixin(Polymer.Element) {
}
customElements.define(HaPanelConfig.is, HaPanelConfig);
</script>

View File

@ -1,52 +1,32 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel='import' href='../../../bower_components/app-route/app-route.html'>
import '@polymer/app-route/app-route.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="./ha-script-picker.html">
<link rel="import" href="./ha-script-editor.html">
import './ha-script-editor.js';
import './ha-script-picker.js';
<dom-module id="ha-config-script">
<template>
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>
<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 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 is="dom-if" if="[[showEditor]]" restamp="">
<ha-script-editor hass="[[hass]]" script="[[script]]" is-wide="[[isWide]]" creating-new="[[_creatingNew]]"></ha-script-editor>
</template>
</template>
</dom-module>
`;
}
<script>
class HaConfigScript extends Polymer.Element {
static get is() { return 'ha-config-script'; }
static get properties() {
@ -121,4 +101,3 @@ class HaConfigScript extends Polymer.Element {
}
customElements.define(HaConfigScript.is, HaConfigScript);
</script>

View File

@ -1,31 +1,34 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../../../bower_components/paper-radio-button/paper-radio-button.html">
<link rel="import" href="../../../bower_components/paper-radio-group/paper-radio-group.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu-light.html">
<link rel="import" href="../../../bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="../../../bower_components/paper-menu-button/paper-menu-button.html">
<link rel="import" href="../../../bower_components/paper-fab/paper-fab.html">
<link rel="import" href="../../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu-light.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-input/paper-textarea.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import '@polymer/paper-menu-button/paper-menu-button.js';
import '@polymer/paper-radio-button/paper-radio-button.js';
import '@polymer/paper-radio-group/paper-radio-group.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/components/entity/ha-entity-picker.html'>
<link rel='import' href='../../../src/components/ha-combo-box.html'>
<link rel='import' href='../../../src/layouts/ha-app-layout.html'>
<link rel='import' href='../../../src/util/hass-mixins.html'>
import '../../../src/components/entity/ha-entity-picker.js';
import '../../../src/components/ha-combo-box.js';
import '../../../src/layouts/ha-app-layout.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-js.js';
import '../ha-config-section.js';
<link rel="import" href="../ha-config-section.html">
<link rel="import" href="../ha-config-js.html">
<dom-module id="ha-script-editor">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaScriptEditor extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style">
.errors {
padding: 20px;
@ -81,39 +84,24 @@
margin-bottom: 0;
}
</style>
<ha-app-layout has-scrolling-region>
<app-header slot="header" fixed>
<ha-app-layout has-scrolling-region="">
<app-header slot="header" fixed="">
<app-toolbar>
<paper-icon-button
icon='mdi:arrow-left'
on-click='backTapped'
></paper-icon-button>
<div main-title>Script [[name]]</div>
<paper-icon-button icon="mdi:arrow-left" on-click="backTapped"></paper-icon-button>
<div main-title="">Script [[name]]</div>
</app-toolbar>
</app-header>
<div class='content'>
<template is='dom-if' if='[[errors]]'>
<div class='errors'>[[errors]]</div>
<div class="content">
<template is="dom-if" if="[[errors]]">
<div class="errors">[[errors]]</div>
</template>
<div id='root'></div>
<div id="root"></div>
</div>
<paper-fab slot="fab"
is-wide$='[[isWide]]'
dirty$='[[dirty]]'
icon='mdi:content-save'
title='Save'
on-click='saveScript'
></paper-fab>
<paper-fab slot="fab" is-wide\$="[[isWide]]" dirty\$="[[dirty]]" icon="mdi:content-save" title="Save" on-click="saveScript"></paper-fab>
</ha-app-layout>
`;
}
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaScriptEditor extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-script-editor'; }
static get properties() {
@ -286,4 +274,3 @@ class HaScriptEditor extends window.hassMixins.LocalizeMixin(Polymer.Element) {
}
customElements.define(HaScriptEditor.is, HaScriptEditor);
</script>

View File

@ -1,150 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/paper-fab/paper-fab.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel='import' href='../../../src/layouts/ha-app-layout.html'>
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../ha-config-section.html">
<dom-module id="ha-script-picker">
<template>
<style include="ha-style">
:host {
display: block;
}
paper-item {
cursor: pointer;
}
paper-fab {
position: fixed;
bottom: 16px;
right: 16px;
z-index: 1;
}
paper-fab[is-wide] {
bottom: 24px;
right: 24px;
}
a {
color: var(--primary-color);
}
</style>
<ha-app-layout has-scrolling-region>
<app-header slot="header" fixed>
<app-toolbar>
<paper-icon-button
icon='mdi: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>
</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='mdi:chevron-right'></iron-icon>
</paper-item>
</template>
</paper-card>
</ha-config-section>
<paper-fab slot="fab"
is-wide$='[[isWide]]'
icon='mdi:plus'
title='Add Script'
on-click='addScript'
></paper-fab>
</ha-app-layout>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaScriptPicker extends
window.hassMixins.LocalizeMixin(window.hassMixins.NavigateMixin(Polymer.Element)) {
static get is() { return 'ha-script-picker'; }
static get properties() {
return {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
scripts: {
type: Array,
},
isWide: {
type: Boolean,
},
};
}
scriptTapped(ev) {
this.navigate('/config/script/edit/' + this.scripts[ev.model.index].entity_id);
}
addScript() {
this.navigate('/config/script/new');
}
computeName(script) {
return window.hassUtil.computeStateName(script);
}
// Still thinking of something to add here.
// eslint-disable-next-line
computeDescription(script) {
return '';
}
_backTapped() {
history.back();
}
}
customElements.define(HaScriptPicker.is, HaScriptPicker);
</script>

View File

@ -0,0 +1,137 @@
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-fab/paper-fab.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/layouts/ha-app-layout.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaScriptPicker extends
window.hassMixins.LocalizeMixin(window.hassMixins.NavigateMixin(PolymerElement)) {
static get template() {
return html`
<style include="ha-style">
:host {
display: block;
}
paper-item {
cursor: pointer;
}
paper-fab {
position: fixed;
bottom: 16px;
right: 16px;
z-index: 1;
}
paper-fab[is-wide] {
bottom: 24px;
right: 24px;
}
a {
color: var(--primary-color);
}
</style>
<ha-app-layout has-scrolling-region="">
<app-header slot="header" fixed="">
<app-toolbar>
<paper-icon-button icon="mdi: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>
</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="mdi:chevron-right"></iron-icon>
</paper-item>
</template>
</paper-card>
</ha-config-section>
<paper-fab slot="fab" is-wide\$="[[isWide]]" icon="mdi:plus" title="Add Script" on-click="addScript"></paper-fab>
</ha-app-layout>
`;
}
static get is() { return 'ha-script-picker'; }
static get properties() {
return {
hass: {
type: Object,
},
narrow: {
type: Boolean,
},
showMenu: {
type: Boolean,
value: false,
},
scripts: {
type: Array,
},
isWide: {
type: Boolean,
},
};
}
scriptTapped(ev) {
this.navigate('/config/script/edit/' + this.scripts[ev.model.index].entity_id);
}
addScript() {
this.navigate('/config/script/new');
}
computeName(script) {
return window.hassUtil.computeStateName(script);
}
// Still thinking of something to add here.
// eslint-disable-next-line
computeDescription(script) {
return '';
}
_backTapped() {
history.back();
}
}
customElements.define(HaScriptPicker.is, HaScriptPicker);

View File

@ -1,618 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../src/components/ha-menu-button.html">
<link rel="import" href="../../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
<link rel='import' href="../../../bower_components/paper-listbox/paper-listbox.html">
<link rel='import' href="../../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
<link rel="import" href="../../../src/components/ha-service-description.html">
<link rel='import' href='../../../src/layouts/ha-app-layout.html'>
<link rel="import" href="../../../src/resources/ha-style.html">
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../ha-config-section.html">
<link rel="import" href="../ha-form-style.html">
<link rel="import" href="./zwave-log.html">
<link rel="import" href="./zwave-network.html">
<link rel="import" href="./zwave-node-information.html">
<link rel="import" href="./zwave-values.html">
<link rel="import" href="./zwave-groups.html">
<link rel="import" href="./zwave-node-config.html">
<link rel="import" href="./zwave-usercodes.html">
<dom-module id="ha-config-zwave">
<template>
<style include="iron-flex ha-style ha-form-style">
.content {
margin-top: 24px;
}
.node-info {
margin-left: 16px;
}
.help-text {
padding-left: 24px;
padding-right: 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;
}
ha-service-description {
display: block;
color: grey;
}
[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='mdi: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>
<!--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='mdi: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>
</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>
<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>
<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>
</div>
<div class='card-actions'>
<paper-input
float-label="New node name"
type=text
value={{newNodeNameInput}}
placeholder=[[computeGetNodeName(selectedNode)]]>
</paper-input>
<ha-call-service-button
hass='[[hass]]'
domain='zwave'
service='rename_node'
service-data=[[computeNodeNameServiceData(newNodeNameInput)]]
>Rename Node</ha-call-service-button>
<ha-service-description
hass='[[hass]]'
domain='zwave'
service='rename_node'
hidden$='[[!showHelp]]'
></ha-service-description>
</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>[[computeSelectCaptionEnt(state)]]</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>
</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>
<div class='content'>
<div class='card-actions'>
<paper-button toggles raised noink active={{entityInfoActive}}>Entity Attributes</paper-button>
</div>
<template is='dom-if' if={{entityInfoActive}}>
<template is='dom-repeat' items='[[selectedEntityAttrs]]' as='state'>
<div class='node-info'>
<span>[[state]]</span>
</div>
</template>
</template>
</div>
</template>
</template>
</paper-card>
<template is='dom-if' if='[[computeIsNodeSelected(selectedNode)]]'>
<!--Node info card-->
<zwave-node-information
id='zwave-node-information'
nodes='[[nodes]]'
selected-node='[[selectedNode]]'
></zwave-node-information>
<!--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>
<!--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>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigZwave extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-config-zwave'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
nodes: {
type: Array,
computed: 'computeNodes(hass)'
},
selectedNode: {
type: Number,
value: -1,
observer: 'selectedNodeChanged'
},
config: {
type: Array,
value: function () {
return [];
}
},
entities: {
type: Array,
computed: 'computeEntities(selectedNode)',
},
entityInfoActive: {
type: Boolean,
},
selectedEntity: {
type: Number,
value: -1,
observer: 'selectedEntityChanged',
},
selectedEntityAttrs: {
type: Array,
computed: 'computeSelectedEntityAttrs(selectedEntity)'
},
values: {
type: Array,
},
groups: {
type: Array,
},
newNodeNameInput: {
type: String,
},
userCodes: {
type: Array,
value: function () {
return [];
},
},
hasNodeUserCodes: {
type: Boolean,
value: false,
},
showHelp: {
type: Boolean,
value: false,
},
entityIgnored: {
type: Boolean,
},
entityPollingIntensity: {
type: Number,
value: 0,
},
};
}
ready() {
super.ready();
this.addEventListener('hass-service-called', ev => this.serviceCalled(ev));
}
serviceCalled(ev) {
var el = this;
if ((ev.detail.success) && (ev.detail.service === 'set_poll_intensity')) {
el.saveEntity();
}
}
computeNodes(hass) {
return Object.keys(hass.states)
.map(function (key) { return hass.states[key]; })
.filter(function (ent) {
return ((ent.entity_id).match('zwave[.]'));
})
.sort(window.hassUtil.sortByName);
}
computeEntities(selectedNode) {
if (!this.nodes || selectedNode === -1) return -1;
var hass = this.hass;
var nodeid = this.nodes[this.selectedNode].attributes.node_id;
return Object.keys(hass.states)
.map(function (key) { return hass.states[key]; })
.filter(function (ent) {
if (ent.attributes.node_id === undefined) {
return false;
}
return (!ent.attributes.hidden &&
'node_id' in ent.attributes &&
ent.attributes.node_id === nodeid &&
(!(ent.entity_id).match('zwave[.]')));
})
.sort(window.hassUtil.sortByName);
}
selectedNodeChanged(selectedNode) {
this.newNodeNameInput = '';
if (selectedNode === -1) return;
this.selectedConfigParameter = -1;
this.selectedConfigParameterValue = -1;
this.selectedGroup = -1;
this.hass.callApi('GET', 'zwave/config/' + this.nodes[selectedNode].attributes.node_id).then((configs) => {
this.config = this._objToArray(configs);
});
this.hass.callApi('GET', 'zwave/values/' + this.nodes[selectedNode].attributes.node_id).then((values) => {
this.values = this._objToArray(values);
});
this.hass.callApi('GET', 'zwave/groups/' + this.nodes[selectedNode].attributes.node_id).then((groups) => {
this.groups = this._objToArray(groups);
});
this.hasNodeUserCodes = false;
this.notifyPath('hasNodeUserCodes');
this.hass.callApi('GET', 'zwave/usercodes/' + this.nodes[selectedNode].attributes.node_id).then((usercodes) => {
this.userCodes = this._objToArray(usercodes);
this.hasNodeUserCodes = this.userCodes.length > 0;
this.notifyPath('hasNodeUserCodes');
});
}
selectedEntityChanged(selectedEntity) {
if (selectedEntity === -1) return;
var el = this;
el.hass.callApi('GET', 'zwave/values/' + el.nodes[el.selectedNode].attributes.node_id).then((values) => {
el.values = el._objToArray(values);
});
var valueId = el.entities[selectedEntity].attributes.value_id;
var valueData = el.values.find(function (obj) { return obj.key === valueId; });
var valueIndex = el.values.indexOf(valueData);
el.hass.callApi('GET', 'config/zwave/device_config/' + valueId)
.then(function (data) {
el.entityIgnored = data.ignored || false;
el.entityPollingIntensity = el.values[valueIndex].value.poll_intensity;
});
}
computeSelectedEntityAttrs(selectedEntity) {
if (selectedEntity === -1) return 'No entity selected';
var entityAttrs = this.entities[selectedEntity].attributes;
var att = [];
Object.keys(entityAttrs).forEach(function (key) {
att.push(key + ': ' + entityAttrs[key]);
});
return att.sort();
}
computeSelectCaption(stateObj) {
return window.hassUtil.computeStateName(stateObj) + ' (Node:' +
stateObj.attributes.node_id + ' ' +
stateObj.attributes.query_stage + ')';
}
computeSelectCaptionEnt(stateObj) {
return (window.hassUtil.computeDomain(stateObj) + '.'
+ window.hassUtil.computeStateName(stateObj));
}
computeIsNodeSelected() {
return (this.nodes && this.selectedNode !== -1);
}
computeIsEntitySelected(selectedEntity) {
return (selectedEntity === -1);
}
computeNodeServiceData(selectedNode) {
return { node_id: this.nodes[selectedNode].attributes.node_id };
}
computeHealNodeServiceData(selectedNode) {
return {
node_id: this.nodes[selectedNode].attributes.node_id,
return_routes: true
};
}
computeGetNodeName(selectedNode) {
if (this.selectedNode === -1 ||
!this.nodes[selectedNode].entity_id) return -1;
return this.nodes[selectedNode].attributes.node_name;
}
computeNodeNameServiceData(newNodeNameInput) {
return {
node_id: this.nodes[this.selectedNode].attributes.node_id,
name: newNodeNameInput
};
}
computeRefreshEntityServiceData(selectedEntity) {
if (selectedEntity === -1) return -1;
return { entity_id: this.entities[selectedEntity].entity_id };
}
computePollIntensityServiceData(entityPollingIntensity) {
if (!this.selectedNode === -1 || this.selectedEntity === -1) return -1;
return {
node_id: this.nodes[this.selectedNode].attributes.node_id,
value_id: this.entities[this.selectedEntity].attributes.value_id,
poll_intensity: parseInt(entityPollingIntensity),
};
}
saveEntity() {
var data = {
ignored: this.entityIgnored,
polling_intensity: parseInt(this.entityPollingIntensity),
};
return this.hass.callApi('POST', 'config/zwave/device_config/' + this.entities[this.selectedEntity].entity_id, data);
}
toggleHelp() {
this.showHelp = !this.showHelp;
}
_objToArray(obj) {
var array = [];
Object.keys(obj).forEach(function (key) {
array.push({
key: key,
value: obj[key],
});
});
return array;
}
_backTapped() {
history.back();
}
}
customElements.define(HaConfigZwave.is, HaConfigZwave);
</script>

View File

@ -0,0 +1,477 @@
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/components/buttons/ha-call-service-button.js';
import '../../../src/components/ha-menu-button.js';
import '../../../src/components/ha-service-description.js';
import '../../../src/layouts/ha-app-layout.js';
import '../../../src/resources/ha-style.js';
import '../../../src/util/hass-mixins.js';
import '../ha-config-section.js';
import '../ha-form-style.js';
import './zwave-groups.js';
import './zwave-log.js';
import './zwave-network.js';
import './zwave-node-config.js';
import './zwave-node-information.js';
import './zwave-usercodes.js';
import './zwave-values.js';
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaConfigZwave extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style ha-form-style">
.content {
margin-top: 24px;
}
.node-info {
margin-left: 16px;
}
.help-text {
padding-left: 24px;
padding-right: 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;
}
ha-service-description {
display: block;
color: grey;
}
[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="mdi: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>
<!--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="mdi: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>
</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>
<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>
<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>
</div>
<div class="card-actions">
<paper-input float-label="New node name" type="text" value="{{newNodeNameInput}}" placeholder="[[computeGetNodeName(selectedNode)]]">
</paper-input>
<ha-call-service-button hass="[[hass]]" domain="zwave" service="rename_node" service-data="[[computeNodeNameServiceData(newNodeNameInput)]]">Rename Node</ha-call-service-button>
<ha-service-description hass="[[hass]]" domain="zwave" service="rename_node" hidden\$="[[!showHelp]]"></ha-service-description>
</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>[[computeSelectCaptionEnt(state)]]</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>
</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>
<div class="content">
<div class="card-actions">
<paper-button toggles="" raised="" noink="" active="{{entityInfoActive}}">Entity Attributes</paper-button>
</div>
<template is="dom-if" if="{{entityInfoActive}}">
<template is="dom-repeat" items="[[selectedEntityAttrs]]" as="state">
<div class="node-info">
<span>[[state]]</span>
</div>
</template>
</template>
</div>
</template>
</template>
</paper-card>
<template is="dom-if" if="[[computeIsNodeSelected(selectedNode)]]">
<!--Node info card-->
<zwave-node-information id="zwave-node-information" nodes="[[nodes]]" selected-node="[[selectedNode]]"></zwave-node-information>
<!--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>
<!--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>
`;
}
static get is() { return 'ha-config-zwave'; }
static get properties() {
return {
hass: Object,
isWide: Boolean,
nodes: {
type: Array,
computed: 'computeNodes(hass)'
},
selectedNode: {
type: Number,
value: -1,
observer: 'selectedNodeChanged'
},
config: {
type: Array,
value: function () {
return [];
}
},
entities: {
type: Array,
computed: 'computeEntities(selectedNode)',
},
entityInfoActive: {
type: Boolean,
},
selectedEntity: {
type: Number,
value: -1,
observer: 'selectedEntityChanged',
},
selectedEntityAttrs: {
type: Array,
computed: 'computeSelectedEntityAttrs(selectedEntity)'
},
values: {
type: Array,
},
groups: {
type: Array,
},
newNodeNameInput: {
type: String,
},
userCodes: {
type: Array,
value: function () {
return [];
},
},
hasNodeUserCodes: {
type: Boolean,
value: false,
},
showHelp: {
type: Boolean,
value: false,
},
entityIgnored: {
type: Boolean,
},
entityPollingIntensity: {
type: Number,
value: 0,
},
};
}
ready() {
super.ready();
this.addEventListener('hass-service-called', ev => this.serviceCalled(ev));
}
serviceCalled(ev) {
var el = this;
if ((ev.detail.success) && (ev.detail.service === 'set_poll_intensity')) {
el.saveEntity();
}
}
computeNodes(hass) {
return Object.keys(hass.states)
.map(function (key) { return hass.states[key]; })
.filter(function (ent) {
return ((ent.entity_id).match('zwave[.]'));
})
.sort(window.hassUtil.sortByName);
}
computeEntities(selectedNode) {
if (!this.nodes || selectedNode === -1) return -1;
var hass = this.hass;
var nodeid = this.nodes[this.selectedNode].attributes.node_id;
return Object.keys(hass.states)
.map(function (key) { return hass.states[key]; })
.filter(function (ent) {
if (ent.attributes.node_id === undefined) {
return false;
}
return (!ent.attributes.hidden &&
'node_id' in ent.attributes &&
ent.attributes.node_id === nodeid &&
(!(ent.entity_id).match('zwave[.]')));
})
.sort(window.hassUtil.sortByName);
}
selectedNodeChanged(selectedNode) {
this.newNodeNameInput = '';
if (selectedNode === -1) return;
this.selectedConfigParameter = -1;
this.selectedConfigParameterValue = -1;
this.selectedGroup = -1;
this.hass.callApi('GET', 'zwave/config/' + this.nodes[selectedNode].attributes.node_id).then((configs) => {
this.config = this._objToArray(configs);
});
this.hass.callApi('GET', 'zwave/values/' + this.nodes[selectedNode].attributes.node_id).then((values) => {
this.values = this._objToArray(values);
});
this.hass.callApi('GET', 'zwave/groups/' + this.nodes[selectedNode].attributes.node_id).then((groups) => {
this.groups = this._objToArray(groups);
});
this.hasNodeUserCodes = false;
this.notifyPath('hasNodeUserCodes');
this.hass.callApi('GET', 'zwave/usercodes/' + this.nodes[selectedNode].attributes.node_id).then((usercodes) => {
this.userCodes = this._objToArray(usercodes);
this.hasNodeUserCodes = this.userCodes.length > 0;
this.notifyPath('hasNodeUserCodes');
});
}
selectedEntityChanged(selectedEntity) {
if (selectedEntity === -1) return;
var el = this;
el.hass.callApi('GET', 'zwave/values/' + el.nodes[el.selectedNode].attributes.node_id).then((values) => {
el.values = el._objToArray(values);
});
var valueId = el.entities[selectedEntity].attributes.value_id;
var valueData = el.values.find(function (obj) { return obj.key === valueId; });
var valueIndex = el.values.indexOf(valueData);
el.hass.callApi('GET', 'config/zwave/device_config/' + valueId)
.then(function (data) {
el.entityIgnored = data.ignored || false;
el.entityPollingIntensity = el.values[valueIndex].value.poll_intensity;
});
}
computeSelectedEntityAttrs(selectedEntity) {
if (selectedEntity === -1) return 'No entity selected';
var entityAttrs = this.entities[selectedEntity].attributes;
var att = [];
Object.keys(entityAttrs).forEach(function (key) {
att.push(key + ': ' + entityAttrs[key]);
});
return att.sort();
}
computeSelectCaption(stateObj) {
return window.hassUtil.computeStateName(stateObj) + ' (Node:' +
stateObj.attributes.node_id + ' ' +
stateObj.attributes.query_stage + ')';
}
computeSelectCaptionEnt(stateObj) {
return (window.hassUtil.computeDomain(stateObj) + '.'
+ window.hassUtil.computeStateName(stateObj));
}
computeIsNodeSelected() {
return (this.nodes && this.selectedNode !== -1);
}
computeIsEntitySelected(selectedEntity) {
return (selectedEntity === -1);
}
computeNodeServiceData(selectedNode) {
return { node_id: this.nodes[selectedNode].attributes.node_id };
}
computeHealNodeServiceData(selectedNode) {
return {
node_id: this.nodes[selectedNode].attributes.node_id,
return_routes: true
};
}
computeGetNodeName(selectedNode) {
if (this.selectedNode === -1 ||
!this.nodes[selectedNode].entity_id) return -1;
return this.nodes[selectedNode].attributes.node_name;
}
computeNodeNameServiceData(newNodeNameInput) {
return {
node_id: this.nodes[this.selectedNode].attributes.node_id,
name: newNodeNameInput
};
}
computeRefreshEntityServiceData(selectedEntity) {
if (selectedEntity === -1) return -1;
return { entity_id: this.entities[selectedEntity].entity_id };
}
computePollIntensityServiceData(entityPollingIntensity) {
if (!this.selectedNode === -1 || this.selectedEntity === -1) return -1;
return {
node_id: this.nodes[this.selectedNode].attributes.node_id,
value_id: this.entities[this.selectedEntity].attributes.value_id,
poll_intensity: parseInt(entityPollingIntensity),
};
}
saveEntity() {
var data = {
ignored: this.entityIgnored,
polling_intensity: parseInt(this.entityPollingIntensity),
};
return this.hass.callApi('POST', 'config/zwave/device_config/' + this.entities[this.selectedEntity].entity_id, data);
}
toggleHelp() {
this.showHelp = !this.showHelp;
}
_objToArray(obj) {
var array = [];
Object.keys(obj).forEach(function (key) {
array.push({
key: key,
value: obj[key],
});
});
return array;
}
_backTapped() {
history.back();
}
}
customElements.define(HaConfigZwave.is, HaConfigZwave);

View File

@ -1,13 +1,15 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
<link rel='import' href="../../../bower_components/paper-listbox/paper-listbox.html">
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
import '../../../src/components/buttons/ha-call-service-button.js';
<dom-module id='zwave-groups'>
<template>
class ZwaveGroups extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
@ -33,70 +35,54 @@
padding-bottom: 12px;
}
</style>
<paper-card class="content" heading='Node group associations'>
<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'>
<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)]]'>
<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'>
<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'>
<div class="help-text">
<span>Other Nodes in this group:</span>
<template is='dom-repeat' items='[[otherGroupNodes]]' as='state'>
<template is="dom-repeat" items="[[otherGroupNodes]]" as="state">
<div>[[state]]</div>
</template>
</div>
<div class='help-text'>
<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='[[computeAssocServiceData(selectedGroup, "add")]]'
>Add To Group</ha-call-service-button>
<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="[[computeAssocServiceData(selectedGroup, &quot;add&quot;)]]">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='[[computeAssocServiceData(selectedGroup, "remove")]]'
>Remove From Group</ha-call-service-button>
<template is="dom-if" if="[[computeTargetInGroup(selectedGroup, selectedTargetNode)]]">
<ha-call-service-button hass="[[hass]]" domain="zwave" service="change_association" service-data="[[computeAssocServiceData(selectedGroup, &quot;remove&quot;)]]">Remove From Group</ha-call-service-button>
</template>
</div>
</template>
</paper-card>
</template>
</dom-module>
`;
}
<script>
class ZwaveGroups extends Polymer.Element {
static get is() { return 'zwave-groups'; }
static get properties() {
@ -253,4 +239,3 @@ class ZwaveGroups extends Polymer.Element {
}
customElements.define(ZwaveGroups.is, ZwaveGroups);
</script>

View File

@ -1,13 +1,15 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../../bower_components/paper-checkbox/paper-checkbox.html">
<link rel="import" href="../../../bower_components/paper-input/paper-input.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../ha-config-section.html">
import '../ha-config-section.js';
<dom-module id='ozw-log'>
<template>
class OzwLog extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
@ -25,32 +27,24 @@
padding-bottom: 24px;
}
</style>
<ha-config-section is-wide='[[isWide]]'>
<span slot='header'>OZW Log</span>
<ha-config-section is-wide="[[isWide]]">
<span slot="header">OZW Log</span>
<paper-card>
<div class='device-picker'>
<paper-input
label="Number of last log lines."
type=number
min=0
max=1000
step=10
value={{numLogLines}}>
<div class="device-picker">
<paper-input label="Number of last log lines." type="number" min="0" max="1000" step="10" value="{{numLogLines}}">
</paper-input>
</div>
<div class="card-actions">
<paper-button raised on-click='refreshLog'>Refresh</paper-button>
<paper-button raised="" on-click="refreshLog">Refresh</paper-button>
</div>
<div class='help-text'>
<div class="help-text">
<pre>[[ozwLogs]]</pre>
</div>
</paper-card>
</ha-config-section>
</template>
</dom-module>
<script>
`;
}
class OzwLog extends Polymer.Element {
static get is() { return 'ozw-log'; }
static get properties() {
@ -86,4 +80,3 @@ class OzwLog extends Polymer.Element {
}
customElements.define(OzwLog.is, OzwLog);
</script>

View File

@ -1,204 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
<link rel="import" href="../../../src/components/buttons/ha-call-api-button.html">
<link rel="import" href="../../../src/components/ha-service-description.html">
<link rel="import" href="../ha-config-section.html">
<dom-module id='zwave-network'>
<template>
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
}
paper-card {
display: block;
margin: 0 auto;
max-width: 600px;
}
.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);
}
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='mdi: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>
</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='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='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='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='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>
</template>
</dom-module>
<script>
class ZwaveNetwork extends Polymer.Element {
static get is() { return 'zwave-network'; }
static get properties() {
return {
hass: {
type: Object,
},
isWide: {
type: Boolean,
value: false,
},
showDescription: {
type: Boolean,
value: false,
},
};
}
helpTap() {
this.showDescription = !this.showDescription;
}
}
customElements.define(ZwaveNetwork.is, ZwaveNetwork);
</script>

View File

@ -0,0 +1,120 @@
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../src/components/buttons/ha-call-api-button.js';
import '../../../src/components/buttons/ha-call-service-button.js';
import '../../../src/components/ha-service-description.js';
import '../ha-config-section.js';
class ZwaveNetwork 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;
}
.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);
}
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="mdi: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>
</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="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="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="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="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 is() { return 'zwave-network'; }
static get properties() {
return {
hass: {
type: Object,
},
isWide: {
type: Boolean,
value: false,
},
showDescription: {
type: Boolean,
value: false,
},
};
}
helpTap() {
this.showDescription = !this.showDescription;
}
}
customElements.define(ZwaveNetwork.is, ZwaveNetwork);

View File

@ -1,14 +1,16 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
<link rel='import' href="../../../bower_components/paper-listbox/paper-listbox.html">
<link rel='import' href="../../../bower_components/paper-input/paper-input.html">
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
import '../../../src/components/buttons/ha-call-service-button.js';
<dom-module id='zwave-node-config'>
<template>
class ZwaveNodeConfig extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
@ -33,43 +35,30 @@
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>
<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>
<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'>
<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'>
<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>
@ -77,50 +66,36 @@
</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}}'>
<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'>
<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'>
<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>
<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>
</dom-module>
`;
}
<script>
class ZwaveNodeConfig extends Polymer.Element {
static get is() { return 'zwave-node-config'; }
static get properties() {
@ -321,4 +296,3 @@ class ZwaveNodeConfig extends Polymer.Element {
}
customElements.define(ZwaveNodeConfig.is, ZwaveNodeConfig);
</script>

View File

@ -1,9 +1,11 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-button/paper-button.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='zwave-node-information'>
<template>
class ZwaveNodeInformation extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
@ -25,26 +27,23 @@
</style>
<div class='content'>
<paper-card heading='Node Information'>
<div class='card-actions'>
<paper-button toggles raised noink active={{nodeInfoActive}}>Show</paper-button>
<div class="content">
<paper-card heading="Node Information">
<div class="card-actions">
<paper-button toggles="" raised="" noink="" active="{{nodeInfoActive}}">Show</paper-button>
</div>
<template is='dom-if' if={{nodeInfoActive}}>
<template is='dom-repeat' items='[[selectedNodeAttrs]]' as='state'>
<div class='node-info'>
<template is="dom-if" if="{{nodeInfoActive}}">
<template is="dom-repeat" items="[[selectedNodeAttrs]]" as="state">
<div class="node-info">
<span>[[state]]</span>
</div>
</template>
</template>
</paper-card>
</div>
`;
}
</template>
</dom-module>
<script>
class ZwaveNodeInformation extends Polymer.Element {
static get is() { return 'zwave-node-information'; }
static get properties() {
@ -82,4 +81,3 @@ class ZwaveNodeInformation extends Polymer.Element {
}
customElements.define(ZwaveNodeInformation.is, ZwaveNodeInformation);
</script>

View File

@ -1,14 +1,16 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
<link rel='import' href="../../../bower_components/paper-listbox/paper-listbox.html">
<link rel='import' href="../../../bower_components/paper-input/paper-input.html">
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
import '../../../src/components/buttons/ha-call-service-button.js';
<dom-module id='zwave-usercodes'>
<template>
class ZwaveUsercodes extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
@ -28,54 +30,34 @@
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'>
<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>
</div>
<template is='dom-if' if="[[isUserCodeSelected(selectedUserCode)]]">
<div class='card-actions'>
<paper-input
label='User code'
type='text'
allowed-pattern='[0-9,a-f,x,\\]'
maxlength='{{userCodeMaxLen}}'
minlength='16'
value='{{selectedUserCodeValue}}'>
<template is="dom-if" if="[[isUserCodeSelected(selectedUserCode)]]">
<div class="card-actions">
<paper-input label="User code" type="text" allowed-pattern="[0-9,a-f,x,\\\\]" maxlength="{{userCodeMaxLen}}" minlength="16" value="{{selectedUserCodeValue}}">
</paper-input>
<pre>Ascii: [[computedCodeOutput]]</pre>
</div>
<div class='card-actions'>
<ha-call-service-button
hass='[[hass]]'
domain='lock'
service='set_usercode'
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")]]'
>Delete Usercode</ha-call-service-button>
<div class="card-actions">
<ha-call-service-button hass="[[hass]]" domain="lock" service="set_usercode" service-data="[[computeUserCodeServiceData(selectedUserCodeValue, &quot;Add&quot;)]]">Set Usercode</ha-call-service-button>
<ha-call-service-button hass="[[hass]]" domain="lock" service="clear_usercode" service-data="[[computeUserCodeServiceData(selectedUserCode, &quot;Delete&quot;)]]">Delete Usercode</ha-call-service-button>
</div>
</template>
</paper-card>
</div>
</template>
</dom-module>
<script>
`;
}
class ZwaveUsercodes extends Polymer.Element {
static get is() { return 'zwave-usercodes'; }
static get properties() {
@ -213,4 +195,3 @@ class ZwaveUsercodes extends Polymer.Element {
}
customElements.define(ZwaveUsercodes.is, ZwaveUsercodes);
</script>

View File

@ -1,13 +1,15 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel='import' href='../../../bower_components/paper-item/paper-item.html'>
<link rel='import' href="../../../bower_components/paper-listbox/paper-listbox.html">
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../src/components/buttons/ha-call-service-button.html">
import '../../../src/components/buttons/ha-call-service-button.js';
<dom-module id='zwave-values'>
<template>
class ZwaveValues extends PolymerElement {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
margin-top: 24px;
@ -32,43 +34,30 @@
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'>
<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>
<template is='dom-if' if='[[!computeIsValueSelected(selectedValue)]]'>
<div class='card-actions'>
<paper-input
float-label="Value Name"
type=text
value={{newValueNameInput}}
placeholder=[[computeGetValueName(selectedValue)]]>
<template is="dom-if" if="[[!computeIsValueSelected(selectedValue)]]">
<div class="card-actions">
<paper-input float-label="Value Name" type="text" value="{{newValueNameInput}}" placeholder="[[computeGetValueName(selectedValue)]]">
</paper-input>
<ha-call-service-button
hass='[[hass]]'
domain='zwave'
service='rename_value'
service-data=[[computeValueNameServiceData(newValueNameInput)]]
>Rename Value</ha-call-service-button>
<ha-call-service-button hass="[[hass]]" domain="zwave" service="rename_value" service-data="[[computeValueNameServiceData(newValueNameInput)]]">Rename Value</ha-call-service-button>
</div>
</template>
</paper-card>
</div>
</template>
</dom-module>
`;
}
<script>
class ZwaveValues extends Polymer.Element {
static get is() { return 'zwave-values'; }
static get properties() {
@ -158,4 +147,3 @@ class ZwaveValues extends Polymer.Element {
}
customElements.define(ZwaveValues.is, ZwaveValues);
</script>

View File

@ -1,9 +1,11 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../../src/util/hass-mixins.js';
<dom-module id="events-list">
<template>
class EventsList extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
ul {
margin: 0;
@ -21,18 +23,16 @@
</style>
<ul>
<template is='dom-repeat' items='[[events]]' as='event'>
<template is="dom-repeat" items="[[events]]" as="event">
<li>
<a href='#' on-click='eventSelected'>{{event.event}}</a>
<a href="#" on-click="eventSelected">{{event.event}}</a>
<span> (</span><span>{{event.listener_count}}</span><span> listeners)</span>
</li>
</template>
</ul>
</template>
</dom-module>
`;
}
<script>
class EventsList extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'events-list'; }
static get properties() {
@ -61,4 +61,3 @@ class EventsList extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(EventsList.is, EventsList);
</script>

View File

@ -1,23 +1,21 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-input/paper-textarea.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
import './events-list.js';
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/resources/ha-style.html">
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel="import" href="./events-list.html">
<dom-module id="ha-panel-dev-event">
<template>
class HaPanelDevEvent extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="ha-style iron-flex iron-positioning"></style>
<style>
:host {
@ -63,16 +61,13 @@
<div>
<div class='header'>Available Events</div>
<events-list on-event-selected='eventSelected' hass='[[hass]]'></event-list>
<events-list on-event-selected='eventSelected' hass='[[hass]]'></events-list>
</div>
</div>
</events-list>
</app-header-layout>
`;
}
</template>
</dom-module>
<script>
class HaPanelDevEvent extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-panel-dev-event'; }
static get properties() {
@ -134,4 +129,3 @@ class HaPanelDevEvent extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaPanelDevEvent.is, HaPanelDevEvent);
</script>

View File

@ -1,22 +1,22 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';
import '@polymer/paper-dialog/paper-dialog.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="../../bower_components/paper-dialog-scrollable/paper-dialog-scrollable.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
import '../../src/components/buttons/ha-call-service-button.js';
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../src/components/buttons/ha-call-service-button.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/resources/ha-style.html">
<dom-module id="ha-panel-dev-info">
<template>
class HaPanelDevInfo extends PolymerElement {
static get template() {
return html`
<style include="iron-positioning ha-style">
:host {
-ms-user-select: initial;
@ -204,7 +204,7 @@
<paper-dialog with-backdrop id="showlog">
<h2>Log Details ([[selectedItem.level]])</h2>
<paper-dialog-scrollable id="scrollable">
<p>[[fullTimeStamp(selectedItem.timestamp)]]</p>
<p>[[fullTimeStamp(selectedItem.timestamp)]]</p>
<template is='dom-if' if='[[selectedItem.message]]'>
<pre>[[selectedItem.message]]</pre>
</template>
@ -213,11 +213,8 @@
</template>
</paper-dialog-scrollable>
</paper-dialog>
</template>
</dom-module>
<script>
class HaPanelDevInfo extends Polymer.Element {
`;
}
static get is() { return 'ha-panel-dev-info'; }
static get properties() {
@ -334,4 +331,3 @@ class HaPanelDevInfo extends Polymer.Element {
}
customElements.define(HaPanelDevInfo.is, HaPanelDevInfo);
</script>

View File

@ -1,20 +1,20 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-input/paper-textarea.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../bower_components/app-layout/app-header-layout/app-header-layout.html'>
<link rel='import' href='../../bower_components/app-layout/app-header/app-header.html'>
<link rel='import' href='../../bower_components/app-layout/app-toolbar/app-toolbar.html'>
<link rel="import" href="../../bower_components/app-storage/app-localstorage/app-localstorage-document.html">
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
import '../../src/util/app-localstorage-document.js';
<link rel='import' href='../../bower_components/paper-card/paper-card.html'>
<link rel='import' href='../../bower_components/paper-input/paper-input.html'>
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
<link rel='import' href='../../bower_components/paper-input/paper-textarea.html'>
<link rel='import' href='../../src/components/ha-menu-button.html'>
<link rel='import' href='../../src/resources/ha-style.html'>
<dom-module id='ha-panel-dev-mqtt'>
<template>
class HaPanelDevMqtt extends PolymerElement {
static get template() {
return html`
<style include='ha-style'>
:host {
-ms-user-select: initial;
@ -75,11 +75,9 @@
</div>
</app-header-layout>
</template>
</dom-module>
`;
}
<script>
class HaPanelDevMqtt extends Polymer.Element {
static get is() { return 'ha-panel-dev-mqtt'; }
static get properties() {
@ -101,4 +99,3 @@ class HaPanelDevMqtt extends Polymer.Element {
}
customElements.define(HaPanelDevMqtt.is, HaPanelDevMqtt);
</script>

View File

@ -1,20 +1,22 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-input/paper-textarea.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
<link rel='import' href='../../bower_components/paper-input/paper-textarea.html'>
import '../../src/components/entity/ha-entity-picker.js';
import '../../src/components/ha-menu-button.js';
import '../../src/components/ha-service-picker.js';
import '../../src/resources/ha-style.js';
import '../../src/util/app-localstorage-document.js';
<link rel='import' href='../../bower_components/app-layout/app-header-layout/app-header-layout.html'>
<link rel='import' href='../../bower_components/app-layout/app-header/app-header.html'>
<link rel='import' href='../../bower_components/app-layout/app-toolbar/app-toolbar.html'>
<link rel="import" href="../../bower_components/app-storage/app-localstorage/app-localstorage-document.html">
<link rel='import' href='../../src/components/ha-menu-button.html'>
<link rel='import' href='../../src/components/entity/ha-entity-picker.html'>
<link rel='import' href='../../src/components/ha-service-picker.html'>
<link rel='import' href='../../src/resources/ha-style.html'>
<dom-module id='ha-panel-dev-service'>
<template>
{
const ERROR_SENTINEL = {};
class HaPanelDevService extends PolymerElement {
static get template() {
return html`
<style include='ha-style'>
:host {
-ms-user-select: initial;
@ -163,13 +165,8 @@
</div>
</app-header-layout>
</template>
</dom-module>
<script>
{
const ERROR_SENTINEL = {};
class HaPanelDevService extends Polymer.Element {
`;
}
static get is() { return 'ha-panel-dev-service'; }
static get properties() {
@ -306,4 +303,3 @@
customElements.define(HaPanelDevService.is, HaPanelDevService);
}
</script>

View File

@ -1,22 +1,21 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-input/paper-textarea.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../../bower_components/paper-checkbox/paper-checkbox.html">
import '../../src/components/entity/ha-entity-picker.js';
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/components/entity/ha-entity-picker.html">
<link rel="import" href="../../src/resources/ha-style.html">
<link rel='import' href='../../src/util/hass-mixins.html'>
<dom-module id="ha-panel-dev-state">
<template>
class HaPanelDevState extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style">
:host {
-ms-user-select: initial;
@ -134,11 +133,8 @@
</table>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
class HaPanelDevState extends window.hassMixins.EventsMixin(Polymer.Element) {
`;
}
static get is() { return 'ha-panel-dev-state'; }
static get properties() {
@ -321,4 +317,3 @@ class HaPanelDevState extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaPanelDevState.is, HaPanelDevState);
</script>

View File

@ -1,18 +1,19 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/utils/debounce.html">
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-input/paper-textarea.js';
import '@polymer/paper-spinner/paper-spinner.js';
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/paper-input/paper-textarea.html">
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/resources/ha-style.html">
<dom-module id="ha-panel-dev-template">
<template>
class HaPanelDevTemplate extends PolymerElement {
static get template() {
return html`
<style is="custom-style" include="ha-style iron-flex iron-positioning"></style>
<style>
:host {
@ -95,11 +96,8 @@
</div>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
class HaPanelDevTemplate extends Polymer.Element {
`;
}
static get is() { return 'ha-panel-dev-template'; }
static get properties() {
@ -176,9 +174,9 @@ For loop example:
if (this.error) {
this.error = false;
}
this._debouncer = Polymer.Debouncer.debounce(
this._debouncer = Debouncer.debounce(
this._debouncer,
Polymer.Async.timeOut.after(500),
timeOut.after(500),
() => { this.renderTemplate(); }
);
}
@ -199,4 +197,3 @@ For loop example:
}
customElements.define(HaPanelDevTemplate.is, HaPanelDevTemplate);
</script>

View File

@ -1,8 +1,12 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel='import' href='../../src/util/hass-mixins.html'>
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="ha-panel-hassio">
<template>
import '../../src/util/hass-mixins.js';
class HaPanelHassio extends
window.hassMixins.NavigateMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style>
iframe {
border: 0;
@ -15,12 +19,8 @@
id='iframe'
src="[[iframeUrl]]"
></iframe>
</template>
</dom-module>
<script>
class HaPanelHassio extends
window.hassMixins.NavigateMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
`;
}
static get is() { return 'ha-panel-hassio'; }
static get properties() {
@ -78,4 +78,3 @@ class HaPanelHassio extends
}
customElements.define(HaPanelHassio.is, HaPanelHassio);
</script>

View File

@ -1,25 +1,29 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="../../bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@vaadin/vaadin-date-picker/vaadin-date-picker.js';
<link rel="import" href="../../bower_components/vaadin-date-picker/vaadin-date-picker.html">
import '../../src/components/ha-menu-button.js';
import '../../src/components/state-history-charts.js';
import '../../src/data/ha-state-history-data.js';
import '../../src/resources/ha-date-picker-style.js';
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
<link rel="import" href="../../src/components/state-history-charts.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/data/ha-state-history-data.html">
<link rel="import" href="../../src/resources/ha-style.html">
<link rel="import" href="../../src/resources/ha-date-picker-style.html">
<link rel='import' href='../../src/util/hass-mixins.html'>
<dom-module id="ha-panel-history">
<template>
<style include="iron-flex ha-style">
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelHistory extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="iron-flex ha-style">
.content {
padding: 0 16px 16px;
}
@ -88,14 +92,8 @@
</state-history-charts>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelHistory extends window.hassMixins.LocalizeMixin(Polymer.Element) {
`;
}
static get is() { return 'ha-panel-history'; }
static get properties() {
@ -157,14 +155,9 @@ class HaPanelHistory extends window.hassMixins.LocalizeMixin(Polymer.Element) {
connectedCallback() {
super.connectedCallback();
// We are unable to parse date because we use intl api to render date
// So we just return last known date.
var lastFormatDate = new Date();
this.$.picker.set('i18n.parseDate', function () {
return lastFormatDate;
});
this.$.picker.set('i18n.parseDate', null);
this.$.picker.set('i18n.formatDate', function (date) {
lastFormatDate = date;
return window.hassUtil.formatDate(date);
return window.hassUtil.formatDate(new Date(date.year, date.month, date.day));
});
}
@ -194,4 +187,3 @@ class HaPanelHistory extends window.hassMixins.LocalizeMixin(Polymer.Element) {
}
customElements.define(HaPanelHistory.is, HaPanelHistory);
</script>

View File

@ -1,12 +1,13 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/resources/ha-style.html">
<dom-module id='ha-panel-iframe'>
<template>
class HaPanelIframe extends PolymerElement {
static get template() {
return html`
<style include='ha-style'>
iframe {
border: 0;
@ -24,11 +25,8 @@
sandbox="allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts"
allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true"
></iframe>
</template>
</dom-module>
<script>
class HaPanelIframe extends Polymer.Element {
`;
}
static get is() { return 'ha-panel-iframe'; }
static get properties() {
@ -49,4 +47,3 @@ class HaPanelIframe extends Polymer.Element {
}
customElements.define(HaPanelIframe.is, HaPanelIframe);
</script>

View File

@ -1,30 +0,0 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel='import' href='../../src/layouts/partial-cards.html'>
<dom-module id="ha-panel-kiosk">
<template>
<partial-cards
id='kiosk-states'
hass='[[hass]]'
show-menu
route='[[route]]'
panel-visible
></partial-cards>
</template>
</dom-module>
<script>
class HaPanelKiosk extends Polymer.Element {
static get is() { return 'ha-panel-kiosk'; }
static get properties() {
return {
hass: Object,
route: Object,
};
}
}
customElements.define(HaPanelKiosk.is, HaPanelKiosk);
</script>

View File

@ -0,0 +1,28 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../src/layouts/partial-cards.js';
class HaPanelKiosk extends PolymerElement {
static get template() {
return html`
<partial-cards
id='kiosk-states'
hass='[[hass]]'
show-menu
route='[[route]]'
panel-visible
></partial-cards>
`;
}
static get is() { return 'ha-panel-kiosk'; }
static get properties() {
return {
hass: Object,
route: Object,
};
}
}
customElements.define(HaPanelKiosk.is, HaPanelKiosk);

View File

@ -1,10 +1,9 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<script>
{
var DATE_CACHE = {};
class HaLogbookData extends Polymer.Element {
class HaLogbookData extends PolymerElement {
static get is() { return 'ha-logbook-data'; }
static get properties() {
@ -77,4 +76,3 @@
customElements.define(HaLogbookData.is, HaLogbookData);
}
</script>

View File

@ -1,12 +1,13 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../src/components/domain-icon.html">
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../../src/components/domain-icon.js';
import '../../src/util/hass-mixins.js';
<dom-module id="ha-logbook">
<template>
class HaLogbook extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
:host {
@ -38,31 +39,29 @@
}
</style>
<template is='dom-if' if='[[!entries.length]]'>
<template is="dom-if" if="[[!entries.length]]">
No logbook entries found.
</template>
<template is='dom-repeat' items="[[entries]]">
<div class='horizontal layout entry'>
<div class='time'>[[formatTime(item.when)]]</div>
<domain-icon domain="[[item.domain]]" class='icon'></domain-icon>
<div class='message' flex>
<template is='dom-if' if="[[!item.entity_id]]">
<span class='name'>[[item.name]]</span>
<template is="dom-repeat" items="[[entries]]">
<div class="horizontal layout entry">
<div class="time">[[formatTime(item.when)]]</div>
<domain-icon domain="[[item.domain]]" class="icon"></domain-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 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>
</template>
</template>
</dom-module>
`;
}
<script>
class HaLogbook extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-logbook'; }
static get properties() {
@ -89,4 +88,3 @@ class HaLogbook extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaLogbook.is, HaLogbook);
</script>

View File

@ -1,25 +1,26 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-spinner/paper-spinner.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@vaadin/vaadin-date-picker/vaadin-date-picker.js';
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-date-picker-style.js';
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
import './ha-logbook-data.js';
import './ha-logbook.js';
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../bower_components/vaadin-date-picker/vaadin-date-picker.html">
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/resources/ha-style.html">
<link rel="import" href="../../src/resources/ha-date-picker-style.html">
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel="import" href="./ha-logbook.html">
<link rel="import" href="./ha-logbook-data.html">
<dom-module id="ha-panel-logbook">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelLogbook extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style">
.content {
padding: 0 16px 16px;
@ -83,14 +84,8 @@
<ha-logbook hass='[[hass]]' entries="[[entries]]" hidden$='[[isLoading]]'></ha-logbook>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelLogbook extends window.hassMixins.LocalizeMixin(Polymer.Element) {
`;
}
static get is() { return 'ha-panel-logbook'; }
static get properties() {
@ -136,14 +131,9 @@ class HaPanelLogbook extends window.hassMixins.LocalizeMixin(Polymer.Element) {
connectedCallback() {
super.connectedCallback();
// We are unable to parse date because we use intl api to render date
// So we just return last known date.
var lastFormatDate = new Date();
this.$.picker.set('i18n.parseDate', function () {
return lastFormatDate;
});
this.$.picker.set('i18n.parseDate', null);
this.$.picker.set('i18n.formatDate', function (date) {
lastFormatDate = date;
return window.hassUtil.formatDate(date);
return window.hassUtil.formatDate(new Date(date.year, date.month, date.day));
});
}
@ -160,4 +150,3 @@ class HaPanelLogbook extends window.hassMixins.LocalizeMixin(Polymer.Element) {
}
customElements.define(HaPanelLogbook.is, HaPanelLogbook);
</script>

View File

@ -1,24 +1,25 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-dialog/paper-dialog.js';
import '@polymer/paper-input/paper-textarea.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
<link rel='import' href='../../bower_components/paper-dialog/paper-dialog.html'>
<link rel='import' href='../../bower_components/paper-input/paper-textarea.html'>
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
<link rel='import' href='../../bower_components/paper-item/paper-item-body.html'>
<link rel='import' href='../../bower_components/paper-card/paper-card.html'>
import '../../src/components/ha-menu-button.js';
import '../../src/resources/ha-style.js';
import '../../src/util/hass-mixins.js';
<link rel='import' href='../../bower_components/app-layout/app-header-layout/app-header-layout.html'>
<link rel='import' href='../../bower_components/app-layout/app-header/app-header.html'>
<link rel='import' href='../../bower_components/app-layout/app-toolbar/app-toolbar.html'>
<link rel="import" href="../../bower_components/app-storage/app-localstorage/app-localstorage-document.html">
<link rel='import' href='../../src/components/ha-menu-button.html'>
<link rel='import' href='../../src/resources/ha-style.html'>
<link rel='import' href='../../src/util/hass-mixins.html'>
<dom-module id='ha-panel-mailbox'>
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelMailbox extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include='ha-style'>
:host {
-ms-user-select: initial;
@ -120,7 +121,7 @@
</div>
</paper-item-body>
</paper-item>
</template>
</template>
</paper-card>
</div>
</app-header-layout>
@ -135,7 +136,7 @@
</h2>
<div id="transcribe"></div>
<div>
<audio id="mp3" preload="none" controls> <source id="mp3src" src="" type="audio/mpeg"></audio>
<audio id="mp3" preload="none" controls> <source id="mp3src" src="" type="audio/mpeg" /></audio>
</div>
</paper-dialog>
@ -146,14 +147,8 @@
<paper-button dialog-confirm autofocus on-click="deleteSelected">[[localize('ui.panel.mailbox.delete_button')]]</paper-button>
</div>
</paper-dialog>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelMailbox extends window.hassMixins.LocalizeMixin(Polymer.Element) {
`;
}
static get is() { return 'ha-panel-mailbox'; }
static get properties() {
@ -272,5 +267,3 @@ class HaPanelMailbox extends window.hassMixins.LocalizeMixin(Polymer.Element) {
}
customElements.define(HaPanelMailbox.is, HaPanelMailbox);
</script>

View File

@ -1,11 +1,13 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/iron-image/iron-image.html'>
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/iron-image/iron-image.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../../src/util/hass-mixins.js';
<dom-module id='ha-entity-marker'>
<template>
class HaEntityMarker extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-positioning"></style>
<style>
.marker {
@ -28,17 +30,15 @@
}
</style>
<div class='marker'>
<template is='dom-if' if='[[entityName]]'>[[entityName]]</template>
<template is='dom-if' if='[[entityPicture]]'>
<iron-image sizing='cover' class='fit' src='[[entityPicture]]'></iron-image>
<div class="marker">
<template is="dom-if" if="[[entityName]]">[[entityName]]</template>
<template is="dom-if" if="[[entityPicture]]">
<iron-image sizing="cover" class="fit" src="[[entityPicture]]"></iron-image>
</template>
</div>
</template>
</dom-module>
`;
}
<script>
class HaEntityMarker extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-entity-marker'; }
static get properties() {
@ -78,4 +78,3 @@ class HaEntityMarker extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaEntityMarker.is, HaEntityMarker);
</script>

View File

@ -1,15 +1,20 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<script src="../../bower_components/leaflet/dist/leaflet.js"></script>
import '../../src/components/ha-menu-button.js';
import '../../src/util/hass-mixins.js';
import './ha-entity-marker.js';
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel="import" href="./ha-entity-marker.html">
window.L.Icon.Default.imagePath = '/static/images/leaflet';
<dom-module id="ha-panel-map">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelMap extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style">
#map {
height: calc(100% - 64px);
@ -24,16 +29,8 @@
</app-toolbar>
<div id='map'></div>
</template>
</dom-module>
<script>
window.L.Icon.Default.imagePath = '/static/images/leaflet';
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelMap extends window.hassMixins.LocalizeMixin(Polymer.Element) {
`;
}
static get is() { return 'ha-panel-map'; }
static get properties() {
@ -197,4 +194,3 @@ class HaPanelMap extends window.hassMixins.LocalizeMixin(Polymer.Element) {
}
customElements.define(HaPanelMap.is, HaPanelMap);
</script>

View File

@ -1,23 +1,28 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/app-layout/app-header-layout/app-header-layout.html">
<link rel="import" href="../../bower_components/app-layout/app-header/app-header.html">
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/paper-item/paper-icon-item.html">
<link rel="import" href="../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../bower_components/paper-checkbox/paper-checkbox.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../bower_components/paper-menu-button/paper-menu-button.html">
<link rel="import" href="../../bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
import '@polymer/app-layout/app-header/app-header.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/paper-card/paper-card.js';
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-icon-item.js';
import '@polymer/paper-item/paper-item-body.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import '@polymer/paper-menu-button/paper-menu-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel="import" href="../../src/components/ha-menu-button.html">
<link rel="import" href="../../src/components/ha-start-voice-button.html">
import '../../src/components/ha-menu-button.js';
import '../../src/components/ha-start-voice-button.js';
import '../../src/util/hass-mixins.js';
<dom-module id="ha-panel-shopping-list">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelShoppingList extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style">
:host {
height: 100%;
@ -128,14 +133,8 @@
</div>
</div>
</app-header-layout>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPanelShoppingList extends window.hassMixins.LocalizeMixin(Polymer.Element) {
`;
}
static get is() { return 'ha-panel-shopping-list'; }
static get properties() {
@ -217,4 +216,3 @@ class HaPanelShoppingList extends window.hassMixins.LocalizeMixin(Polymer.Elemen
}
customElements.define(HaPanelShoppingList.is, HaPanelShoppingList);
</script>

View File

@ -1,23 +1,22 @@
{
"entrypoint": "index.html",
"shell": "src/home-assistant.html",
"shell": "src/home-assistant.js",
"fragments": [
"panels/config/ha-panel-config.html",
"panels/dev-event/ha-panel-dev-event.html",
"panels/dev-info/ha-panel-dev-info.html",
"panels/dev-mqtt/ha-panel-dev-mqtt.html",
"panels/dev-service/ha-panel-dev-service.html",
"panels/dev-state/ha-panel-dev-state.html",
"panels/dev-template/ha-panel-dev-template.html",
"panels/hassio/ha-panel-hassio.html",
"panels/history/ha-panel-history.html",
"panels/iframe/ha-panel-iframe.html",
"panels/kiosk/ha-panel-kiosk.html",
"panels/logbook/ha-panel-logbook.html",
"panels/map/ha-panel-map.html",
"panels/shopping-list/ha-panel-shopping-list.html",
"panels/mailbox/ha-panel-mailbox.html",
"src/resources/ha-chart-scripts.html"
"panels/config/ha-panel-config.js",
"panels/dev-event/ha-panel-dev-event.js",
"panels/dev-info/ha-panel-dev-info.js",
"panels/dev-mqtt/ha-panel-dev-mqtt.js",
"panels/dev-service/ha-panel-dev-service.js",
"panels/dev-state/ha-panel-dev-state.js",
"panels/dev-template/ha-panel-dev-template.js",
"panels/hassio/ha-panel-hassio.js",
"panels/history/ha-panel-history.js",
"panels/iframe/ha-panel-iframe.js",
"panels/kiosk/ha-panel-kiosk.js",
"panels/logbook/ha-panel-logbook.js",
"panels/map/ha-panel-map.js",
"panels/shopping-list/ha-panel-shopping-list.js",
"panels/mailbox/ha-panel-mailbox.js"
],
"sources": [
"src/**/*",
@ -25,7 +24,13 @@
"!src/translations/*"
],
"lint": {
"rules": ["polymer-2"]
"rules": ["polymer-3"],
"filesToIgnore": [
"**/*.html",
"**/ha-paper-slider.js",
"**/hass-mixins.js",
"**/ha-iconset-svg.js"
]
},
"builds": [
{

View File

@ -16,45 +16,33 @@ cp -r public/__init__.py $OUTPUT_DIR_ES5/
# Build frontend
BUILD_DEV=0 ./node_modules/.bin/gulp
NODE_ENV=production webpack -p
BUILD_DEV=0 ./node_modules/.bin/gulp authorize authorize-es5
# Entry points
cp build/*.js build/*.html $OUTPUT_DIR
cp build-es5/*.js build-es5/*.html $OUTPUT_DIR_ES5
# Panels
mkdir $OUTPUT_DIR/panels
cp build/panels/*.html $OUTPUT_DIR/panels
mkdir $OUTPUT_DIR_ES5/panels
cp build-es5/panels/*.html $OUTPUT_DIR_ES5/panels
# Chart code
cp build/src/resources/ha-chart-scripts.html $OUTPUT_DIR
cp build-es5/src/resources/ha-chart-scripts.html $OUTPUT_DIR_ES5
# Copy frontend to output
cp build/core.js $OUTPUT_DIR
cp build/webpack/* $OUTPUT_DIR
cp build-es5/core.js $OUTPUT_DIR_ES5
cp build-es5/webpack/* $OUTPUT_DIR_ES5
cp build-es5/compatibility.js $OUTPUT_DIR_ES5
# Translations
cp -r build-translations/output $OUTPUT_DIR/translations
# Local Roboto
cp -r bower_components/font-roboto-local/fonts $OUTPUT_DIR
cp -r node_modules/@polymer/font-roboto-local/fonts $OUTPUT_DIR
# Polyfill web components
cp bower_components/webcomponentsjs/webcomponents-lite.js $OUTPUT_DIR
cp bower_components/webcomponentsjs/custom-elements-es5-adapter.js $OUTPUT_DIR_ES5
cp node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js $OUTPUT_DIR
cp node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js $OUTPUT_DIR_ES5
# Icons
script/update_mdi.py
# Leaflet
mkdir $OUTPUT_DIR/images/leaflet
cp bower_components/leaflet/dist/leaflet.css $OUTPUT_DIR/images/leaflet
cp -r bower_components/leaflet/dist/images $OUTPUT_DIR/images/leaflet/
# Generate service worker
BUILD_DEV=0 ./node_modules/.bin/gulp gen-service-worker-es5
cp build-es5/service_worker.js $OUTPUT_DIR_ES5
BUILD_DEV=0 ./node_modules/.bin/gulp gen-service-worker
cp build/service_worker.js $OUTPUT_DIR
cp node_modules/leaflet/dist/leaflet.css $OUTPUT_DIR/images/leaflet
cp -r node_modules/leaflet/dist/images $OUTPUT_DIR/images/leaflet/
./node_modules/.bin/gulp compress
@ -65,7 +53,5 @@ echo "VERSION = '`git rev-parse HEAD`'" >> $OUTPUT_DIR_ES5/__init__.py
echo "CREATED_AT = `date +%s`" >> $OUTPUT_DIR_ES5/__init__.py
# Generate the MD5 hash of the new frontend
script/fingerprint_frontend.py --base_dir $OUTPUT_DIR
script/fingerprint_frontend.py --base_dir $OUTPUT_DIR_ES5
./node_modules/.bin/gulp gen-index-html
./node_modules/.bin/gulp gen-index-html-es5

View File

@ -1,45 +0,0 @@
#!/bin/sh
# Set XSS_VERSION or MARKED_VERSION to set package versions. If unset, the latest version will be used.
# Stop on errors
set -e
cd "$(dirname "$0")/.."
output="public/markdown-js.html"
echo "<script>" > $output
pkgs="xss:dist/xss.min.js marked:marked.min.js"
for pkg in $pkgs; do
name="$(cut -d':' -f1 <<< "$pkg")"
js_path="$(cut -d':' -f2 <<< "$pkg")"
# Check env variable for version
version=$(eval "echo \$$(echo $name | tr "a-z" "A-Z")_VERSION")
if [ -z "$version" ]; then
version=$(yarn -s info $name dist-tags.latest)
fi
homepage=$(yarn -s info "$name@$version" homepage)
license=$(yarn -s info "$name@$version" license)
tarball=$(yarn -s info "$name@$version" dist.tarball)
cat >>$output <<EOF
/*
* $name@$version ($license)
* $homepage
*/
EOF
echo "Downloading $name@$version"
curl -s "$tarball" | tar -xzO "package/$js_path" | ./node_modules/.bin/uglifyjs -c -m >> $output
done
echo "</script>" >> $output
size=$(wc -c < $output)
gzip_size=$(cat $output | gzip | wc -c)
echo "$size bytes ($gzip_size bytes gzipped) written to $output"

View File

@ -1,39 +0,0 @@
#!/usr/bin/env python3
"""Generate a file with all md5 hashes of the assets."""
from collections import OrderedDict
import glob
import hashlib
import json
import argparse
from os import path
import re
parser = argparse.ArgumentParser(description='Generate fingerprints of frontend files.')
parser.add_argument('--base_dir', type=str, help='Base dir to look for files.', default='hass_frontend')
args = parser.parse_args()
base_dir = args.base_dir + '/'
fingerprint_file = path.join(base_dir, '__init__.py')
panel_match = re.compile(r'ha-panel-((\w|-)+)\.html')
def fingerprint():
"""Fingerprint the panels."""
files = glob.glob(base_dir + 'panels/*.html')
md5s = OrderedDict()
for fil in sorted(files):
panel = panel_match.search(fil).groups(0)[0]
with open(fil) as fp:
md5 = hashlib.md5(fp.read().encode('utf-8')).hexdigest()
md5s[panel] = md5
template = "FINGERPRINTS = {}\n"
result = template.format(json.dumps(md5s, indent=4))
with open(fingerprint_file, 'at') as fp:
fp.write(result)
if __name__ == '__main__':
fingerprint()

View File

@ -34,7 +34,7 @@ def get_remote_version():
def clean_component(source):
"""Clean component."""
return source[source.index(START_ICONSET):]
return source[source.index(START_ICONSET):].replace('iron-iconset-svg', 'ha-iconset-svg')
def write_component(source):

View File

@ -1,41 +1,36 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href='../../bower_components/paper-button/paper-button.html'>
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@polymer/paper-button/paper-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import '../components/ha-form.js';
import '../util/hass-mixins.js';
<link rel='import' href='../components/ha-form.html'>
<link rel='import' href='../util/hass-mixins.html'>
<dom-module id='ha-auth-flow'>
<template>
<template is='dom-if' if='[[_equals(_state, "loading")]]'>
Please wait
</template>
<template is='dom-if' if='[[_equals(_state, "error")]]'>
Something went wrong
</template>
<template is='dom-if' if='[[_equals(_state, "step")]]'>
<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")]]'>
<ha-form
data='{{_stepData}}'
schema='[[_step.data_schema]]'
error='[[_step.errors]]'
></ha-form>
</template>
<paper-button on-click='_handleSubmit'>[[_computeSubmitCaption(_step.type)]]</paper-button>
</template>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaAuthFlow extends window.hassMixins.EventsMixin(Polymer.Element) {
class HaAuthFlow extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<template is="dom-if" if="[[_equals(_state, &quot;loading&quot;)]]">
Please wait
</template>
<template is="dom-if" if="[[_equals(_state, &quot;error&quot;)]]">
Something went wrong
</template>
<template is="dom-if" if="[[_equals(_state, &quot;step&quot;)]]">
<template is="dom-if" if="[[_equals(_step.type, &quot;abort&quot;)]]">
Aborted
</template>
<template is="dom-if" if="[[_equals(_step.type, &quot;create_entry&quot;)]]">
Success!
</template>
<template is="dom-if" if="[[_equals(_step.type, &quot;form&quot;)]]">
<ha-form data="{{_stepData}}" schema="[[_step.data_schema]]" error="[[_step.errors]]"></ha-form>
</template>
<paper-button on-click="_handleSubmit">[[_computeSubmitCaption(_step.type)]]</paper-button>
</template>
`;
}
static get is() { return 'ha-auth-flow'; }
static get properties() {
return {
@ -140,4 +135,3 @@ class HaAuthFlow extends window.hassMixins.EventsMixin(Polymer.Element) {
}
}
customElements.define(HaAuthFlow.is, HaAuthFlow);
</script>

View File

@ -1,13 +1,15 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/polymer/lib/elements/dom-if.html'>
<link rel='import' href='../../bower_components/polymer/lib/elements/dom-repeat.html'>
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/polymer/lib/elements/dom-if.js';
import '@polymer/polymer/lib/elements/dom-repeat.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='./ha-pick-auth-provider.html'>
<link rel='import' href='./ha-auth-flow.html'>
import './ha-auth-flow.js';
import './ha-pick-auth-provider.js';
<dom-module id='ha-authorize'>
<template>
class HaAuthorize extends PolymerElement {
static get template() {
return html`
<style is="custom-style" include="iron-flex iron-positioning"></style>
<style>
.layout {
@ -15,31 +17,18 @@
}
</style>
<div class="layout vertical center fit">
<img src="/static/icons/favicon-192x192.png" height="192" />
<img src="/static/icons/favicon-192x192.png" height="192">
<template is='dom-if' if='[[_authProvider]]'>
<ha-auth-flow
client-id='[[clientId]]'
client-secret='[[clientSecret]]'
redirect-uri='[[redirectUri]]'
oauth2-state='[[oauth2State]]'
auth-provider='[[_authProvider]]'
on-reset='_handleReset'
/>
</template>
<template is='dom-if' if='[[!_authProvider]]'>
<ha-pick-auth-provider
client-id='[[clientId]]'
client-secret='[[clientSecret]]'
on-pick='_handleAuthProviderPick'
></ha-pick-auth-provider>
<template is="dom-if" if="[[_authProvider]]">
<ha-auth-flow client-id="[[clientId]]" client-secret="[[clientSecret]]" redirect-uri="[[redirectUri]]" oauth2-state="[[oauth2State]]" auth-provider="[[_authProvider]]" on-reset="_handleReset">
</ha-auth-flow></template>
<template is="dom-if" if="[[!_authProvider]]">
<ha-pick-auth-provider client-id="[[clientId]]" client-secret="[[clientSecret]]" on-pick="_handleAuthProviderPick"></ha-pick-auth-provider>
</template>
</div>
</template>
</dom-module>
`;
}
<script>
class HaAuthorize extends Polymer.Element {
static get is() { return 'ha-authorize'; }
static get properties() {
return {
@ -78,4 +67,3 @@ class HaAuthorize extends Polymer.Element {
}
}
customElements.define(HaAuthorize.is, HaAuthorize);
</script>

View File

@ -1,10 +1,15 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../util/hass-mixins.html'>
import '../util/hass-mixins.js';
<dom-module id='ha-pick-auth-provider'>
<template>
/*
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaPickAuthProvider extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
:host {
text-align: center;
@ -14,29 +19,24 @@
cursor: pointer;
}
</style>
<template is='dom-if' if='[[_equal(_state, "loading")]]'>
<template is="dom-if" if="[[_equal(_state, &quot;loading&quot;)]]">
Loading auth providers.
</template>
<template is='dom-if' if='[[_equal(_state, "no-results")]]'>
<template is="dom-if" if="[[_equal(_state, &quot;no-results&quot;)]]">
No auth providers found.
</template>
<template is='dom-if' if='[[_equal(_state, "error-loading")]]'>
<template is="dom-if" if="[[_equal(_state, &quot;error-loading&quot;)]]">
Error loading
</template>
<template is='dom-if' if='[[_equal(_state, "pick")]]'>
<template is="dom-if" if="[[_equal(_state, &quot;pick&quot;)]]">
<p>Log in with</p>
<template is='dom-repeat' items='[[authProviders]]'>
<paper-item on-click='_handlePick'>[[item.name]]</paper-item>
<template is="dom-repeat" items="[[authProviders]]">
<paper-item on-click="_handlePick">[[item.name]]</paper-item>
</template>
</template>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaPickAuthProvider extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-pick-auth-provider'; }
static get properties() {
return {
@ -83,4 +83,3 @@ class HaPickAuthProvider extends window.hassMixins.EventsMixin(Polymer.Element)
}
}
customElements.define(HaPickAuthProvider.is, HaPickAuthProvider);
</script>

View File

@ -8,19 +8,19 @@
<body>
<ha-authorize>Loading</ha-authorize>
<script>
function addScript(src) {
var e = document.createElement('script');
e.src = src;
document.head.appendChild(e);
}
var webComponentsSupported = (
'customElements' in window &&
'import' in document.createElement('link') &&
'content' in document.createElement('template'));
if (!webComponentsSupported) {
addScript('/static/webcomponents-lite.js');
}
function addScript(src) {
var e = document.createElement('script');
e.src = src;
document.head.appendChild(e);
}
var webComponentsSupported = (
'customElements' in window &&
'import' in document.createElement('link') &&
'content' in document.createElement('template'));
if (!webComponentsSupported) {
addScript('/static/webcomponents-lite.js');
}
</script>
<link rel='import' href='./auth/ha-authorize.html'>
<script src="/home-assistant-polymer/build/webpack/ha-authorize.js"></script>
</body>
</html>

View File

@ -1,30 +0,0 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../components/entity/ha-state-label-badge.html'>
<dom-module id='ha-badges-card'>
<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>
</template>
</dom-module>
<script>
class HaBadgesCard extends Polymer.Element {
static get is() { return 'ha-badges-card'; }
static get properties() {
return {
hass: Object,
states: Array,
};
}
}
customElements.define(HaBadgesCard.is, HaBadgesCard);
</script>

View File

@ -0,0 +1,29 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../components/entity/ha-state-label-badge.js';
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>
`;
}
static get is() { return 'ha-badges-card'; }
static get properties() {
return {
hass: Object,
states: Array,
};
}
}
customElements.define(HaBadgesCard.is, HaBadgesCard);

View File

@ -1,12 +1,22 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../bower_components/paper-material/paper-material.html">
import '@polymer/paper-styles/element-styles/paper-material-styles.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../util/hass-mixins.html'>
import '../util/hass-mixins.js';
<dom-module id='ha-camera-card'>
<template>
<style include="paper-material">
{
const UPDATE_INTERVAL = 10000; // ms
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaCameraCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.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;
@ -39,29 +49,16 @@
}
</style>
<img
src='[[cameraFeedSrc]]'
class='camera-feed'
hidden$='[[!imageLoaded]]'
alt='[[computeStateName(stateObj)]]'>
<div class='caption'>
<img src="[[cameraFeedSrc]]" class="camera-feed" hidden\$="[[!imageLoaded]]" alt="[[computeStateName(stateObj)]]">
<div class="caption">
[[computeStateName(stateObj)]]
<template is='dom-if' if='[[!imageLoaded]]'>
<template is="dom-if" if="[[!imageLoaded]]">
([[localize('ui.card.camera.not_available')]])
</template>
</div>
</template>
</dom-module>
`;
}
<script>
{
const UPDATE_INTERVAL = 10000; // ms
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaCameraCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-camera-card'; }
static get properties() {
return {
@ -75,14 +72,6 @@
type: Boolean,
value: true,
},
/**
* The z-depth of the card, from 0-5.
*/
elevation: {
type: Number,
value: 1,
reflectToAttribute: true,
},
};
}
@ -127,4 +116,3 @@
}
customElements.define(HaCameraCard.is, HaCameraCard);
}
</script>

View File

@ -1,15 +1,14 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='./ha-camera-card.html'>
<link rel='import' href='./ha-entities-card.html'>
<link rel='import' href='./ha-history_graph-card.html'>
<link rel='import' href='./ha-media_player-card.html'>
<link rel='import' href='./ha-weather-card.html'>
<link rel='import' href='./ha-persistent_notification-card.html'>
<link rel='import' href='./ha-plant-card.html'>
import './ha-camera-card.js';
import './ha-entities-card.js';
import './ha-history_graph-card.js';
import './ha-media_player-card.js';
import './ha-persistent_notification-card.js';
import './ha-plant-card.js';
import './ha-weather-card.js';
<script>
class HaCardChooser extends Polymer.Element {
class HaCardChooser extends PolymerElement {
static get is() { return 'ha-card-chooser'; }
static get properties() {
return {
@ -78,4 +77,3 @@ class HaCardChooser extends Polymer.Element {
}
}
customElements.define(HaCardChooser.is, HaCardChooser);
</script>

View File

@ -1,14 +1,16 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '../components/entity/ha-entity-toggle.js';
import '../components/ha-card.js';
import '../state-summary/state-card-content.js';
import '../util/hass-mixins.js';
<link rel='import' href='../components/ha-card.html'>
<link rel='import' href='../components/entity/ha-entity-toggle.html'>
<link rel='import' href='../state-summary/state-card-content.html'>
<link rel='import' href='../util/hass-mixins.html'>
<dom-module id='ha-entities-card'>
<template>
class HaEntitiesCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
ha-card {
@ -37,33 +39,25 @@
</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 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>
<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>
</template>
</dom-module>
`;
}
<script>
class HaEntitiesCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-entities-card'; }
static get properties() {
return {
@ -155,4 +149,3 @@ class HaEntitiesCard extends
}
}
customElements.define(HaEntitiesCard.is, HaEntitiesCard);
</script>

View File

@ -1,12 +1,14 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../bower_components/paper-card/paper-card.html">
import '@polymer/paper-card/paper-card.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../components/state-history-charts.html">
<link rel="import" href="../data/ha-state-history-data.html">
<link rel='import' href='../util/hass-mixins.html'>
import '../components/state-history-charts.js';
import '../data/ha-state-history-data.js';
import '../util/hass-mixins.js';
<dom-module id='ha-history_graph-card'>
<template>
class HaHistoryGraphCard extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
paper-card:not([dialog]) .content {
padding: 0 16px 16px;
@ -31,32 +33,17 @@
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
history-data="[[stateHistory]]"
is-loading-data="[[stateHistoryLoading]]"
up-to-now
no-single>
<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 history-data="[[stateHistory]]" is-loading-data="[[stateHistoryLoading]]" up-to-now="" no-single="">
</state-history-charts>
</div>
</paper-card>
</template>
</dom-module>
`;
}
<script>
class HaHistoryGraphCard extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-history_graph-card'; }
static get properties() {
return {
@ -120,4 +107,3 @@ class HaHistoryGraphCard extends window.hassMixins.EventsMixin(Polymer.Element)
}
}
customElements.define(HaHistoryGraphCard.is, HaHistoryGraphCard);
</script>

View File

@ -1,18 +1,24 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-progress/paper-progress.js';
import '@polymer/paper-styles/element-styles/paper-material-styles.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '../util/hass-media-player-model.js';
import '../util/hass-mixins.js';
<link rel="import" href="../../bower_components/paper-material/paper-material.html">
<link rel='import' href='../../bower_components/paper-icon-button/paper-icon-button.html'>
<link rel='import' href='../../bower_components/paper-progress/paper-progress.html'>
<link rel='import' href='../util/hass-media-player-model.html'>
<link rel='import' href='../util/hass-mixins.html'>
<dom-module id='ha-media_player-card'>
<template>
<style include="paper-material iron-flex iron-flex-alignment iron-positioning">
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaMediaPlayerCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.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;
@ -148,70 +154,33 @@
}
</style>
<div class$='[[computeBannerClasses(playerObj)]]'>
<div class='cover' id='cover'></div>
<div class\$="[[computeBannerClasses(playerObj)]]">
<div class="cover" id="cover"></div>
<div class='caption'>
<div class="caption">
[[computeStateName(stateObj)]]
<div class='title'>[[computePrimaryText(localize, playerObj)]]</div>
[[playerObj.secondaryTitle]]<br />
<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>
<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='mdi:power'
on-click='handleTogglePower'
invisible$='[[computeHidePowerButton(playerObj)]]'
class='self-center secondary'
></paper-icon-button>
<div class="controls layout horizontal justified">
<paper-icon-button icon="mdi:power" on-click="handleTogglePower" invisible\$="[[computeHidePowerButton(playerObj)]]" class="self-center secondary"></paper-icon-button>
<div>
<paper-icon-button
icon='mdi: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='mdi:skip-next'
invisible$='[[!playerObj.supportsNextTrack]]'
disabled='[[playerObj.isOff]]'
on-click='handleNext'
></paper-icon-button>
<paper-icon-button icon="mdi: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="mdi:skip-next" invisible\$="[[!playerObj.supportsNextTrack]]" disabled="[[playerObj.isOff]]" on-click="handleNext"></paper-icon-button>
</div>
<paper-icon-button
icon='mdi:dots-vertical'
on-click='handleOpenMoreInfo'
class='self-center secondary'
></paper-icon-button>
<paper-icon-button icon="mdi:dots-vertical" on-click="handleOpenMoreInfo" class="self-center secondary"></paper-icon-button>
</div>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaMediaPlayerCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-media_player-card'; }
static get properties() {
return {
@ -227,14 +196,6 @@ class HaMediaPlayerCard extends
computed: 'computePlaybackControlIcon(playerObj)',
},
playbackPosition: Number,
/**
* The z-depth of the card, from 0-5.
*/
elevation: {
type: Number,
value: 1,
reflectToAttribute: true,
},
};
}
@ -347,4 +308,3 @@ class HaMediaPlayerCard extends
}
}
customElements.define(HaMediaPlayerCard.is, HaMediaPlayerCard);
</script>

View File

@ -1,13 +1,17 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/paper-button/paper-button.html'>
import '@polymer/paper-button/paper-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../components/ha-card.html'>
<link rel='import' href='../components/ha-markdown.html'>
import '../components/ha-card.js';
import '../components/ha-markdown.js';
import '../util/hass-mixins.js';
<link rel='import' href='../util/hass-mixins.html'>
<dom-module id='ha-persistent_notification-card'>
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPersistentNotificationCard extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style>
:host {
@apply --paper-font-body1;
@ -37,18 +41,13 @@
}
</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 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>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaPersistentNotificationCard extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-persistent_notification-card'; }
static get properties() {
return {
@ -68,4 +67,3 @@ class HaPersistentNotificationCard extends window.hassMixins.LocalizeMixin(Polym
}
}
customElements.define(HaPersistentNotificationCard.is, HaPersistentNotificationCard);
</script>

View File

@ -1,10 +1,13 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
<link rel='import' href='../components/ha-card.html'>
<link rel='import' href='../util/hass-mixins.html'>
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="ha-plant-card">
<template>
import '../components/ha-card.js';
import '../util/hass-mixins.js';
class HaPlantCard extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
.content {
display: flex;
@ -30,12 +33,12 @@
}
</style>
<ha-card header='[[computeTitle(stateObj)]]'>
<div class='content'>
<ha-card header="[[computeTitle(stateObj)]]">
<div class="content">
<template is="dom-repeat" items="[[computeAttributes(stateObj.attributes)]]">
<div class="attributes" on-click="attributeClicked">
<div><iron-icon icon="[[computeIcon(item, stateObj.attributes.battery)]]"></iron-icon></div>
<div class$="[[computeClass(stateObj.attributes.problem, item)]]">
<div class\$="[[computeClass(stateObj.attributes.problem, item)]]">
[[computeValue(stateObj.attributes, item)]]
</div>
<div class="uom">[[computeUom(stateObj.attributes.unit_of_measurement_dict, item)]]</div>
@ -43,11 +46,9 @@
</template>
</div>
</ha-card>
</template>
</dom-module>
`;
}
<script>
class HaPlantCard extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-plant-card'; }
static get properties() {
return {
@ -105,4 +106,3 @@ class HaPlantCard extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaPlantCard.is, HaPlantCard);
</script>

View File

@ -1,11 +1,17 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
<link rel='import' href='../components/ha-card.html'>
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../util/hass-mixins.html'>
import '../components/ha-card.js';
import '../util/hass-mixins.js';
<dom-module id='ha-weather-card'>
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaWeatherCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style>
:host {
cursor: pointer;
@ -80,8 +86,8 @@
color: var(--secondary-text-color);
}
</style>
<ha-card header='[[stateObj.attributes.friendly_name]]'>
<div class='content'>
<ha-card header="[[stateObj.attributes.friendly_name]]">
<div class="content">
<div class="now">
<div class="main">
<template is="dom-if" if="[[showWeatherIcon(stateObj.state)]]">
@ -117,7 +123,7 @@
</div>
<template is="dom-if" if="[[forecast]]">
<div class="forecast">
<template is='dom-repeat' items='[[forecast]]'>
<template is="dom-repeat" items="[[forecast]]">
<div>
<div class="weekday">[[computeDateTime(item.datetime)]]</div>
<template is="dom-if" if="[[item.condition]]">
@ -135,15 +141,9 @@
</template>
</div>
</ha-card>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaWeatherCard extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-weather-card'; }
static get properties() {
return {
@ -238,4 +238,3 @@ class HaWeatherCard extends
}
}
customElements.define(HaWeatherCard.is, HaWeatherCard);
</script>

View File

@ -1,20 +1,16 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="./ha-progress-button.html">
<link rel='import' href='../../util/hass-mixins.html'>
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='ha-call-api-button'>
<template>
<ha-progress-button
id='progress'
progress='[[progress]]'
on-click='buttonTapped'
disabled='[[disabled]]'
><slot></slot></ha-progress-button>
</template>
</dom-module>
import '../../util/hass-mixins.js';
import './ha-progress-button.js';
class HaCallApiButton extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<ha-progress-button id="progress" progress="[[progress]]" on-click="buttonTapped" disabled="[[disabled]]"><slot></slot></ha-progress-button>
`;
}
<script>
class HaCallApiButton extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-call-api-button'; }
static get properties() {
@ -71,4 +67,3 @@ class HaCallApiButton extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaCallApiButton.is, HaCallApiButton);
</script>

View File

@ -1,20 +1,16 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="./ha-progress-button.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../util/hass-mixins.html'>
import '../../util/hass-mixins.js';
import './ha-progress-button.js';
<dom-module id='ha-call-service-button'>
<template>
<ha-progress-button
id='progress'
progress='[[progress]]'
on-click='buttonTapped'
><slot></slot></ha-progress-button>
</template>
</dom-module>
class HaCallServiceButton extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<ha-progress-button id="progress" progress="[[progress]]" on-click="buttonTapped"><slot></slot></ha-progress-button>
`;
}
<script>
class HaCallServiceButton extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-call-service-button'; }
static get properties() {
@ -68,4 +64,3 @@ class HaCallServiceButton extends window.hassMixins.EventsMixin(Polymer.Element)
}
customElements.define(HaCallServiceButton.is, HaCallServiceButton);
</script>

View File

@ -1,9 +1,11 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../../bower_components/paper-spinner/paper-spinner.html">
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-spinner/paper-spinner.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='ha-progress-button'>
<template>
class HaProgressButton extends PolymerElement {
static get template() {
return html`
<style>
.container {
position: relative;
@ -40,25 +42,19 @@
bottom: 0;
}
</style>
<div class='container' id='container'>
<paper-button
id='button'
disabled='[[computeDisabled(disabled, progress)]]'
on-click='buttonTapped'
>
<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>
<template is="dom-if" if="[[progress]]">
<div class="progress">
<paper-spinner active=""></paper-spinner>
</div>
</template>
</div>
</template>
</dom-module>
`;
}
<script>
class HaProgressButton extends Polymer.Element {
static get is() { return 'ha-progress-button'; }
static get properties() {
@ -110,4 +106,3 @@ class HaProgressButton extends Polymer.Element {
}
customElements.define(HaProgressButton.is, HaProgressButton);
</script>

View File

@ -1,15 +1,16 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/iron-icon/iron-icon.html">
import domainIcon from '../../js/common/entity/domain_icon.js';
<dom-module id="domain-icon">
<template>
class DomainIcon extends PolymerElement {
static get template() {
return html`
<iron-icon icon="[[computeIcon(domain, state)]]"></iron-icon>
</template>
</dom-module>
`;
}
<script>
class DomainIcon extends Polymer.Element {
static get is() { return 'domain-icon'; }
static get properties() {
@ -27,9 +28,8 @@ class DomainIcon extends Polymer.Element {
}
computeIcon(domain, state) {
return window.hassUtil.domainIcon(domain, state);
return domainIcon(domain, state);
}
}
customElements.define(DomainIcon.is, DomainIcon);
</script>

View File

@ -1,542 +0,0 @@
<link rel='import' href='../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../bower_components/iron-resizable-behavior/iron-resizable-behavior.html">
<link rel='import' href='../../../bower_components/paper-icon-button/paper-icon-button.html'>
<dom-module id="ha-chart-base">
<template>
<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>
</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>
</template>
</dom-module>
<script>
// eslint-disable-next-line no-unused-vars
/* global Chart moment Color */
{
let SCRIPT_LOADED = false;
class HaChartBase extends Polymer.mixinBehaviors([
Polymer.IronResizableBehavior
], Polymer.Element) {
get chart() {
return this._chart;
}
static get is() { return 'ha-chart-base'; }
static get properties() {
return {
data: Object,
identifier: String,
rendered: {
type: Boolean,
notify: true,
value: false,
readOnly: true,
},
metas: {
type: Array,
value: () => [],
},
tooltip: {
type: Object,
value: () => ({
opacity: '0',
left: '0',
top: '0',
xPadding: '5',
yPadding: '3'
})
},
unit: Object,
};
}
static get observers() {
return ['onPropsChange(data)'];
}
connectedCallback() {
super.connectedCallback();
this._isAttached = true;
this.onPropsChange();
this._resizeListener = () => {
this._debouncer = Polymer.Debouncer.debounce(
this._debouncer,
Polymer.Async.timeOut.after(10),
() => {
if (this._isAttached) {
this.resizeChart();
}
}
);
};
if (typeof ResizeObserver === 'function') {
this.resizeObserver = new ResizeObserver((entries) => {
entries.forEach(() => {
this._resizeListener();
});
});
this.resizeObserver.observe(this.$.chartTarget);
} else {
this.addEventListener('iron-resize', this._resizeListener);
}
if (!SCRIPT_LOADED) {
Polymer.importHref(
window.CHART_SCRIPT,
() => {
SCRIPT_LOADED = true;
this.onPropsChange();
},
);
}
}
disconnectedCallback() {
super.disconnectedCallback();
this._isAttached = false;
if (this.resizeObserver) {
this.resizeObserver.unobserve(this.$.chartTarget);
}
this.removeEventListener('iron-resize', this._resizeListener);
if (this._resizeTimer !== undefined) {
clearInterval(this._resizeTimer);
this._resizeTimer = undefined;
}
}
onPropsChange() {
if (!this._isAttached || !SCRIPT_LOADED || !this.data) {
return;
}
this.drawChart();
}
_customTooltips(tooltip) {
// Hide if no tooltip
if (tooltip.opacity === 0) {
this.set(['tooltip', 'opacity'], 0);
return;
}
// Set caret Position
if (tooltip.yAlign) {
this.set(['tooltip', 'yAlign'], tooltip.yAlign);
} else {
this.set(['tooltip', 'yAlign'], 'no-transform');
}
const title = tooltip.title ? tooltip.title[0] || '' : '';
this.set(['tooltip', 'title'], title);
const bodyLines = tooltip.body.map(n => n.lines);
// Set Text
if (tooltip.body) {
this.set(['tooltip', 'lines'], bodyLines.map((body, i) => {
const colors = tooltip.labelColors[i];
return {
color: colors.borderColor,
bgColor: colors.backgroundColor,
text: body.join('\n'),
};
}));
}
const parentWidth = this.$.chartTarget.clientWidth;
let positionX = tooltip.caretX;
const positionY = this._chart.canvas.offsetTop + tooltip.caretY;
if (tooltip.caretX + 100 > parentWidth) {
positionX = parentWidth - 100;
} else if (tooltip.caretX < 100) {
positionX = 100;
}
positionX += this._chart.canvas.offsetLeft;
// Display, position, and set styles for font
this.tooltip = Object.assign({}, this.tooltip, {
opacity: 1,
left: `${positionX}px`,
top: `${positionY}px`,
});
}
_legendClick(event) {
event = event || window.event;
event.stopPropagation();
let target = event.target || event.srcElement;
while (target.nodeName !== 'LI') { // user clicked child, find parent LI
target = target.parentElement;
}
const index = event.model.itemsIndex;
const meta = this._chart.getDatasetMeta(index);
meta.hidden = meta.hidden === null ? !this._chart.data.datasets[index].hidden : null;
this.set(['metas', index, 'hidden'], this._chart.isDatasetVisible(index) ? null : 'hidden');
this._chart.update();
}
_drawLegend() {
const chart = this._chart;
// New data for old graph. Keep metadata.
const preserveVisibility =
this._oldIdentifier && this.identifier === this._oldIdentifier;
this._oldIdentifier = this.identifier;
this.set('metas', this._chart.data.datasets.map((x, i) => ({
label: x.label,
color: x.color,
bgColor: x.backgroundColor,
hidden: preserveVisibility && i < this.metas.length ?
this.metas[i].hidden : !chart.isDatasetVisible(i),
})));
let updateNeeded = false;
if (preserveVisibility) {
for (let i = 0; i < this.metas.length; i++) {
const meta = chart.getDatasetMeta(i);
if (!!meta.hidden !== !!this.metas[i].hidden) updateNeeded = true;
meta.hidden = this.metas[i].hidden ? true : null;
}
}
if (updateNeeded) {
chart.update();
}
this.unit = this.data.unit;
}
_formatTickValue(value, index, values) {
if (values.length === 0) {
return value;
}
const date = new Date(values[index].value);
return window.hassUtil.formatTime(date);
}
drawChart() {
const data = this.data.data;
const ctx = this.$.chartCanvas;
if ((!data.datasets || !data.datasets.length) && !this._chart) {
return;
}
if (this.data.type !== 'timeline' && data.datasets.length > 0) {
const cnt = data.datasets.length;
const colors = this.constructor.getColorList(cnt);
for (let loopI = 0; loopI < cnt; loopI++) {
data.datasets[loopI].borderColor = colors[loopI].rgbString();
data.datasets[loopI].backgroundColor = colors[loopI].alpha(0.6).rgbaString();
}
}
if (this._chart) {
this._customTooltips({ opacity: 0 });
this._chart.data = data;
this._chart.update({ duration: 0 });
if (this.isTimeline !== true && this.data.legend === true) {
this._drawLegend();
}
this.resizeChart();
} else {
if (!data.datasets) {
return;
}
this._customTooltips({ opacity: 0 });
const plugins = [
{ afterRender: () => this._setRendered(true) }
];
let options = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 0,
},
hover: {
animationDuration: 0,
},
responsiveAnimationDuration: 0,
tooltips: {
enabled: false,
custom: this._customTooltips.bind(this),
},
legend: {
display: false,
},
line: {
spanGaps: true,
},
elements: {
font: "12px 'Roboto', 'sans-serif'",
},
ticks: {
fontFamily: "'Roboto', 'sans-serif'",
}
};
options = Chart.helpers.merge(options, this.data.options);
options.scales.xAxes[0].ticks.callback = this._formatTickValue;
if (this.data.type === 'timeline') {
this.set('isTimeline', true);
if (this.data.colors !== undefined) {
this._colorFunc = this.constructor.getColorGenerator(
this.data.colors.staticColors,
this.data.colors.staticColorIndex
);
}
if (this._colorFunc !== undefined) {
options.colorFunction = this._colorFunc;
}
if (data.datasets.length === 1) {
if (options.scales.yAxes[0].ticks) {
options.scales.yAxes[0].ticks.display = false;
} else {
options.scales.yAxes[0].ticks = { display: false };
}
}
}
this.$.chartTarget.style.height = '160px';
this.$.chartTarget.height = '160px';
const chartData = {
type: this.data.type,
data: this.data.data,
options: options,
plugins: plugins,
};
// Async resize after dom update
this._chart = new Chart(ctx, chartData);
if (this.isTimeline !== true && this.data.legend === true) {
this._drawLegend();
}
this.resizeChart();
}
}
resizeChart() {
if (!this._chart) return;
// Chart not ready
if (this.$.chartTarget.clientWidth === 0) {
if (this._resizeTimer === undefined) {
this._resizeTimer = setInterval(this.resizeChart.bind(this), 10);
return;
}
}
clearInterval(this._resizeTimer);
this._resizeTimer = undefined;
this._resizeChart();
}
_resizeChart() {
const chartTarget = this.$.chartTarget;
const options = this.data;
const data = options.data;
if (data.datasets.length === 0) {
return;
}
if (!this.isTimeline) {
this._chart.resize();
return;
}
// Recalculate chart height for Timeline chart
var axis = this._chart.boxes.filter(x => x.position === 'bottom')[0];
if (axis && axis.height > 0) {
this._axisHeight = axis.height;
}
if (!this._axisHeight) {
chartTarget.style.height = '100px';
chartTarget.height = '100px';
this._chart.resize();
axis = this._chart.boxes.filter(x => x.position === 'bottom')[0];
if (axis && axis.height > 0) {
this._axisHeight = axis.height;
}
}
if (this._axisHeight) {
const cnt = data.datasets.length;
const targetHeight = ((30 * cnt) + this._axisHeight) + 'px';
if (chartTarget.style.height !== targetHeight) {
chartTarget.style.height = targetHeight;
chartTarget.height = targetHeight;
}
this._chart.resize();
}
}
// Get HSL distributed color list
static getColorList(count) {
let processL = false;
if (count > 10) {
processL = true;
count = Math.ceil(count / 2);
}
const h1 = 360 / count;
const result = [];
for (let loopI = 0; loopI < count; loopI++) {
result[loopI] = Color().hsl(h1 * loopI, 80, 38);
if (processL) {
result[loopI + count] = Color().hsl(h1 * loopI, 80, 62);
}
}
return result;
}
static getColorGenerator(staticColors, startIndex) {
// Known colors for static data,
// should add for very common state string manually.
// Palette modified from http://google.github.io/palette.js/ mpn65, Apache 2.0
const palette = [
'ff0029', '66a61e', '377eb8', '984ea3', '00d2d5', 'ff7f00', 'af8d00',
'7f80cd', 'b3e900', 'c42e60', 'a65628', 'f781bf', '8dd3c7', 'bebada',
'fb8072', '80b1d3', 'fdb462', 'fccde5', 'bc80bd', 'ffed6f', 'c4eaff',
'cf8c00', '1b9e77', 'd95f02', 'e7298a', 'e6ab02', 'a6761d', '0097ff',
'00d067', 'f43600', '4ba93b', '5779bb', '927acc', '97ee3f', 'bf3947',
'9f5b00', 'f48758', '8caed6', 'f2b94f', 'eff26e', 'e43872', 'd9b100',
'9d7a00', '698cff', 'd9d9d9', '00d27e', 'd06800', '009f82', 'c49200',
'cbe8ff', 'fecddf', 'c27eb6', '8cd2ce', 'c4b8d9', 'f883b0', 'a49100',
'f48800', '27d0df', 'a04a9b'];
function getColorIndex(idx) {
// Reuse the color if index too large.
return Color('#' + palette[idx % palette.length]);
}
const colorDict = {};
let colorIndex = 0;
if (startIndex > 0) colorIndex = startIndex;
if (staticColors) {
Object.keys(staticColors).forEach((c) => {
const c1 = staticColors[c];
if (isFinite(c1)) {
colorDict[c.toLowerCase()] = getColorIndex(c1);
} else {
colorDict[c.toLowerCase()] = Color(staticColors[c]);
}
});
}
// Custom color assign
function getColor(__, data) {
let ret;
const name = data[3];
if (name === null) return Color().hsl(0, 40, 38);
if (name === undefined) return Color().hsl(120, 40, 38);
const name1 = name.toLowerCase();
if (ret === undefined) {
ret = colorDict[name1];
}
if (ret === undefined) {
ret = getColorIndex(colorIndex);
colorIndex++;
colorDict[name1] = ret;
}
return ret;
}
return getColor;
}
}
customElements.define(HaChartBase.is, HaChartBase);
}
</script>

View File

@ -0,0 +1,540 @@
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js';
// eslint-disable-next-line no-unused-vars
/* global Chart moment Color */
let scriptsLoaded = null;
class HaChartBase extends mixinBehaviors([
IronResizableBehavior
], PolymerElement) {
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>
</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() {
return this._chart;
}
static get is() { return 'ha-chart-base'; }
static get properties() {
return {
data: Object,
identifier: String,
rendered: {
type: Boolean,
notify: true,
value: false,
readOnly: true,
},
metas: {
type: Array,
value: () => [],
},
tooltip: {
type: Object,
value: () => ({
opacity: '0',
left: '0',
top: '0',
xPadding: '5',
yPadding: '3'
})
},
unit: Object,
};
}
static get observers() {
return ['onPropsChange(data)'];
}
connectedCallback() {
super.connectedCallback();
this._isAttached = true;
this.onPropsChange();
this._resizeListener = () => {
this._debouncer = Debouncer.debounce(
this._debouncer,
timeOut.after(10),
() => {
if (this._isAttached) {
this.resizeChart();
}
}
);
};
if (typeof ResizeObserver === 'function') {
this.resizeObserver = new ResizeObserver((entries) => {
entries.forEach(() => {
this._resizeListener();
});
});
this.resizeObserver.observe(this.$.chartTarget);
} else {
this.addEventListener('iron-resize', this._resizeListener);
}
if (scriptsLoaded === null) {
scriptsLoaded = import(/* webpackChunkName: "load_chart" */ '../../resources/ha-chart-scripts.js');
}
scriptsLoaded.then((ChartModule) => {
this.ChartClass = ChartModule.default;
this.onPropsChange();
});
}
disconnectedCallback() {
super.disconnectedCallback();
this._isAttached = false;
if (this.resizeObserver) {
this.resizeObserver.unobserve(this.$.chartTarget);
}
this.removeEventListener('iron-resize', this._resizeListener);
if (this._resizeTimer !== undefined) {
clearInterval(this._resizeTimer);
this._resizeTimer = undefined;
}
}
onPropsChange() {
if (!this._isAttached || !this.ChartClass || !this.data) {
return;
}
this.drawChart();
}
_customTooltips(tooltip) {
// Hide if no tooltip
if (tooltip.opacity === 0) {
this.set(['tooltip', 'opacity'], 0);
return;
}
// Set caret Position
if (tooltip.yAlign) {
this.set(['tooltip', 'yAlign'], tooltip.yAlign);
} else {
this.set(['tooltip', 'yAlign'], 'no-transform');
}
const title = tooltip.title ? tooltip.title[0] || '' : '';
this.set(['tooltip', 'title'], title);
const bodyLines = tooltip.body.map(n => n.lines);
// Set Text
if (tooltip.body) {
this.set(['tooltip', 'lines'], bodyLines.map((body, i) => {
const colors = tooltip.labelColors[i];
return {
color: colors.borderColor,
bgColor: colors.backgroundColor,
text: body.join('\n'),
};
}));
}
const parentWidth = this.$.chartTarget.clientWidth;
let positionX = tooltip.caretX;
const positionY = this._chart.canvas.offsetTop + tooltip.caretY;
if (tooltip.caretX + 100 > parentWidth) {
positionX = parentWidth - 100;
} else if (tooltip.caretX < 100) {
positionX = 100;
}
positionX += this._chart.canvas.offsetLeft;
// Display, position, and set styles for font
this.tooltip = Object.assign({}, this.tooltip, {
opacity: 1,
left: `${positionX}px`,
top: `${positionY}px`,
});
}
_legendClick(event) {
event = event || window.event;
event.stopPropagation();
let target = event.target || event.srcElement;
while (target.nodeName !== 'LI') { // user clicked child, find parent LI
target = target.parentElement;
}
const index = event.model.itemsIndex;
const meta = this._chart.getDatasetMeta(index);
meta.hidden = meta.hidden === null ? !this._chart.data.datasets[index].hidden : null;
this.set(['metas', index, 'hidden'], this._chart.isDatasetVisible(index) ? null : 'hidden');
this._chart.update();
}
_drawLegend() {
const chart = this._chart;
// New data for old graph. Keep metadata.
const preserveVisibility =
this._oldIdentifier && this.identifier === this._oldIdentifier;
this._oldIdentifier = this.identifier;
this.set('metas', this._chart.data.datasets.map((x, i) => ({
label: x.label,
color: x.color,
bgColor: x.backgroundColor,
hidden: preserveVisibility && i < this.metas.length ?
this.metas[i].hidden : !chart.isDatasetVisible(i),
})));
let updateNeeded = false;
if (preserveVisibility) {
for (let i = 0; i < this.metas.length; i++) {
const meta = chart.getDatasetMeta(i);
if (!!meta.hidden !== !!this.metas[i].hidden) updateNeeded = true;
meta.hidden = this.metas[i].hidden ? true : null;
}
}
if (updateNeeded) {
chart.update();
}
this.unit = this.data.unit;
}
_formatTickValue(value, index, values) {
if (values.length === 0) {
return value;
}
const date = new Date(values[index].value);
return window.hassUtil.formatTime(date);
}
drawChart() {
const data = this.data.data;
const ctx = this.$.chartCanvas;
if ((!data.datasets || !data.datasets.length) && !this._chart) {
return;
}
if (this.data.type !== 'timeline' && data.datasets.length > 0) {
const cnt = data.datasets.length;
const colors = this.constructor.getColorList(cnt);
for (let loopI = 0; loopI < cnt; loopI++) {
data.datasets[loopI].borderColor = colors[loopI].rgbString();
data.datasets[loopI].backgroundColor = colors[loopI].alpha(0.6).rgbaString();
}
}
if (this._chart) {
this._customTooltips({ opacity: 0 });
this._chart.data = data;
this._chart.update({ duration: 0 });
if (this.isTimeline !== true && this.data.legend === true) {
this._drawLegend();
}
this.resizeChart();
} else {
if (!data.datasets) {
return;
}
this._customTooltips({ opacity: 0 });
const plugins = [
{ afterRender: () => this._setRendered(true) }
];
let options = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 0,
},
hover: {
animationDuration: 0,
},
responsiveAnimationDuration: 0,
tooltips: {
enabled: false,
custom: this._customTooltips.bind(this),
},
legend: {
display: false,
},
line: {
spanGaps: true,
},
elements: {
font: "12px 'Roboto', 'sans-serif'",
},
ticks: {
fontFamily: "'Roboto', 'sans-serif'",
}
};
options = Chart.helpers.merge(options, this.data.options);
options.scales.xAxes[0].ticks.callback = this._formatTickValue;
if (this.data.type === 'timeline') {
this.set('isTimeline', true);
if (this.data.colors !== undefined) {
this._colorFunc = this.constructor.getColorGenerator(
this.data.colors.staticColors,
this.data.colors.staticColorIndex
);
}
if (this._colorFunc !== undefined) {
options.colorFunction = this._colorFunc;
}
if (data.datasets.length === 1) {
if (options.scales.yAxes[0].ticks) {
options.scales.yAxes[0].ticks.display = false;
} else {
options.scales.yAxes[0].ticks = { display: false };
}
}
}
this.$.chartTarget.style.height = '160px';
this.$.chartTarget.height = '160px';
const chartData = {
type: this.data.type,
data: this.data.data,
options: options,
plugins: plugins,
};
// Async resize after dom update
this._chart = new this.ChartClass(ctx, chartData);
if (this.isTimeline !== true && this.data.legend === true) {
this._drawLegend();
}
this.resizeChart();
}
}
resizeChart() {
if (!this._chart) return;
// Chart not ready
if (this.$.chartTarget.clientWidth === 0) {
if (this._resizeTimer === undefined) {
this._resizeTimer = setInterval(this.resizeChart.bind(this), 10);
return;
}
}
clearInterval(this._resizeTimer);
this._resizeTimer = undefined;
this._resizeChart();
}
_resizeChart() {
const chartTarget = this.$.chartTarget;
const options = this.data;
const data = options.data;
if (data.datasets.length === 0) {
return;
}
if (!this.isTimeline) {
this._chart.resize();
return;
}
// Recalculate chart height for Timeline chart
var axis = this._chart.boxes.filter(x => x.position === 'bottom')[0];
if (axis && axis.height > 0) {
this._axisHeight = axis.height;
}
if (!this._axisHeight) {
chartTarget.style.height = '100px';
chartTarget.height = '100px';
this._chart.resize();
axis = this._chart.boxes.filter(x => x.position === 'bottom')[0];
if (axis && axis.height > 0) {
this._axisHeight = axis.height;
}
}
if (this._axisHeight) {
const cnt = data.datasets.length;
const targetHeight = ((30 * cnt) + this._axisHeight) + 'px';
if (chartTarget.style.height !== targetHeight) {
chartTarget.style.height = targetHeight;
chartTarget.height = targetHeight;
}
this._chart.resize();
}
}
// Get HSL distributed color list
static getColorList(count) {
let processL = false;
if (count > 10) {
processL = true;
count = Math.ceil(count / 2);
}
const h1 = 360 / count;
const result = [];
for (let loopI = 0; loopI < count; loopI++) {
result[loopI] = Color().hsl(h1 * loopI, 80, 38);
if (processL) {
result[loopI + count] = Color().hsl(h1 * loopI, 80, 62);
}
}
return result;
}
static getColorGenerator(staticColors, startIndex) {
// Known colors for static data,
// should add for very common state string manually.
// Palette modified from http://google.github.io/palette.js/ mpn65, Apache 2.0
const palette = [
'ff0029', '66a61e', '377eb8', '984ea3', '00d2d5', 'ff7f00', 'af8d00',
'7f80cd', 'b3e900', 'c42e60', 'a65628', 'f781bf', '8dd3c7', 'bebada',
'fb8072', '80b1d3', 'fdb462', 'fccde5', 'bc80bd', 'ffed6f', 'c4eaff',
'cf8c00', '1b9e77', 'd95f02', 'e7298a', 'e6ab02', 'a6761d', '0097ff',
'00d067', 'f43600', '4ba93b', '5779bb', '927acc', '97ee3f', 'bf3947',
'9f5b00', 'f48758', '8caed6', 'f2b94f', 'eff26e', 'e43872', 'd9b100',
'9d7a00', '698cff', 'd9d9d9', '00d27e', 'd06800', '009f82', 'c49200',
'cbe8ff', 'fecddf', 'c27eb6', '8cd2ce', 'c4b8d9', 'f883b0', 'a49100',
'f48800', '27d0df', 'a04a9b'];
function getColorIndex(idx) {
// Reuse the color if index too large.
return Color('#' + palette[idx % palette.length]);
}
const colorDict = {};
let colorIndex = 0;
if (startIndex > 0) colorIndex = startIndex;
if (staticColors) {
Object.keys(staticColors).forEach((c) => {
const c1 = staticColors[c];
if (isFinite(c1)) {
colorDict[c.toLowerCase()] = getColorIndex(c1);
} else {
colorDict[c.toLowerCase()] = Color(staticColors[c]);
}
});
}
// Custom color assign
function getColor(__, data) {
let ret;
const name = data[3];
if (name === null) return Color().hsl(0, 40, 38);
if (name === undefined) return Color().hsl(120, 40, 38);
const name1 = name.toLowerCase();
if (ret === undefined) {
ret = colorDict[name1];
}
if (ret === undefined) {
ret = getColorIndex(colorIndex);
colorIndex++;
colorDict[name1] = ret;
}
return ret;
}
return getColor;
}
}
customElements.define(HaChartBase.is, HaChartBase);

View File

@ -1,16 +1,20 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/vaadin-combo-box/vaadin-combo-box-light.html">
<link rel="import" href="../../../bower_components/paper-item/paper-icon-item.html">
<link rel="import" href="../../../bower_components/paper-item/paper-item-body.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../bower_components/paper-input/paper-input.html">
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-icon-item.js';
import '@polymer/paper-item/paper-item-body.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@vaadin/vaadin-combo-box/vaadin-combo-box-light.js';
<link rel='import' href='../../../src/util/hass-mixins.html'>
import '../../util/hass-mixins.js';
import './state-badge.js';
<link rel="import" href="./state-badge.html">
<dom-module id="ha-entity-picker">
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaEntityPicker extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get template() {
return html`
<style>
paper-input > paper-icon-button {
width: 24px;
@ -22,34 +26,10 @@
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]]'
>
<paper-input
autofocus="[[autofocus]]"
label="[[_computeLabel(label, localize)]]"
class="input"
value='[[value]]'
disabled='[[disabled]]'
>
<paper-icon-button
slot="suffix"
class="clear-button"
icon="mdi: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>
<vaadin-combo-box-light items="[[_states]]" item-value-path="entity_id" item-label-path="entity_id" value="{{value}}" opened="{{opened}}" allow-custom-value="[[allowCustomEntity]]">
<paper-input autofocus="[[autofocus]]" label="[[_computeLabel(label, localize)]]" class="input" value="[[value]]" disabled="[[disabled]]">
<paper-icon-button slot="suffix" class="clear-button" icon="mdi: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>
@ -58,22 +38,17 @@
}
</style>
<paper-icon-item>
<state-badge state-obj="[[item]]" slot='item-icon'></state-badge>
<paper-item-body two-line>
<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>
<div secondary="">[[item.entity_id]]</div>
</paper-item-body>
</paper-icon-item>
</template>
</vaadin-combo-box-light>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaEntityPicker extends window.hassMixins.LocalizeMixin(Polymer.Element) {
static get is() { return 'ha-entity-picker'; }
static get properties() {
@ -162,4 +137,3 @@ class HaEntityPicker extends window.hassMixins.LocalizeMixin(Polymer.Element) {
}
customElements.define(HaEntityPicker.is, HaEntityPicker);
</script>

View File

@ -1,9 +1,11 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html">
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="ha-entity-toggle">
<template>
class HaEntityToggle extends PolymerElement {
static get template() {
return html`
<style>
:host {
white-space: nowrap;
@ -24,20 +26,16 @@
}
</style>
<template is='dom-if' if='[[stateObj.attributes.assumed_state]]'>
<paper-icon-button icon="mdi:flash-off" on-click="turnOff" state-active$='[[!isOn]]'></paper-icon-button>
<paper-icon-button icon="mdi:flash" on-click="turnOn" state-active$='[[isOn]]'></paper-icon-button>
<template is="dom-if" if="[[stateObj.attributes.assumed_state]]">
<paper-icon-button icon="mdi:flash-off" on-click="turnOff" state-active\$="[[!isOn]]"></paper-icon-button>
<paper-icon-button icon="mdi: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 is="dom-if" if="[[!stateObj.attributes.assumed_state]]">
<paper-toggle-button checked="[[toggleChecked]]" on-change="toggleChanged"></paper-toggle-button>
</template>
</template>
</dom-module>
`;
}
<script>
class HaEntityToggle extends Polymer.Element {
static get is() { return 'ha-entity-toggle'; }
static get properties() {
@ -150,4 +148,3 @@ class HaEntityToggle extends Polymer.Element {
}
customElements.define(HaEntityToggle.is, HaEntityToggle);
</script>

View File

@ -1,29 +0,0 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/iron-icon/iron-icon.html">
<dom-module id="ha-state-icon">
<template>
<iron-icon icon="[[computeIcon(stateObj)]]"></iron-icon>
</template>
</dom-module>
<script>
class HaStateIcon extends Polymer.Element {
static get is() { return 'ha-state-icon'; }
static get properties() {
return {
stateObj: {
type: Object,
},
};
}
computeIcon(stateObj) {
return window.hassUtil.stateIcon(stateObj);
}
}
customElements.define(HaStateIcon.is, HaStateIcon);
</script>

View File

@ -0,0 +1,29 @@
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import stateIcon from '../../../js/common/entity/state_icon.js';
class HaStateIcon extends PolymerElement {
static get template() {
return html`
<iron-icon icon="[[computeIcon(stateObj)]]"></iron-icon>
`;
}
static get is() { return 'ha-state-icon'; }
static get properties() {
return {
stateObj: {
type: Object,
},
};
}
computeIcon(stateObj) {
return stateIcon(stateObj);
}
}
customElements.define(HaStateIcon.is, HaStateIcon);

View File

@ -1,12 +1,18 @@
<link rel='import' href='../../../bower_components/polymer/polymer-element.html'>
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../src/util/hass-mixins.html'>
<link rel="import" href="../../../src/util/hass-util.html">
import '../../util/hass-mixins.js';
import '../../util/hass-util.js';
import '../ha-label-badge.js';
<link rel='import' href='../ha-label-badge.html'>
<dom-module id='ha-state-label-badge'>
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaStateLabelBadge extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(PolymerElement)) {
static get template() {
return html`
<style>
:host {
cursor: pointer;
@ -45,23 +51,10 @@
}
</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>
</template>
</dom-module>
<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>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaStateLabelBadge extends
window.hassMixins.LocalizeMixin(window.hassMixins.EventsMixin(Polymer.Element)) {
static get is() { return 'ha-state-label-badge'; }
static get properties() {
@ -211,4 +204,3 @@ class HaStateLabelBadge extends
}
customElements.define(HaStateLabelBadge.is, HaStateLabelBadge);
</script>

View File

@ -1,9 +1,12 @@
<link rel='import' href='../../../bower_components/polymer/polymer-element.html'>
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='./ha-state-icon.html'>
import './ha-state-icon.js';
import computeStateDomain from '../../../js/common/entity/compute_state_domain.js';
<dom-module id='state-badge'>
<template>
class StateBadge extends PolymerElement {
static get template() {
return html`
<style>
:host {
position: relative;
@ -36,17 +39,10 @@
}
</style>
<ha-state-icon
id='icon'
state-obj='[[stateObj]]'
data-domain$='[[computeDomain(stateObj)]]'
data-state$='[[stateObj.state]]'
></ha-state-icon>
</template>
</dom-module>
<ha-state-icon id="icon" state-obj="[[stateObj]]" data-domain\$="[[computeDomain(stateObj)]]" data-state\$="[[stateObj.state]]"></ha-state-icon>
`;
}
<script>
class StateBadge extends Polymer.Element {
static get is() { return 'state-badge'; }
static get properties() {
return {
@ -58,7 +54,7 @@ class StateBadge extends Polymer.Element {
}
computeDomain(stateObj) {
return window.hassUtil.computeDomain(stateObj);
return computeStateDomain(stateObj);
}
@ -92,4 +88,3 @@ class StateBadge extends Polymer.Element {
}
}
customElements.define(StateBadge.is, StateBadge);
</script>

View File

@ -1,11 +1,13 @@
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="./state-badge.html">
<link rel="import" href="../ha-relative-time.html">
<link rel="import" href="../../util/hass-util.html">
import '../ha-relative-time.js';
import './state-badge.js';
import computeStateName from '../../../js/common/entity/compute_state_name.js';
<dom-module id="state-info">
<template>
class StateInfo extends PolymerElement {
static get template() {
return html`
<style>
:host {
@apply --paper-font-body1;
@ -37,27 +39,25 @@
}
</style>
<state-badge state-obj='[[stateObj]]'></state-badge>
<state-badge state-obj="[[stateObj]]"></state-badge>
<div class='info'>
<div class='name' in-dialog$='[[inDialog]]'>[[computeStateName(stateObj)]]</div>
<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 datetime='[[stateObj.last_changed]]'></ha-relative-time>
<template is="dom-if" if="[[inDialog]]">
<div class="time-ago">
<ha-relative-time datetime="[[stateObj.last_changed]]"></ha-relative-time>
</div>
</template>
<template is='dom-if' if='[[!inDialog]]'>
<div class='extra-info'>
<template is="dom-if" if="[[!inDialog]]">
<div class="extra-info">
<slot>
</div>
</slot></div>
</template>
</div>
</template>
</dom-module>
`;
}
<script>
class StateInfo extends Polymer.Element {
static get is() { return 'state-info'; }
static get properties() {
@ -78,9 +78,8 @@ class StateInfo extends Polymer.Element {
}
computeStateName(stateObj) {
return window.hassUtil.computeStateName(stateObj);
return computeStateName(stateObj);
}
}
customElements.define(StateInfo.is, StateInfo);
</script>

View File

@ -1,11 +1,12 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '../util/hass-attributes-util.js';
<link rel="import" href="../util/hass-attributes-util.html">
<dom-module id="ha-attributes">
<template>
class HaAttributes extends PolymerElement {
static get template() {
return html`
<style is="custom-style" include="iron-flex iron-flex-alignment"></style>
<style>
.data-entry .value {
@ -17,20 +18,18 @@
}
</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>
<div class="attribution" hidden\$="[[!computeAttribution(stateObj)]]">[[computeAttribution(stateObj)]]</div>
</div>
</template>
</dom-module>
`;
}
<script>
class HaAttributes extends Polymer.Element {
static get is() { return 'ha-attributes'; }
static get properties() {
@ -81,4 +80,3 @@ class HaAttributes extends Polymer.Element {
}
customElements.define(HaAttributes.is, HaAttributes);
</script>

View File

@ -1,14 +1,16 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../bower_components/paper-material/paper-material.html">
import '@polymer/paper-styles/element-styles/paper-material-styles.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='ha-card'>
<template>
<style include="paper-material">
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 {
@ -20,15 +22,13 @@
}
</style>
<template is='dom-if' if='[[header]]'>
<div class='header'>[[header]]</div>
<template is="dom-if" if="[[header]]">
<div class="header">[[header]]</div>
</template>
<slot></slot>
</template>
</dom-module>
`;
}
<script>
class HaCard extends Polymer.Element {
static get is() { return 'ha-card'; }
static get properties() {
@ -36,17 +36,8 @@ class HaCard extends Polymer.Element {
header: {
type: String,
},
/**
* The z-depth of the card, from 0-5.
*/
elevation: {
type: Number,
value: 1,
reflectToAttribute: true,
},
};
}
}
customElements.define(HaCard.is, HaCard);
</script>

View File

@ -1,84 +1,14 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/utils/debounce.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '../cards/ha-badges-card.js';
import '../cards/ha-card-chooser.js';
import '../util/hass-util.js';
import './ha-demo-badge.js';
<link rel="import" href="./ha-demo-badge.html">
<link rel="import" href="../cards/ha-badges-card.html">
<link rel="import" href="../cards/ha-card-chooser.html">
<link rel="import" href="../util/hass-util.html">
<dom-module id="ha-cards">
<template>
<style is="custom-style" include="iron-flex iron-flex-factors"></style>
<style>
:host {
display: block;
padding-top: 8px;
padding-right: 8px;
transform: translateZ(0);
position: relative;
}
.badges {
font-size: 85%;
text-align: center;
}
.column {
max-width: 500px;
overflow-x: hidden;
}
ha-card-chooser {
display: block;
margin-left: 8px;
margin-bottom: 8px;
}
@media (max-width: 500px) {
:host {
padding-right: 0;
}
ha-card-chooser {
margin-left: 0;
}
}
@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>
</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>
</template>
</div>
</template>
</div>
</template>
</dom-module>
<script>
{
// mapping domain to size of the card.
const DOMAINS_WITH_CARD = {
@ -145,7 +75,76 @@
const computeDomain = window.hassUtil.computeDomain;
class HaCards extends Polymer.Element {
class HaCards extends PolymerElement {
static get template() {
return html`
<style is="custom-style" include="iron-flex iron-flex-factors"></style>
<style>
:host {
display: block;
padding-top: 8px;
padding-right: 8px;
transform: translateZ(0);
position: relative;
}
.badges {
font-size: 85%;
text-align: center;
}
.column {
max-width: 500px;
overflow-x: hidden;
}
ha-card-chooser {
display: block;
margin-left: 8px;
margin-bottom: 8px;
}
@media (max-width: 500px) {
:host {
padding-right: 0;
}
ha-card-chooser {
margin-left: 0;
}
}
@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>
</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>
</template>
</div>
</template>
</div>
</div>
`;
}
static get is() { return 'ha-cards'; }
static get properties() {
return {
@ -192,9 +191,9 @@
} else if (!this.$.main.parentNode && this.$.main._parentNode) {
this.$.main._parentNode.appendChild(this.$.main);
}
this._debouncer = Polymer.Debouncer.debounce(
this._debouncer = Debouncer.debounce(
this._debouncer,
Polymer.Async.timeOut.after(10),
timeOut.after(10),
() => {
// Things might have changed since it got scheduled.
if (this.panelVisible && this.viewVisible) {
@ -367,4 +366,3 @@
}
customElements.define(HaCards.is, HaCards);
}
</script>

View File

@ -1,11 +1,13 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../util/hass-mixins.html'>
import '../util/hass-mixins.js';
<dom-module id="ha-climate-control">
<template>
class HaClimateControl extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-flex iron-flex-alignment"></style>
<style>
/* local DOM styles go here */
@ -43,10 +45,9 @@
<paper-icon-button icon="mdi:chevron-down" on-click="decrementValue"></paper-icon-button>
</div>
</div>
</template>
</dom-module>
<script>
class HaClimateControl extends window.hassMixins.EventsMixin(Polymer.Element) {
`;
}
static get is() { return 'ha-climate-control'; }
static get properties() {
@ -123,4 +124,3 @@ class HaClimateControl extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaClimateControl.is, HaClimateControl);
</script>

View File

@ -1,7 +1,9 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id="ha-climate-state">
<template>
class HaClimateState extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: flex;
@ -24,23 +26,21 @@
}
</style>
<div class='target'>
<div class="target">
<span class="state-label">
[[stateObj.state]]
</span>
[[computeTarget(stateObj)]]
</div>
<template is='dom-if' if='[[currentStatus]]'>
<div class='current'>
<template is="dom-if" if="[[currentStatus]]">
<div class="current">
Currently: [[currentStatus]]
</div>
</template>
</template>
</dom-module>
`;
}
<script>
class HaClimateState extends Polymer.Element {
static get is() { return 'ha-climate-state'; }
static get properties() {
@ -81,4 +81,3 @@ class HaClimateState extends Polymer.Element {
}
}
customElements.define(HaClimateState.is, HaClimateState);
</script>

View File

@ -1,9 +1,14 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../util/hass-mixins.js';
<dom-module id='ha-color-picker'>
<template>
/**
* Color-picker custom element
*/
class HaColorPicker extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
:host {
user-select: none;
@ -55,29 +60,24 @@
}
</style>
<div id='canvas'>
<svg id='interactionLayer'>
<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" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="2" />
<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 type="linear" slope="0.3"></feFuncA>
</feComponentTransfer>
<feBlend in="SourceGraphic" in2="alphaOut" mode="normal" />
<feBlend in="SourceGraphic" in2="alphaOut" mode="normal"></feBlend>
</filter>
</defs>
</svg>
<canvas id='backgroundLayer'></canvas>
<canvas id="backgroundLayer"></canvas>
</div>
</template>
</dom-module>
`;
}
<script>
/**
* Color-picker custom element
*/
class HaColorPicker extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-color-picker'; }
static get properties() {
@ -526,4 +526,3 @@ class HaColorPicker extends window.hassMixins.EventsMixin(Polymer.Element) {
}
}
customElements.define(HaColorPicker.is, HaColorPicker);
</script>

View File

@ -1,11 +1,13 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/vaadin-combo-box/vaadin-combo-box-light.html">
<link rel="import" href="../../bower_components/paper-item/paper-item.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-item.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@vaadin/vaadin-combo-box/vaadin-combo-box-light.js';
<dom-module id="ha-combo-box">
<template>
class HaComboBox extends PolymerElement {
static get template() {
return html`
<style>
paper-input > paper-icon-button {
width: 24px;
@ -17,32 +19,10 @@
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]]'
>
<paper-input
autofocus="[[autofocus]]"
label="[[label]]"
class="input"
value='[[value]]'
>
<paper-icon-button
slot="suffix"
class="clear-button"
icon="mdi: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>
<vaadin-combo-box-light items="[[_items]]" item-value-path="[[itemValuePath]]" item-label-path="[[itemLabelPath]]" value="{{value}}" opened="{{opened}}" allow-custom-value="[[allowCustomValue]]">
<paper-input autofocus="[[autofocus]]" label="[[label]]" class="input" value="[[value]]">
<paper-icon-button slot="suffix" class="clear-button" icon="mdi: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>
@ -53,11 +33,9 @@
<paper-item>[[_computeItemLabel(item, itemLabelPath)]]</paper-item>
</template>
</vaadin-combo-box-light>
</template>
</dom-module>
`;
}
<script>
class HaComboBox extends Polymer.Element {
static get is() { return 'ha-combo-box'; }
static get properties() {
@ -106,4 +84,3 @@ class HaComboBox extends Polymer.Element {
}
customElements.define(HaComboBox.is, HaComboBox);
</script>

View File

@ -1,10 +1,12 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../util/cover-model.html">
import '../util/cover-model.js';
<dom-module id="ha-cover-controls">
<template>
class HaCoverControls extends PolymerElement {
static get template() {
return html`
<style>
.state {
white-space: nowrap;
@ -14,21 +16,14 @@
}
</style>
<div class='state'>
<paper-icon-button icon="mdi:arrow-up" on-click='onOpenTap'
invisible$='[[!entityObj.supportsOpen]]'
disabled='[[computeOpenDisabled(stateObj, entityObj)]]'></paper-icon-button>
<paper-icon-button icon="mdi:stop" on-click='onStopTap'
invisible$='[[!entityObj.supportsStop]]'></paper-icon-button>
<paper-icon-button icon="mdi:arrow-down" on-click='onCloseTap'
invisible$='[[!entityObj.supportsClose]]'
disabled='[[computeClosedDisabled(stateObj, entityObj)]]'></paper-icon-button>
<div class="state">
<paper-icon-button icon="mdi:arrow-up" on-click="onOpenTap" invisible\$="[[!entityObj.supportsOpen]]" disabled="[[computeOpenDisabled(stateObj, entityObj)]]"></paper-icon-button>
<paper-icon-button icon="mdi:stop" on-click="onStopTap" invisible\$="[[!entityObj.supportsStop]]"></paper-icon-button>
<paper-icon-button icon="mdi:arrow-down" on-click="onCloseTap" invisible\$="[[!entityObj.supportsClose]]" disabled="[[computeClosedDisabled(stateObj, entityObj)]]"></paper-icon-button>
</div>
</template>
</dom-module>
`;
}
<script>
class HaCoverControls extends Polymer.Element {
static get is() { return 'ha-cover-controls'; }
static get properties() {
@ -71,4 +66,3 @@ class HaCoverControls extends Polymer.Element {
}
customElements.define(HaCoverControls.is, HaCoverControls);
</script>

View File

@ -1,12 +1,13 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
import '../util/cover-model.js';
<link rel='import' href='../util/cover-model.html'>
<dom-module id='ha-cover-tilt-controls'>
<template>
class HaCoverTiltControls extends PolymerElement {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
:host {
@ -16,22 +17,12 @@
visibility: hidden !important;
}
</style>
<paper-icon-button icon="mdi:arrow-top-right"
on-click='onOpenTiltTap' title='Open tilt'
invisible$='[[!entityObj.supportsOpenTilt]]'
disabled='[[computeOpenDisabled(stateObj, entityObj)]]'></paper-icon-button>
<paper-icon-button icon="mdi:stop" on-click='onStopTiltTap'
invisible$='[[!entityObj.supportsStopTilt]]'
title='Stop tilt'></paper-icon-button>
<paper-icon-button icon="mdi:arrow-bottom-left"
on-click='onCloseTiltTap' title='Close tilt'
invisible$='[[!entityObj.supportsCloseTilt]]'
disabled='[[computeClosedDisabled(stateObj, entityObj)]]'></paper-icon-button>
</template>
</dom-module>
<paper-icon-button icon="mdi:arrow-top-right" on-click="onOpenTiltTap" title="Open tilt" invisible\$="[[!entityObj.supportsOpenTilt]]" disabled="[[computeOpenDisabled(stateObj, entityObj)]]"></paper-icon-button>
<paper-icon-button icon="mdi:stop" on-click="onStopTiltTap" invisible\$="[[!entityObj.supportsStopTilt]]" title="Stop tilt"></paper-icon-button>
<paper-icon-button icon="mdi:arrow-bottom-left" on-click="onCloseTiltTap" title="Close tilt" invisible\$="[[!entityObj.supportsCloseTilt]]" disabled="[[computeClosedDisabled(stateObj, entityObj)]]"></paper-icon-button>
`;
}
<script>
class HaCoverTiltControls extends Polymer.Element {
static get is() { return 'ha-cover-tilt-controls'; }
static get properties() {
@ -74,4 +65,3 @@ class HaCoverTiltControls extends Polymer.Element {
}
customElements.define(HaCoverTiltControls.is, HaCoverTiltControls);
</script>

View File

@ -1,27 +0,0 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='./ha-label-badge.html'>
<dom-module id='ha-demo-badge'>
<template>
<style>
:host {
--ha-label-badge-color: #dac90d;
}
</style>
<ha-label-badge
icon='mdi:emoticon'
label='Demo'
description=''
></ha-label-badge>
</template>
</dom-module>
<script>
class HaDemoBadge extends Polymer.Element {
static get is() { return 'ha-demo-badge'; }
}
customElements.define(HaDemoBadge.is, HaDemoBadge);
</script>

View File

@ -0,0 +1,22 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import './ha-label-badge.js';
class HaDemoBadge extends PolymerElement {
static get template() {
return html`
<style>
:host {
--ha-label-badge-color: #dac90d;
}
</style>
<ha-label-badge icon="mdi:emoticon" label="Demo" description=""></ha-label-badge>
`;
}
static get is() { return 'ha-demo-badge'; }
}
customElements.define(HaDemoBadge.is, HaDemoBadge);

View File

@ -1,153 +0,0 @@
<link rel="import" href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href='../../bower_components/paper-input/paper-input.html'>
<link rel="import" href='../../bower_components/paper-checkbox/paper-checkbox.html'>
<link rel='import' href='../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html'>
<link rel='import' href='../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
<link rel='import' href='../util/hass-mixins.html'>
<link rel="import" href='./ha-paper-slider.html'>
<dom-module id="ha-form">
<template>
<style>
.error {
color: red;
}
</style>
<template is='dom-if' if='[[_isArray(schema)]]' restamp>
<template is='dom-if' if='[[error.base]]'>
[[computeError(error.base, schema)]]
</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>
<paper-input
label='[[computeLabel(schema)]]'
value='{{data}}'
></paper-input>
</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'
></paper-input>
</template>
</template>
<template is='dom-if' if='[[_equals(schema.type, "float")]]' restamp>
<!--TODO-->
<paper-input
label='[[computeLabel(schema)]]'
value='{{data}}'
></paper-input>
</template>
<template is='dom-if' if='[[_equals(schema.type, "boolean")]]' restamp>
<paper-checkbox
checked='{{data}}'
>[[computeLabel(schema)]]</paper-checkbox>
</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$='[[item]]'>[[item]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
</template>
</template>
</template>
</dom-module>
<script>
class HaForm extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-form'; }
static get properties() {
return {
data: {
type: Object,
notify: true,
},
schema: Object,
error: Object,
// A function that will computes the label to be displayed for a given
// schema object.
computeLabel: {
type: Function,
value: () => schema => schema && schema.name,
},
// A function that will computes an error message to be displayed for a
// given error ID, and relevant schema object
computeError: {
type: Function,
value: () => (error, schema) => error, // eslint-disable-line no-unused-vars
},
};
}
_isArray(val) {
return Array.isArray(val);
}
_isRange(schema) {
return ('valueMin' in schema) && ('valueMax' in schema);
}
_equals(a, b) {
return a === b;
}
_getValue(obj, item) {
return obj[item.name];
}
_valueChanged(ev) {
this.set(['data', ev.model.item.name], ev.detail.value);
}
}
customElements.define(HaForm.is, HaForm);
</script>

121
src/components/ha-form.js Normal file
View File

@ -0,0 +1,121 @@
import '@polymer/paper-checkbox/paper-checkbox.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../util/hass-mixins.js';
import './ha-paper-slider.js';
class HaForm extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
.error {
color: red;
}
</style>
<template is="dom-if" if="[[_isArray(schema)]]" restamp="">
<template is="dom-if" if="[[error.base]]">
[[computeError(error.base, schema)]]
</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, &quot;string&quot;)]]" restamp="">
<paper-input label="[[computeLabel(schema)]]" value="{{data}}"></paper-input>
</template>
<template is="dom-if" if="[[_equals(schema.type, &quot;integer&quot;)]]" 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"></paper-input>
</template>
</template>
<template is="dom-if" if="[[_equals(schema.type, &quot;float&quot;)]]" restamp="">
<!--TODO-->
<paper-input label="[[computeLabel(schema)]]" value="{{data}}"></paper-input>
</template>
<template is="dom-if" if="[[_equals(schema.type, &quot;boolean&quot;)]]" restamp="">
<paper-checkbox checked="{{data}}">[[computeLabel(schema)]]</paper-checkbox>
</template>
<template is="dom-if" if="[[_equals(schema.type, &quot;select&quot;)]]" 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\$="[[item]]">[[item]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
</template>
</template>
`;
}
static get is() { return 'ha-form'; }
static get properties() {
return {
data: {
type: Object,
notify: true,
},
schema: Object,
error: Object,
// A function that will computes the label to be displayed for a given
// schema object.
computeLabel: {
type: Function,
value: () => schema => schema && schema.name,
},
// A function that will computes an error message to be displayed for a
// given error ID, and relevant schema object
computeError: {
type: Function,
value: () => (error, schema) => error, // eslint-disable-line no-unused-vars
},
};
}
_isArray(val) {
return Array.isArray(val);
}
_isRange(schema) {
return ('valueMin' in schema) && ('valueMax' in schema);
}
_equals(a, b) {
return a === b;
}
_getValue(obj, item) {
return obj[item.name];
}
_valueChanged(ev) {
this.set(['data', ev.model.item.name], ev.detail.value);
}
}
customElements.define(HaForm.is, HaForm);

View File

@ -0,0 +1,35 @@
import '@polymer/iron-iconset-svg/iron-iconset-svg.js';
const IronIconsetClass = customElements.get('iron-iconset-svg');
class HaIconset extends IronIconsetClass {
/**
* Fire 'iron-iconset-added' event at next microtask.
*/
_fireIronIconsetAdded() {
this.async(function () {
this.fire('iron-iconset-added', this, { node: window });
});
}
/**
*
* When name is changed, register iconset metadata
*
*/
_nameChanged() {
this._meta.value = null;
this._meta.key = this.name;
this._meta.value = this;
if (this.ownerDocument && this.ownerDocument.readyState === 'loading') {
// Document still loading. It could be that not all icons in the iconset are parsed yet.
this.ownerDocument.addEventListener('DOMContentLoaded', function () {
this._fireIronIconsetAdded();
}.bind(this));
} else {
this._fireIronIconsetAdded();
}
}
}
customElements.define('ha-iconset-svg', HaIconset);

View File

@ -1,8 +1,10 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='ha-label-badge'>
<template>
class HaLabelBadge extends PolymerElement {
static get template() {
return html`
<style>
.badge-container {
display: inline-block;
@ -78,23 +80,21 @@
}
</style>
<div class='badge-container'>
<div class='label-badge' id='badge'>
<div class$='[[computeValueClasses(value)]]'>
<iron-icon icon='[[icon]]' hidden$='[[computeHideIcon(icon, value, image)]]'></iron-icon>
<span hidden$='[[computeHideValue(value, image)]]'>[[value]]</span>
<div class="badge-container">
<div class="label-badge" id="badge">
<div class\$="[[computeValueClasses(value)]]">
<iron-icon icon="[[icon]]" hidden\$="[[computeHideIcon(icon, value, image)]]"></iron-icon>
<span hidden\$="[[computeHideValue(value, image)]]">[[value]]</span>
</div>
<div hidden$='[[computeHideLabel(label)]]' class$='[[computeLabelClasses(label)]]'>
<div hidden\$="[[computeHideLabel(label)]]" class\$="[[computeLabelClasses(label)]]">
<span>[[label]]</span>
</div>
</div>
<div class='title' hidden$='[[!description]]'>[[description]]</div>
<div class="title" hidden\$="[[!description]]">[[description]]</div>
</div>
</template>
</dom-module>
`;
}
<script>
class HaLabelBadge extends Polymer.Element {
static get is() { return 'ha-label-badge'; }
static get properties() {
return {
@ -135,4 +135,3 @@ class HaLabelBadge extends Polymer.Element {
}
}
customElements.define(HaLabelBadge.is, HaLabelBadge);
</script>

View File

@ -1,9 +1,12 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
<link rel="import" href='./ha-paper-slider.html'>
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='ha-labeled-slider'>
<template>
import './ha-paper-slider.js';
class HaLabeledSlider extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
@ -30,17 +33,15 @@
}
</style>
<div class='title'>[[caption]]</div>
<iron-icon icon='[[icon]]'></iron-icon>
<div class='slider-container'>
<ha-paper-slider min='[[min]]' max='[[max]]' value='{{value}}' ignore-bar-touch='[[ignoreBarTouch]]'>
<div class="title">[[caption]]</div>
<iron-icon icon="[[icon]]"></iron-icon>
<div class="slider-container">
<ha-paper-slider min="[[min]]" max="[[max]]" value="{{value}}" ignore-bar-touch="[[ignoreBarTouch]]">
</ha-paper-slider>
</div>
</template>
</dom-module>
`;
}
<script>
class HaLabeledSlider extends Polymer.Element {
static get is() { return 'ha-labeled-slider'; }
static get properties() {
@ -60,4 +61,3 @@ class HaLabeledSlider extends Polymer.Element {
}
customElements.define(HaLabeledSlider.is, HaLabeledSlider);
</script>

View File

@ -1,12 +1,12 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../util/hass-mixins.js';
<link rel='import' href='../util/hass-mixins.html'>
let loaded = null;
<script>
/*
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaMarkdown extends window.hassMixins.EventsMixin(Polymer.Element) {
class HaMarkdown extends window.hassMixins.EventsMixin(PolymerElement) {
static get is() { return 'ha-markdown'; }
static get properties() {
@ -24,11 +24,13 @@ class HaMarkdown extends window.hassMixins.EventsMixin(Polymer.Element) {
this._renderScheduled = false;
this._resize = () => this.fire('iron-resize');
Polymer.importHref(
'/static/markdown-js.html',
() => { this._scriptLoaded = 1; this._render(); },
() => { this._scriptLoaded = 2; this._render(); },
);
if (!loaded) {
loaded = import(/* webpackChunkName: "load_markdown" */ '../resources/load_markdown.js');
}
loaded.then(
() => { this._scriptLoaded = 1; },
() => { this._scriptLoaded = 2; },
).then(() => this._render());
}
_render() {
@ -71,4 +73,3 @@ class HaMarkdown extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaMarkdown.is, HaMarkdown);
</script>

View File

@ -1,25 +1,21 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/paper-icon-button/paper-icon-button.html'>
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../util/hass-mixins.js';
<dom-module id='ha-menu-button'>
<template>
class HaMenuButton extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
.invisible {
visibility: hidden;
}
</style>
<paper-icon-button
icon='mdi:menu'
class$='[[computeMenuButtonClass(narrow, showMenu)]]'
on-click='toggleMenu'
></paper-icon-button>
</template>
</dom-module>
<paper-icon-button icon="mdi:menu" class\$="[[computeMenuButtonClass(narrow, showMenu)]]" on-click="toggleMenu"></paper-icon-button>
`;
}
<script>
class HaMenuButton extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-menu-button'; }
static get properties() {
@ -47,4 +43,3 @@ class HaMenuButton extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(HaMenuButton.is, HaMenuButton);
</script>

View File

@ -1,9 +1,12 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-slider/paper-slider.html">
import '@polymer/paper-slider/paper-slider.js';
import { DomModule } from '@polymer/polymer/lib/elements/dom-module.js';
import '@polymer/polymer/polymer-legacy.js';
const documentContainer = document.createElement('template');
documentContainer.setAttribute('style', 'display: none;');
<dom-module id="ha-paper-slider">
<template strip-whitespace>
documentContainer.innerHTML = `<dom-module id="ha-paper-slider">
<template strip-whitespace="">
<style include="paper-slider">
.pin > .slider-knob > .slider-knob-inner {
font-size: var(--ha-paper-slider-pin-font-size, 10px);
@ -53,36 +56,36 @@
</style>
</template>
<script>
'use strict';
{
/**
* @polymer
* @customElement
* @appliesMixin paper-slider
*/
const PaperSliderClass = customElements.get('paper-slider');
let myTemplate;
</dom-module>`;
class HaPaperSlider extends PaperSliderClass {
static get is() { return 'ha-paper-slider'; }
document.head.appendChild(documentContainer.content);
static get template() {
if (!myTemplate) {
// Retrieve this element's dom-module template
myTemplate = Polymer.DomModule.import(HaPaperSlider.is, 'template');
// Clone the contents of the superclass template
const superTemplateContents = document.importNode(PaperSliderClass.template.content, true);
// Remove the style from superclass contents, we already included them in our own <style>
superTemplateContents.querySelector('style').remove();
// Insert the superclass contents
myTemplate.content.append(superTemplateContents);
}
return myTemplate;
}
{
/**
* @polymer
* @customElement
* @appliesMixin paper-slider
*/
const PaperSliderClass = customElements.get('paper-slider');
let myTemplate;
class HaPaperSlider extends PaperSliderClass {
static get is() { return 'ha-paper-slider'; }
static get template() {
if (!myTemplate) {
// Retrieve this element's dom-module template
myTemplate = DomModule.import(HaPaperSlider.is, 'template');
// Clone the contents of the superclass template
const superTemplateContents = document.importNode(PaperSliderClass.template.content, true);
// Remove the style from superclass contents, we already included them in our own <style>
superTemplateContents.querySelector('style').remove();
// Insert the superclass contents
myTemplate.content.append(superTemplateContents);
}
customElements.define(HaPaperSlider.is, HaPaperSlider);
return myTemplate;
}
</script>
</dom-module>
}
customElements.define(HaPaperSlider.is, HaPaperSlider);
}

View File

@ -1,20 +1,16 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-toggle-button/paper-toggle-button.html">
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../util/hass-mixins.html'>
import '../util/hass-mixins.js';
<dom-module id='ha-push-notifications-toggle'>
<template>
<paper-toggle-button
hidden$='[[!pushSupported]]'
disabled='[[loading]]'
checked='{{pushChecked}}'
></paper-toggle-button>
</template>
</dom-module>
class HaPushNotificationsToggle extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<paper-toggle-button hidden\$="[[!pushSupported]]" disabled="[[loading]]" checked="{{pushChecked}}"></paper-toggle-button>
`;
}
<script>
class HaPushNotificationsToggle extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-push-notifications-toggle'; }
static get properties() {
@ -127,4 +123,3 @@ class HaPushNotificationsToggle extends window.hassMixins.EventsMixin(Polymer.El
}
customElements.define(HaPushNotificationsToggle.is, HaPushNotificationsToggle);
</script>

View File

@ -1,7 +1,9 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<script>
class HaRelativeTime extends Polymer.Element {
import relativeTime from '../../js/common/datetime/relative_time.js';
class HaRelativeTime extends PolymerElement {
static get is() { return 'ha-relative-time'; }
static get properties() {
@ -51,11 +53,10 @@ class HaRelativeTime extends Polymer.Element {
}
updateRelative() {
var root = Polymer.dom(this);
var root = dom(this);
root.innerHTML = this.parsedDateTime ?
window.hassUtil.relativeTime(this.parsedDateTime) : 'never';
relativeTime(this.parsedDateTime) : 'never';
}
}
customElements.define(HaRelativeTime.is, HaRelativeTime);
</script>

View File

@ -1,13 +1,13 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='ha-service-description'>
<template>
class HaServiceDescription extends PolymerElement {
static get template() {
return html`
[[_getDescription(hass, domain, service)]]
</template>
</dom-module>
`;
}
<script>
class HaServiceDescription extends Polymer.Element {
static get is() { return 'ha-service-description'; }
static get properties() {
@ -28,4 +28,3 @@ class HaServiceDescription extends Polymer.Element {
}
customElements.define(HaServiceDescription.is, HaServiceDescription);
</script>

View File

@ -1,25 +1,19 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../util/hass-mixins.html">
import '../util/hass-mixins.js';
import './ha-combo-box.js';
<link rel="import" href="./ha-combo-box.html">
<dom-module id="ha-service-picker">
<template>
<ha-combo-box
label="[[localize('ui.components.service-picker.service')]]"
items='[[_services]]'
value='{{value}}'
allow-custom-value
></ha-combo-box>
</template>
</dom-module>
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaServicePicker extends window.hassMixins.LocalizeMixin(Polymer.Element) {
class HaServicePicker extends window.hassMixins.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>
`;
}
static get is() { return 'ha-service-picker'; }
static get properties() {
@ -58,4 +52,3 @@ class HaServicePicker extends window.hassMixins.LocalizeMixin(Polymer.Element) {
}
customElements.define(HaServicePicker.is, HaServicePicker);
</script>

View File

@ -1,18 +1,24 @@
<link rel="import" href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
<link rel='import' href='../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../bower_components/paper-item/paper-item.html'>
<link rel='import' href='../../bower_components/paper-item/paper-icon-item.html'>
<link rel='import' href='../../bower_components/paper-icon-button/paper-icon-button.html'>
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-item/paper-icon-item.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/app-layout/app-toolbar/app-toolbar.html">
import '../util/hass-mixins.js';
import '../util/hass-translation.js';
<link rel='import' href='../util/hass-mixins.html'>
<link rel='import' href='../util/hass-translation.html'>
<dom-module id='ha-sidebar'>
<template>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaSidebar extends
window.hassMixins.LocalizeMixin(window.hassMixins.NavigateMixin(PolymerElement)) {
static get template() {
return html`
<style include="iron-flex iron-flex-alignment iron-positioning">
:host {
--sidebar-text: {
@ -94,73 +100,48 @@
</style>
<app-toolbar>
<div main-title>Home Assistant</div>
<paper-icon-button icon='mdi:chevron-left' hidden$='[[narrow]]' on-click='toggleMenu'></paper-icon-button>
<div main-title="">Home Assistant</div>
<paper-icon-button icon="mdi:chevron-left" hidden\$="[[narrow]]" on-click="toggleMenu"></paper-icon-button>
</app-toolbar>
<paper-listbox attr-for-selected='data-panel' selected='[[hass.panelUrl]]'>
<paper-icon-item on-click='menuClicked' data-panel='states'>
<iron-icon slot="item-icon" icon='mdi:apps'></iron-icon>
<span class='item-text'>[[localize('panel.states')]]</span>
<paper-listbox attr-for-selected="data-panel" selected="[[hass.panelUrl]]">
<paper-icon-item on-click="menuClicked" data-panel="states">
<iron-icon slot="item-icon" icon="mdi:apps"></iron-icon>
<span class="item-text">[[localize('panel.states')]]</span>
</paper-icon-item>
<template is='dom-repeat' items='[[panels]]'>
<paper-icon-item on-click='menuClicked' data-panel$='[[item.url_path]]'>
<iron-icon slot="item-icon" icon='[[item.icon]]'></iron-icon>
<span class='item-text'>[[computePanelName(localize, item)]]</span>
<template is="dom-repeat" items="[[panels]]">
<paper-icon-item on-click="menuClicked">
<iron-icon slot="item-icon" icon="[[item.icon]]"></iron-icon>
<span class="item-text">[[computePanelName(localize, item)]]</span>
</paper-icon-item>
</template>
<paper-icon-item on-click='menuClicked' data-panel='logout' class='logout'>
<iron-icon slot="item-icon" icon='mdi:exit-to-app'></iron-icon>
<span class='item-text'>[[localize('ui.sidebar.log_out')]]</span>
<paper-icon-item on-click="menuClicked" data-panel="logout" class="logout">
<iron-icon slot="item-icon" icon="mdi:exit-to-app"></iron-icon>
<span class="item-text">[[localize('ui.sidebar.log_out')]]</span>
</paper-icon-item>
</paper-listbox>
<div>
<div class='divider'></div>
<div class="divider"></div>
<div class='subheader'>[[localize('ui.sidebar.developer_tools')]]</div>
<div class="subheader">[[localize('ui.sidebar.developer_tools')]]</div>
<div class='dev-tools layout horizontal justified'>
<paper-icon-button
icon='mdi:remote' data-panel='dev-service'
alt="[[localize('panel.dev-services')]]" title="[[localize('panel.dev-services')]]"
on-click='menuClicked'></paper-icon-button>
<paper-icon-button
icon='mdi:code-tags' data-panel='dev-state'
alt="[[localize('panel.dev-states')]]" title="[[localize('panel.dev-states')]]"
on-click='menuClicked'></paper-icon-button>
<paper-icon-button
icon='mdi:radio-tower' data-panel='dev-event'
alt="[[localize('panel.dev-events')]]" title="[[localize('panel.dev-events')]]"
on-click='menuClicked'></paper-icon-button>
<paper-icon-button
icon='mdi:file-xml' data-panel='dev-template'
alt="[[localize('panel.dev-templates')]]" title="[[localize('panel.dev-templates')]]"
on-click='menuClicked'></paper-icon-button>
<template is='dom-if' if='[[_mqttLoaded(hass)]]'>
<paper-icon-button
icon='mdi:altimeter' data-panel='dev-mqtt'
alt="[[localize('panel.dev-mqtt')]]" title="[[localize('panel.dev-mqtt')]]"
on-click='menuClicked'></paper-icon-button>
<div class="dev-tools layout horizontal justified">
<paper-icon-button icon="mdi:remote" data-panel="dev-service" alt="[[localize('panel.dev-services')]]" title="[[localize('panel.dev-services')]]" on-click="menuClicked"></paper-icon-button>
<paper-icon-button icon="mdi:code-tags" data-panel="dev-state" alt="[[localize('panel.dev-states')]]" title="[[localize('panel.dev-states')]]" on-click="menuClicked"></paper-icon-button>
<paper-icon-button icon="mdi:radio-tower" data-panel="dev-event" alt="[[localize('panel.dev-events')]]" title="[[localize('panel.dev-events')]]" on-click="menuClicked"></paper-icon-button>
<paper-icon-button icon="mdi:file-xml" data-panel="dev-template" alt="[[localize('panel.dev-templates')]]" title="[[localize('panel.dev-templates')]]" on-click="menuClicked"></paper-icon-button>
<template is="dom-if" if="[[_mqttLoaded(hass)]]">
<paper-icon-button icon="mdi:altimeter" data-panel="dev-mqtt" alt="[[localize('panel.dev-mqtt')]]" title="[[localize('panel.dev-mqtt')]]" on-click="menuClicked"></paper-icon-button>
</template>
<paper-icon-button
icon='mdi:information-outline' data-panel='dev-info'
alt="[[localize('panel.dev-info')]]" title="[[localize('panel.dev-info')]]"
on-click='menuClicked'></paper-icon-button>
<paper-icon-button icon="mdi:information-outline" data-panel="dev-info" alt="[[localize('panel.dev-info')]]" title="[[localize('panel.dev-info')]]" on-click="menuClicked"></paper-icon-button>
</div>
</div>
</template>
</dom-module>
`;
}
<script>
/*
* @appliesMixin window.hassMixins.LocalizeMixin
* @appliesMixin window.hassMixins.EventsMixin
*/
class HaSidebar extends
window.hassMixins.LocalizeMixin(window.hassMixins.NavigateMixin(Polymer.Element)) {
static get is() { return 'ha-sidebar'; }
static get properties() {
@ -230,18 +211,23 @@ class HaSidebar extends
}
menuClicked(ev) {
var target = ev.target;
var checks = 5;
var attr = target.getAttribute('data-panel');
// find panel to select
while (checks && !attr) {
target = target.parentElement;
attr = target.getAttribute('data-panel');
checks--;
// Selection made inside dom-repeat
if (ev.model) {
this.selectPanel(ev.model.item.component_name);
return;
}
if (checks) {
let target = ev.target;
let checks = 5;
let attr;
do {
attr = target.getAttribute('data-panel');
target = target.parentElement;
checks--;
} while (checks > 0 && target !== null && !attr);
if (checks > 0 && target !== null) {
this.selectPanel(attr);
}
}
@ -268,4 +254,3 @@ class HaSidebar extends
}
customElements.define(HaSidebar.is, HaSidebar);
</script>

View File

@ -1,20 +1,16 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
import '../util/hass-mixins.js';
<dom-module id='ha-start-voice-button'>
<template>
<paper-icon-button
icon="mdi:microphone" hidden$='[[!canListen]]'
on-click="handleListenClick"
></paper-icon-button>
class HaStartVoiceButton extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<paper-icon-button icon="mdi:microphone" hidden\$="[[!canListen]]" on-click="handleListenClick"></paper-icon-button>
`;
}
</template>
</dom-module>
<script>
class HaStartVoiceButton extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'ha-start-voice-button'; }
static get properties() {
@ -43,4 +39,3 @@ class HaStartVoiceButton extends window.hassMixins.EventsMixin(Polymer.Element)
}
customElements.define(HaStartVoiceButton.is, HaStartVoiceButton);
</script>

View File

@ -1,11 +1,13 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel='import' href='../../bower_components/iron-icon/iron-icon.html'>
import '@polymer/iron-icon/iron-icon.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='./ha-relative-time.html'>
<link rel='import' href='../util/hass-util.html'>
import '../util/hass-util.js';
import './ha-relative-time.js';
<dom-module id='hassio-card-content'>
<template>
class HassioCardContent extends PolymerElement {
static get template() {
return html`
<style>
iron-icon {
margin-right: 16px;
@ -41,23 +43,21 @@
display: block;
}
</style>
<iron-icon icon='[[icon]]' class$='[[iconClass]]' title='[[iconTitle]]'></iron-icon>
<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]]'>
<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 class='addition' datetime='[[datetime]]'></ha-relative-time>
<template is="dom-if" if="[[datetime]]">
<ha-relative-time class="addition" datetime="[[datetime]]"></ha-relative-time>
</template>
</div>
</div>
</template>
</dom-module>
`;
}
<script>
class HassioCardContent extends Polymer.Element {
static get is() { return 'hassio-card-content'; }
static get properties() {
@ -75,4 +75,3 @@ class HassioCardContent extends Polymer.Element {
}
}
customElements.define(HassioCardContent.is, HassioCardContent);
</script>

View File

@ -1,9 +1,12 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/utils/debounce.html">
<link rel="import" href="./entity/ha-chart-base.html">
import '@polymer/polymer/lib/utils/debounce.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='state-history-chart-line'>
<template>
import './entity/ha-chart-base.js';
class StateHistoryChartLine extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
@ -12,16 +15,10 @@
transition: height 0.3s ease-in-out;
}
</style>
<ha-chart-base
id='chart'
data="[[chartData]]"
identifier="[[identifier]]"
rendered="{{rendered}}"
></ha-chart-base>
</template>
</dom-module>
<script>
class StateHistoryChartLine extends Polymer.Element {
<ha-chart-base id="chart" data="[[chartData]]" identifier="[[identifier]]" rendered="{{rendered}}"></ha-chart-base>
`;
}
static get is() { return 'state-history-chart-line'; }
static get properties() {
return {
@ -299,4 +296,3 @@ class StateHistoryChartLine extends Polymer.Element {
}
}
customElements.define(StateHistoryChartLine.is, StateHistoryChartLine);
</script>

View File

@ -1,9 +1,12 @@
<link rel='import' href='../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../bower_components/polymer/lib/utils/debounce.html">
<link rel='import' href='./entity/ha-chart-base.html'>
import '@polymer/polymer/lib/utils/debounce.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<dom-module id='state-history-chart-timeline'>
<template>
import './entity/ha-chart-base.js';
class StateHistoryChartTimeline extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
@ -15,16 +18,10 @@
}
</style>
<ha-chart-base
data="[[chartData]]"
rendered="{{rendered}}"
></ha-chart-base>
</template>
</dom-module>
<script>
'use strict';
<ha-chart-base data="[[chartData]]" rendered="{{rendered}}"></ha-chart-base>
`;
}
class StateHistoryChartTimeline extends Polymer.Element {
static get is() { return 'state-history-chart-timeline'; }
static get properties() {
return {
@ -195,5 +192,3 @@ class StateHistoryChartTimeline extends Polymer.Element {
}
}
customElements.define(StateHistoryChartTimeline.is, StateHistoryChartTimeline);
</script>

View File

@ -1,11 +1,13 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
import '@polymer/paper-spinner/paper-spinner.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="./state-history-chart-timeline.html">
<link rel="import" href="./state-history-chart-line.html">
import './state-history-chart-line.js';
import './state-history-chart-timeline.js';
<dom-module id="state-history-charts">
<template>
class StateHistoryCharts extends PolymerElement {
static get template() {
return html`
<style>
:host {
display: block;
@ -18,36 +20,26 @@
color: var(--secondary-text-color);
}
</style>
<template is='dom-if' class='info' if='[[_computeIsLoading(isLoadingData)]]'>
<div class='info'>Loading state history...</div>
<template is="dom-if" class="info" if="[[_computeIsLoading(isLoadingData)]]">
<div class="info">Loading state history...</div>
</template>
<template is='dom-if' class='info' if='[[_computeIsEmpty(isLoadingData, historyData)]]'>
<div class='info'>No state history found.</div>
<template is="dom-if" class="info" if="[[_computeIsEmpty(isLoadingData, historyData)]]">
<div class="info">No state history found.</div>
</template>
<template is='dom-if' if='[[historyData.timeline.length]]'>
<state-history-chart-timeline
data='[[historyData.timeline]]'
end-time='[[_computeEndTime(endTime, upToNow, historyData)]]'
no-single='[[noSingle]]'>
<template is="dom-if" if="[[historyData.timeline.length]]">
<state-history-chart-timeline data="[[historyData.timeline]]" end-time="[[_computeEndTime(endTime, upToNow, historyData)]]" no-single="[[noSingle]]">
</state-history-chart-timeline>
</template>
<template is='dom-repeat' items='[[historyData.line]]'>
<state-history-chart-line
unit='[[item.unit]]'
data='[[item.data]]'
identifier='[[item.identifier]]'
is-single-device='[[_computeIsSingleLineChart(item.data, noSingle)]]'
end-time='[[_computeEndTime(endTime, upToNow, historyData)]]'>
<template is="dom-repeat" items="[[historyData.line]]">
<state-history-chart-line unit="[[item.unit]]" data="[[item.data]]" identifier="[[item.identifier]]" is-single-device="[[_computeIsSingleLineChart(item.data, noSingle)]]" end-time="[[_computeEndTime(endTime, upToNow, historyData)]]">
</state-history-chart-line>
</template>
</template>
</dom-module>
`;
}
<script>
class StateHistoryCharts extends Polymer.Element {
static get is() { return 'state-history-charts'; }
static get properties() {
return {
@ -91,4 +83,3 @@ class StateHistoryCharts extends Polymer.Element {
}
}
customElements.define(StateHistoryCharts.is, StateHistoryCharts);
</script>

View File

@ -1,10 +1,9 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../src/util/hass-mixins.html'>
<link rel='import' href='../../src/util/hass-util.html'>
<script>
'use strict';
import '../util/hass-mixins.js';
import '../util/hass-util.js';
{
const RECENT_THRESHOLD = 60000; // 1 minute
@ -99,7 +98,7 @@
/*
* @appliesMixin window.hassMixins.LocalizeMixin
*/
class HaStateHistoryData extends window.hassMixins.LocalizeMixin(Polymer.Element) {
class HaStateHistoryData extends window.hassMixins.LocalizeMixin(PolymerElement) {
static get is() { return 'ha-state-history-data'; }
static get properties() {
return {
@ -165,9 +164,9 @@
}
filterChangedDebouncer(...args) {
this._debounceFilterChanged = Polymer.Debouncer.debounce(
this._debounceFilterChanged = Debouncer.debounce(
this._debounceFilterChanged,
Polymer.Async.timeOut.after(0),
timeOut.after(0),
() => {
this.filterChanged(...args);
}
@ -385,4 +384,3 @@
}
customElements.define(HaStateHistoryData.is, HaStateHistoryData);
}
</script>

View File

@ -1,15 +1,16 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/paper-dialog-behavior/paper-dialog-shared-styles.js';
import '@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/paper-dialog-behavior/paper-dialog-shared-styles.html">
<link rel="import" href="../../bower_components/paper-dialog-scrollable/paper-dialog-scrollable.html">
<link rel='import' href='../util/hass-mixins.html'>
<link rel='import' href='../resources/ha-style.html'>
import '../resources/ha-style.js';
import '../util/hass-mixins.js';
import './more-info/more-info-controls.js';
import './more-info/more-info-settings.js';
<link rel='import' href='./more-info/more-info-controls.html'>
<link rel='import' href='./more-info/more-info-settings.html'>
<dom-module id="ha-more-info-dialog">
<template>
class HaMoreInfoDialog extends window.hassMixins.DialogMixin(PolymerElement) {
static get template() {
return html`
<style include="ha-style-dialog paper-dialog-shared-styles">
:host {
font-size: 14px;
@ -64,29 +65,15 @@
}
</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 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 is="dom-if" if="[[_equals(_page, &quot;settings&quot;)]]">
<more-info-settings class="no-padding" hass="[[hass]]" state-obj="[[stateObj]]" registry-info="{{_registryInfo}}"></more-info-settings>
</template>
</template>
</dom-module>
`;
}
<script>
class HaMoreInfoDialog extends window.hassMixins.DialogMixin(Polymer.Element) {
static get is() { return 'ha-more-info-dialog'; }
static get properties() {
return {
@ -176,4 +163,3 @@ class HaMoreInfoDialog extends window.hassMixins.DialogMixin(Polymer.Element) {
}
}
customElements.define(HaMoreInfoDialog.is, HaMoreInfoDialog);
</script>

View File

@ -1,12 +1,12 @@
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
import '@polymer/iron-icon/iron-icon.js';
import '@polymer/paper-dialog-behavior/paper-dialog-shared-styles.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../bower_components/paper-dialog-behavior/paper-dialog-shared-styles.html">
<link rel="import" href="../../bower_components/iron-icon/iron-icon.html">
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<dom-module id="ha-voice-command-dialog">
<template>
class HaVoiceCommandDialog extends window.hassMixins.DialogMixin(PolymerElement) {
static get template() {
return html`
<style include="paper-dialog-shared-styles">
iron-icon {
margin-right: 8px;
@ -105,34 +105,28 @@
}
</style>
<div class='content'>
<div class='messages' id='messages'>
<template is='dom-repeat' items='[[_conversation]]' as='message'>
<div class$='[[_computeMessageClasses(message)]]'>[[message.text]]</div>
<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'>
<template is="dom-if" if="[[results]]">
<div class="messages">
<div class="message user">
<span>{{results.final}}</span>
<span class='interimTranscript'>[[results.interim]]</span>
<span class="interimTranscript">[[results.interim]]</span>
</div>
</div>
</template>
<div class='icon' hidden$="[[results]]">
<paper-icon-button
icon="mdi:text-to-speech"
on-click='startListening'
></paper-icon-button>
<div class="icon" hidden\$="[[results]]">
<paper-icon-button icon="mdi:text-to-speech" on-click="startListening"></paper-icon-button>
</div>
</div>
</template>
`;
}
</dom-module>
<script>
class HaVoiceCommandDialog extends window.hassMixins.DialogMixin(Polymer.Element) {
static get is() { return 'ha-voice-command-dialog'; }
static get properties() {
@ -249,4 +243,3 @@ class HaVoiceCommandDialog extends window.hassMixins.DialogMixin(Polymer.Element
}
customElements.define(HaVoiceCommandDialog.is, HaVoiceCommandDialog);
</script>

View File

@ -1,45 +1,27 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../../bower_components/paper-button/paper-button.html'>
<link rel='import' href='../../../../bower_components/paper-input/paper-input.html'>
import '../../../util/hass-mixins.js';
<link rel='import' href='../../../../src/util/hass-mixins.html'>
<dom-module id='more-info-alarm_control_panel'>
<template>
class MoreInfoAlarmControlPanel extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<div class='layout horizontal'>
<paper-input
label='code'
value='{{enteredCode}}'
pattern='[[codeFormat]]'
type='password'
hidden$='[[!codeFormat]]'
disabled='[[!codeInputEnabled]]'
></paper-input>
<div class="layout horizontal">
<paper-input label="code" value="{{enteredCode}}" pattern="[[codeFormat]]" type="password" hidden\$="[[!codeFormat]]" disabled="[[!codeInputEnabled]]"></paper-input>
</div>
<div class='layout horizontal'>
<paper-button
on-click='handleDisarmTap'
hidden$='[[!disarmButtonVisible]]'
disabled='[[!codeValid]]'
>Disarm</paper-button>
<paper-button
on-click='handleHomeTap'
hidden$='[[!armHomeButtonVisible]]'
disabled=[[!codeValid]]>Arm Home</paper-button>
<paper-button
on-click='handleAwayTap'
hidden$='[[!armAwayButtonVisible]]'
disabled='[[!codeValid]]'>Arm Away</paper-button>
<div class="layout horizontal">
<paper-button on-click="handleDisarmTap" hidden\$="[[!disarmButtonVisible]]" disabled="[[!codeValid]]">Disarm</paper-button>
<paper-button on-click="handleHomeTap" hidden\$="[[!armHomeButtonVisible]]" disabled="[[!codeValid]]">Arm Home</paper-button>
<paper-button on-click="handleAwayTap" hidden\$="[[!armAwayButtonVisible]]" disabled="[[!codeValid]]">Arm Away</paper-button>
</div>
</template>
</dom-module>
`;
}
<script>
class MoreInfoAlarmControlPanel extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'more-info-alarm_control_panel'; }
static get properties() {
@ -138,4 +120,3 @@ class MoreInfoAlarmControlPanel extends window.hassMixins.EventsMixin(Polymer.El
}
customElements.define(MoreInfoAlarmControlPanel.is, MoreInfoAlarmControlPanel);
</script>

View File

@ -1,13 +1,13 @@
<link rel="import" href="../../../../bower_components/polymer/polymer-element.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-button/paper-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '../../../components/ha-relative-time.js';
<link rel="import" href="../../../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../../components/ha-relative-time.html">
<dom-module id="more-info-automation">
<template>
class MoreInfoAutomation extends PolymerElement {
static get template() {
return html`
<style>
paper-button {
color: var(--primary-color);
@ -22,13 +22,10 @@
<ha-relative-time datetime="[[stateObj.attributes.last_triggered]]"></ha-relative-time>
</p>
<paper-button on-click='handleTriggerTapped'>TRIGGER</paper-button>
<paper-button on-click="handleTriggerTapped">TRIGGER</paper-button>
`;
}
</template>
</dom-module>
<script>
class MoreInfoAutomation extends Polymer.Element {
static get is() { return 'more-info-automation'; }
static get properties() {
@ -51,4 +48,3 @@ class MoreInfoAutomation extends Polymer.Element {
}
customElements.define(MoreInfoAutomation.is, MoreInfoAutomation);
</script>

View File

@ -1,9 +1,11 @@
<link rel="import" href="../../../../bower_components/polymer/polymer-element.html">
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../../src/util/hass-mixins.html'>
import '../../../util/hass-mixins.js';
<dom-module id='more-info-camera'>
<template>
class MoreInfoCamera extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style>
:host {
max-width:640px;
@ -14,13 +16,10 @@
}
</style>
<img class='camera-image' src="[[computeCameraImageUrl(hass, stateObj, isVisible)]]"
on-load='imageLoaded' alt='[[computeStateName(stateObj)]]' />
</template>
</dom-module>
<img class="camera-image" src="[[computeCameraImageUrl(hass, stateObj, isVisible)]]" on-load="imageLoaded" alt="[[computeStateName(stateObj)]]">
`;
}
<script>
class MoreInfoCamera extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'more-info-camera'; }
static get properties() {
@ -71,4 +70,3 @@ class MoreInfoCamera extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(MoreInfoCamera.is, MoreInfoCamera);
</script>

View File

@ -1,20 +1,20 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../../bower_components/polymer/lib/utils/debounce.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { timeOut } from '@polymer/polymer/lib/utils/async.js';
import { Debouncer } from '@polymer/polymer/lib/utils/debounce.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
import '../../../components/ha-climate-control.js';
import '../../../components/ha-paper-slider.js';
import '../../../util/hass-mixins.js';
<link rel='import' href='../../../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../../../bower_components/paper-item/paper-item.html'>
<link rel='import' href='../../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html'>
<link rel='import' href='../../../../bower_components/paper-toggle-button/paper-toggle-button.html'>
<link rel='import' href='../../../../src/util/hass-mixins.html'>
<link rel="import" href='../../../components/ha-climate-control.html'>
<link rel="import" href='../../../components/ha-paper-slider.html'>
<dom-module id='more-info-climate'>
<template>
class MoreInfoClimate extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
:host {
@ -105,87 +105,52 @@
}
</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'>On / Off</div>
<paper-toggle-button
checked='[[onToggleChecked]]'
on-change='onToggleChanged'>
<template is="dom-if" if="[[supportsOn(stateObj)]]">
<div class="container-on">
<div class="center horizontal layout single-row">
<div class="flex">On / Off</div>
<paper-toggle-button checked="[[onToggleChecked]]" on-change="onToggleChanged">
</paper-toggle-button>
</div>
</div>
</template>
<div class='container-temperature'>
<div class$='[[stateObj.attributes.operation_mode]]'>
<div hidden$='[[!supportsTemperatureControls(stateObj)]]'>Target
<div class="container-temperature">
<div class\$="[[stateObj.attributes.operation_mode]]">
<div hidden\$="[[!supportsTemperatureControls(stateObj)]]">Target
Temperature</div>
<template is='dom-if' if='[[supportsTemperature(stateObj)]]'>
<ha-climate-control
value='[[stateObj.attributes.temperature]]'
units='[[stateObj.attributes.unit_of_measurement]]'
step='[[computeTemperatureStepSize(stateObj)]]'
min='[[stateObj.attributes.min_temp]]'
max='[[stateObj.attributes.max_temp]]'
on-change='targetTemperatureChanged'
>
<template is="dom-if" if="[[supportsTemperature(stateObj)]]">
<ha-climate-control value="[[stateObj.attributes.temperature]]" units="[[stateObj.attributes.unit_of_measurement]]" step="[[computeTemperatureStepSize(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='[[stateObj.attributes.unit_of_measurement]]'
step='[[computeTemperatureStepSize(stateObj)]]'
min='[[stateObj.attributes.min_temp]]'
max='[[stateObj.attributes.target_temp_high]]'
class='range-control-left'
on-change='targetTemperatureLowChanged'
>
<template is="dom-if" if="[[supportsTemperatureRange(stateObj)]]">
<ha-climate-control value="[[stateObj.attributes.target_temp_low]]" units="[[stateObj.attributes.unit_of_measurement]]" step="[[computeTemperatureStepSize(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='[[stateObj.attributes.unit_of_measurement]]'
step='[[computeTemperatureStepSize(stateObj)]]'
min='[[stateObj.attributes.target_temp_low]]'
max='[[stateObj.attributes.max_temp]]'
class='range-control-right'
on-change='targetTemperatureHighChanged'
>
<ha-climate-control value="[[stateObj.attributes.target_temp_high]]" units="[[stateObj.attributes.unit_of_measurement]]" step="[[computeTemperatureStepSize(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'>
<template is="dom-if" if="[[supportsHumidity(stateObj)]]">
<div class="container-humidity">
<div>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>
<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>
</template>
<template is='dom-if' if='[[supportsOperationMode(stateObj)]]'>
<div class='container-operation_list'>
<div class='controls'>
<paper-dropdown-menu class='capitalize' label-float dynamic-align label='Operation'>
<template is="dom-if" if="[[supportsOperationMode(stateObj)]]">
<div class="container-operation_list">
<div class="controls">
<paper-dropdown-menu class="capitalize" label-float="" dynamic-align="" label="Operation">
<paper-listbox slot="dropdown-content" selected="{{operationIndex}}">
<template is='dom-repeat'
items='[[stateObj.attributes.operation_list]]'
on-dom-change='handleOperationListUpdate'>
<template is="dom-repeat" items="[[stateObj.attributes.operation_list]]" on-dom-change="handleOperationListUpdate">
<paper-item class="capitalize">[[item]]</paper-item>
</template>
</paper-listbox>
@ -194,13 +159,11 @@
</div>
</template>
<template is='dom-if' if='[[supportsFanMode(stateObj)]]'>
<div class='container-fan_list'>
<paper-dropdown-menu label-float dynamic-align label='Fan Mode'>
<template is="dom-if" if="[[supportsFanMode(stateObj)]]">
<div class="container-fan_list">
<paper-dropdown-menu label-float="" dynamic-align="" label="Fan Mode">
<paper-listbox slot="dropdown-content" selected="{{fanIndex}}">
<template is='dom-repeat'
items='[[stateObj.attributes.fan_list]]'
on-dom-change='handleFanListUpdate'>
<template is="dom-repeat" items="[[stateObj.attributes.fan_list]]" on-dom-change="handleFanListUpdate">
<paper-item>[[item]]</paper-item>
</template>
</paper-listbox>
@ -208,13 +171,11 @@
</div>
</template>
<template is='dom-if' if='[[supportsSwingMode(stateObj)]]'>
<div class='container-swing_list'>
<paper-dropdown-menu label-float dynamic-align label='Swing Mode'>
<template is="dom-if" if="[[supportsSwingMode(stateObj)]]">
<div class="container-swing_list">
<paper-dropdown-menu label-float="" dynamic-align="" label="Swing Mode">
<paper-listbox slot="dropdown-content" selected="{{swingIndex}}">
<template is='dom-repeat'
items='[[stateObj.attributes.swing_list]]'
on-dom-change='handleSwingListUpdate'>
<template is="dom-repeat" items="[[stateObj.attributes.swing_list]]" on-dom-change="handleSwingListUpdate">
<paper-item>[[item]]</paper-item>
</template>
</paper-listbox>
@ -222,35 +183,29 @@
</div>
</template>
<template is='dom-if' if='[[supportsAwayMode(stateObj)]]'>
<div class='container-away_mode'>
<div class='center horizontal layout single-row'>
<div class='flex'>Away Mode</div>
<paper-toggle-button
checked='[[awayToggleChecked]]'
on-change='awayToggleChanged'>
<template is="dom-if" if="[[supportsAwayMode(stateObj)]]">
<div class="container-away_mode">
<div class="center horizontal layout single-row">
<div class="flex">Away Mode</div>
<paper-toggle-button checked="[[awayToggleChecked]]" on-change="awayToggleChanged">
</paper-toggle-button>
</div>
</div>
</template>
<template is='dom-if' if='[[supportsAuxHeat(stateObj)]]'>
<div class='container-aux_heat'>
<div class='center horizontal layout single-row'>
<div class='flex'>Aux Heat</div>
<paper-toggle-button
checked='[[auxToggleChecked]]'
on-change='auxToggleChanged'>
<template is="dom-if" if="[[supportsAuxHeat(stateObj)]]">
<div class="container-aux_heat">
<div class="center horizontal layout single-row">
<div class="flex">Aux Heat</div>
<paper-toggle-button checked="[[auxToggleChecked]]" on-change="auxToggleChanged">
</paper-toggle-button>
</div>
</div>
</template>
</div>
</template>
</dom-module>
`;
}
<script>
class MoreInfoClimate extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'more-info-climate'; }
static get properties() {
@ -297,9 +252,9 @@ class MoreInfoClimate extends window.hassMixins.EventsMixin(Polymer.Element) {
}
if (oldVal) {
this._debouncer = Polymer.Debouncer.debounce(
this._debouncer = Debouncer.debounce(
this._debouncer,
Polymer.Async.timeOut.after(500),
timeOut.after(500),
() => {
this.fire('iron-resize');
}
@ -504,4 +459,3 @@ class MoreInfoClimate extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(MoreInfoClimate.is, MoreInfoClimate);
</script>

View File

@ -1,14 +1,16 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
<link rel="import" href="../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel='import' href='../../../../bower_components/iron-input/iron-input.html'>
<link rel='import' href='../../../../bower_components/paper-spinner/paper-spinner.html'>
<link rel='import' href='../../../../bower_components/paper-button/paper-button.html'>
<link rel='import' href='../../../../bower_components/paper-input/paper-input.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/iron-input/iron-input.js';
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-spinner/paper-spinner.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../components/ha-markdown.html'>
import '../../../components/ha-markdown.js';
<dom-module id='more-info-configurator'>
<template>
class MoreInfoConfigurator extends PolymerElement {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
p {
@ -47,33 +49,21 @@
}
</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]]'>
<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>
<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>
@ -81,11 +71,9 @@
</template>
</div>
</template>
</dom-module>
`;
}
<script>
class MoreInfoConfigurator extends Polymer.Element {
static get is() { return 'more-info-configurator'; }
static get properties() {
@ -145,4 +133,3 @@ class MoreInfoConfigurator extends Polymer.Element {
}
customElements.define(MoreInfoConfigurator.is, MoreInfoConfigurator);
</script>

View File

@ -1,27 +1,26 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='more-info-alarm_control_panel.html'>
<link rel='import' href='more-info-automation.html'>
<link rel='import' href='more-info-camera.html'>
<link rel='import' href='more-info-climate.html'>
<link rel='import' href='more-info-configurator.html'>
<link rel='import' href='more-info-cover.html'>
<link rel='import' href='more-info-default.html'>
<link rel='import' href='more-info-fan.html'>
<link rel='import' href='more-info-history_graph.html'>
<link rel='import' href='more-info-group.html'>
<link rel='import' href='more-info-light.html'>
<link rel='import' href='more-info-lock.html'>
<link rel='import' href='more-info-media_player.html'>
<link rel='import' href='more-info-script.html'>
<link rel='import' href='more-info-sun.html'>
<link rel='import' href='more-info-updater.html'>
<link rel='import' href='more-info-vacuum.html'>
<link rel='import' href='more-info-input_datetime.html'>
<link rel='import' href='more-info-weather.html'>
import './more-info-alarm_control_panel.js';
import './more-info-automation.js';
import './more-info-camera.js';
import './more-info-climate.js';
import './more-info-configurator.js';
import './more-info-cover.js';
import './more-info-default.js';
import './more-info-fan.js';
import './more-info-group.js';
import './more-info-history_graph.js';
import './more-info-input_datetime.js';
import './more-info-light.js';
import './more-info-lock.js';
import './more-info-media_player.js';
import './more-info-script.js';
import './more-info-sun.js';
import './more-info-updater.js';
import './more-info-vacuum.js';
import './more-info-weather.js';
<script>
class MoreInfoContent extends Polymer.Element {
class MoreInfoContent extends PolymerElement {
static get is() { return 'more-info-content'; }
static get properties() {
@ -69,4 +68,3 @@ class MoreInfoContent extends Polymer.Element {
}
customElements.define(MoreInfoContent.is, MoreInfoContent);
</script>

View File

@ -1,14 +1,19 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../../../bower_components/paper-icon-button/paper-icon-button.html">
import '../../../components/ha-cover-tilt-controls.js';
import '../../../components/ha-paper-slider.js';
import '../../../util/cover-model.js';
<link rel="import" href='../../../components/ha-paper-slider.html'>
<link rel='import' href='../../../util/cover-model.html'>
<link rel='import' href='../../../components/ha-cover-tilt-controls.html'>
<dom-module id='more-info-cover'>
<template>
{
const FEATURE_CLASS_NAMES = {
128: 'has-set_tilt_position',
};
class MoreInfoCover extends PolymerElement {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
.current_position, .tilt {
@ -26,44 +31,26 @@
visibility: hidden !important;
}
</style>
<div class$='[[computeClassNames(stateObj)]]'>
<div class\$="[[computeClassNames(stateObj)]]">
<div class='current_position'>
<div class="current_position">
<div>Position</div>
<ha-paper-slider
min='0' max='100'
value='{{coverPositionSliderValue}}'
step='1' pin
disabled='[[!entityObj.supportsSetPosition]]'
on-change='coverPositionSliderChanged'
ignore-bar-touch></ha-paper-slider>
<ha-paper-slider min="0" max="100" value="{{coverPositionSliderValue}}" step="1" pin="" disabled="[[!entityObj.supportsSetPosition]]" on-change="coverPositionSliderChanged" ignore-bar-touch=""></ha-paper-slider>
</div>
<div class='tilt'>
<div class="tilt">
<div>Tilt position</div>
<div>
<ha-cover-tilt-controls hidden$="[[entityObj.isTiltOnly]]" hass="[[hass]]" state-obj="[[stateObj]]">
<ha-cover-tilt-controls hidden\$="[[entityObj.isTiltOnly]]" hass="[[hass]]" state-obj="[[stateObj]]">
</ha-cover-tilt-controls>
</div>
<ha-paper-slider
min='0' max='100'
value='{{coverTiltPositionSliderValue}}'
step='1' pin
disabled='[[!entityObj.supportsSetTiltPosition]]'
on-change='coverTiltPositionSliderChanged'
ignore-bar-touch></ha-paper-slider>
<ha-paper-slider min="0" max="100" value="{{coverTiltPositionSliderValue}}" step="1" pin="" disabled="[[!entityObj.supportsSetTiltPosition]]" on-change="coverTiltPositionSliderChanged" ignore-bar-touch=""></ha-paper-slider>
</div>
</div>
</template>
</dom-module>
`;
}
<script>
{
const FEATURE_CLASS_NAMES = {
128: 'has-set_tilt_position',
};
class MoreInfoCover extends Polymer.Element {
static get is() { return 'more-info-cover'; }
static get properties() {
@ -125,4 +112,3 @@
customElements.define(MoreInfoCover.is, MoreInfoCover);
}
</script>

View File

@ -1,25 +0,0 @@
<link rel="import" href="../../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../components/ha-attributes.html">
<dom-module id="more-info-default">
<template>
<ha-attributes state-obj="[[stateObj]]"></ha-attributes>
</template>
</dom-module>
<script>
class MoreInfoDefault extends Polymer.Element {
static get is() { return 'more-info-default'; }
static get properties() {
return {
stateObj: {
type: Object,
},
};
}
}
customElements.define(MoreInfoDefault.is, MoreInfoDefault);
</script>

View File

@ -0,0 +1,24 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../components/ha-attributes.js';
class MoreInfoDefault extends PolymerElement {
static get template() {
return html`
<ha-attributes state-obj="[[stateObj]]"></ha-attributes>
`;
}
static get is() { return 'more-info-default'; }
static get properties() {
return {
stateObj: {
type: Object,
},
};
}
}
customElements.define(MoreInfoDefault.is, MoreInfoDefault);

View File

@ -1,19 +1,19 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-icon-button/paper-icon-button.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import '@polymer/paper-toggle-button/paper-toggle-button.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html'>
<link rel='import' href='../../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html'>
<link rel='import' href='../../../../bower_components/paper-listbox/paper-listbox.html'>
<link rel='import' href='../../../../bower_components/paper-item/paper-item.html'>
<link rel='import' href='../../../../bower_components/paper-toggle-button/paper-toggle-button.html'>
<link rel='import' href='../../../../bower_components/paper-icon-button/paper-icon-button.html'>
import '../../../components/ha-attributes.js';
import '../../../util/hass-mixins.js';
<link rel='import' href='../../../../src/util/hass-mixins.html'>
<link rel="import" href="../../../components/ha-attributes.html">
<dom-module id='more-info-fan'>
<template>
<style is='custom-style' include='iron-flex'></style>
class MoreInfoFan extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
.container-speed_list,
.container-direction,
@ -36,48 +36,39 @@
}
</style>
<div class$='[[computeClassNames(stateObj)]]'>
<div class\$="[[computeClassNames(stateObj)]]">
<div class="container-speed_list">
<paper-dropdown-menu label-float dynamic-align label='Speed'>
<paper-listbox slot="dropdown-content" selected='{{speedIndex}}'>
<template is='dom-repeat'
items='[[stateObj.attributes.speed_list]]'>
<paper-dropdown-menu label-float="" dynamic-align="" label="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'>Oscillate</div>
<paper-toggle-button
checked='[[oscillationToggleChecked]]'
on-change='oscillationToggleChanged'>
<div class="container-oscillating">
<div class="center horizontal layout single-row">
<div class="flex">Oscillate</div>
<paper-toggle-button checked="[[oscillationToggleChecked]]" on-change="oscillationToggleChanged">
</paper-toggle-button>
</div>
</div>
<div class='container-direction'>
<div class='direction'>
<div class="container-direction">
<div class="direction">
<div>Direction</div>
<paper-icon-button icon='mdi:rotate-left'
on-click='onDirectionLeft' title='Left'
disabled='[[computeIsRotatingLeft(stateObj)]]'></paper-icon-button>
<paper-icon-button icon='mdi:rotate-right'
on-click='onDirectionRight' title='Right'
disabled='[[computeIsRotatingRight(stateObj)]]'></paper-icon-button>
<paper-icon-button icon="mdi:rotate-left" on-click="onDirectionLeft" title="Left" disabled="[[computeIsRotatingLeft(stateObj)]]"></paper-icon-button>
<paper-icon-button icon="mdi: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>
</template>
</dom-module>
`;
}
<script>
class MoreInfoFan extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'more-info-fan'; }
static get properties() {
@ -173,4 +164,3 @@ class MoreInfoFan extends window.hassMixins.EventsMixin(Polymer.Element) {
}
customElements.define(MoreInfoFan.is, MoreInfoFan);
</script>

View File

@ -1,9 +1,12 @@
<link rel="import" href="../../../../bower_components/polymer/polymer-element.html">
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../state-summary/state-card-content.html">
import '../../../state-summary/state-card-content.js';
<dom-module id="more-info-group">
<template>
class MoreInfoGroup extends PolymerElement {
static get template() {
return html`
<style>
.child-card {
margin-bottom: 8px;
@ -15,16 +18,14 @@
</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>
<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>
</template>
</dom-module>
`;
}
<script>
class MoreInfoGroup extends Polymer.Element {
static get is() { return 'more-info-group'; }
static get properties() {
@ -90,7 +91,7 @@ class MoreInfoGroup extends Polymer.Element {
}
if (!groupDomainStateObj) {
const el = Polymer.dom(this.$.groupedControlDetails);
const el = dom(this.$.groupedControlDetails);
if (el.lastChild) {
el.removeChild(el.lastChild);
}
@ -105,4 +106,3 @@ class MoreInfoGroup extends Polymer.Element {
}
customElements.define(MoreInfoGroup.is, MoreInfoGroup);
</script>

View File

@ -1,35 +0,0 @@
<link rel="import" href="../../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../cards/ha-history_graph-card.html">
<link rel="import" href="../../../components/ha-attributes.html">
<dom-module id="more-info-history_graph">
<template>
<style>
:host {
display: block;
margin-bottom: 6px;
}
</style>
<ha-history_graph-card
hass='[[hass]]'
state-obj='[[stateObj]]'
in-dialog
></ha-graph-card>
<ha-attributes state-obj="[[stateObj]]"></ha-attributes>
</template>
</dom-module>
<script>
class MoreInfoHistoryGraph extends Polymer.Element {
static get is() { return 'more-info-history_graph'; }
static get properties() {
return {
hass: Object,
stateObj: Object,
};
}
}
customElements.define(MoreInfoHistoryGraph.is, MoreInfoHistoryGraph);
</script>

View File

@ -0,0 +1,30 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../../../cards/ha-history_graph-card.js';
import '../../../components/ha-attributes.js';
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>
`;
}
static get is() { return 'more-info-history_graph'; }
static get properties() {
return {
hass: Object,
stateObj: Object,
};
}
}
customElements.define(MoreInfoHistoryGraph.is, MoreInfoHistoryGraph);

View File

@ -1,28 +1,34 @@
<link rel="import" href="../../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../../components/ha-relative-time.html">
<link rel="import" href="../../../../bower_components/vaadin-date-picker/vaadin-date-picker.html">
<link rel="import" href="../../../../bower_components/paper-time-input/paper-time-input.html">
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@polymer/polymer/polymer-legacy.js';
import '@vaadin/vaadin-date-picker/vaadin-date-picker.js';
<dom-module id="more-info-input_datetime">
<template>
<div class$='[[computeClassNames(stateObj)]]'>
<template is="dom-if" if="[[doesHaveDate(stateObj)]]" restamp>
import '../../../components/ha-relative-time.js';
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>
<template is="dom-if" if="[[doesHaveTime(stateObj)]]" restamp="">
<div>
<paper-time-input hour="{{selectedHour}}" min="{{selectedMinute}}" format="24"></paper-time-input>
<paper-input
type='time'
label='time'
value='{{selectedTime}}'
></paper-input>
</div>
</template>
</div>
</template>
</dom-module>
`;
}
<script>
class DatetimeInput extends Polymer.Element {
static get is() {
return 'more-info-input_datetime';
}
@ -43,18 +49,14 @@ class DatetimeInput extends Polymer.Element {
observer: 'stateObjChanged',
},
selectedHour: {
type: Number,
observer: 'dateTimeChanged',
},
selectedMinute: {
type: Number,
observer: 'dateTimeChanged',
},
selectedDate: {
type: String,
observer: 'dateTimeChanged',
},
selectedTime: {
type: String,
observer: 'dateTimeChanged',
}
};
}
@ -66,6 +68,9 @@ class DatetimeInput extends Polymer.Element {
/* Convert the date in the stateObj into a string useable by vaadin-date-picker */
getDateString(stateObj) {
if (stateObj.state === 'unknown') {
return '';
}
var monthFiller;
if (stateObj.attributes.month < 10) {
monthFiller = '0';
@ -91,31 +96,23 @@ class DatetimeInput extends Polymer.Element {
return;
}
var minuteFiller;
var changed = false;
let changed = false;
var serviceData = {
const serviceData = {
entity_id: this.stateObj.entity_id
};
if (this.stateObj.attributes.has_time) {
changed |= (parseInt(this.selectedMinute) !== this.stateObj.attributes.minute);
changed |= (parseInt(this.selectedHour) !== this.stateObj.attributes.hour);
if (this.selectedMinute < 10) {
minuteFiller = '0';
} else {
minuteFiller = '';
}
var timeStr = this.selectedHour + ':' + minuteFiller + this.selectedMinute;
serviceData.time = timeStr;
changed |= this.selectedTime !== `${this.stateObj.attributes.hour}:${this.stateObj.attributes.minute}`;
serviceData.time = this.selectedTime;
}
if (this.stateObj.attributes.has_date) {
const dateInput = this.shadowRoot.querySelector('#dateInput');
const dateValInput = new Date(dateInput.value);
if (this.selectedDate.length === 0) {
return; // Date was not set
}
const dateValInput = new Date(this.selectedDate);
const dateValState = new Date(
this.stateObj.attributes.year,
this.stateObj.attributes.month - 1,
@ -124,10 +121,7 @@ class DatetimeInput extends Polymer.Element {
changed |= (dateValState !== dateValInput);
serviceData.date = dateInput.value;
if (dateInput.value.length < 1) {
return; // Date was not set
}
serviceData.date = this.selectedDate;
}
if (changed) {
@ -165,4 +159,3 @@ class DatetimeInput extends Polymer.Element {
}
customElements.define(DatetimeInput.is, DatetimeInput);
</script>

View File

@ -1,18 +1,26 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
import '@polymer/paper-item/paper-item.js';
import '@polymer/paper-listbox/paper-listbox.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel="import" href="../../../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../../../../bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="../../../../bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="../../../../bower_components/paper-item/paper-item.html">
import '../../../components/ha-attributes.js';
import '../../../components/ha-color-picker.js';
import '../../../components/ha-labeled-slider.js';
import '../../../util/hass-mixins.js';
<link rel='import' href='../../../../src/util/hass-mixins.html'>
<link rel='import' href='../../../components/ha-labeled-slider.html'>
<link rel='import' href='../../../components/ha-color-picker.html'>
<link rel='import' href='../../../components/ha-attributes.html'>
<dom-module id='more-info-light'>
<template>
{
const FEATURE_CLASS_NAMES = {
1: 'has-brightness',
2: 'has-color_temp',
4: 'has-effect_list',
16: 'has-color',
128: 'has-white_value',
};
class MoreInfoLight extends window.hassMixins.EventsMixin(PolymerElement) {
static get template() {
return html`
<style is="custom-style" include="iron-flex"></style>
<style>
.effect_list {
@ -66,48 +74,27 @@
}
</style>
<div class$='[[computeClassNames(stateObj)]]'>
<div class\$="[[computeClassNames(stateObj)]]">
<div class='control brightness'>
<ha-labeled-slider
caption='Brightness' icon='mdi:brightness-5' max='255'
value='{{brightnessSliderValue}}'
on-change='brightnessSliderChanged'
ignore-bar-touch></ha-labeled-slider>
<div class="control brightness">
<ha-labeled-slider caption="Brightness" icon="mdi:brightness-5" max="255" value="{{brightnessSliderValue}}" on-change="brightnessSliderChanged" ignore-bar-touch=""></ha-labeled-slider>
</div>
<div class='control color_temp'>
<ha-labeled-slider
caption='Color Temperature' icon='mdi:thermometer'
min='[[stateObj.attributes.min_mireds]]' max='[[stateObj.attributes.max_mireds]]'
value='{{ctSliderValue}}'
on-change='ctSliderChanged'
ignore-bar-touch></ha-labeled-slider>
<div class="control color_temp">
<ha-labeled-slider caption="Color Temperature" icon="mdi:thermometer" min="[[stateObj.attributes.min_mireds]]" max="[[stateObj.attributes.max_mireds]]" value="{{ctSliderValue}}" on-change="ctSliderChanged" ignore-bar-touch=""></ha-labeled-slider>
</div>
<div class='control white_value'>
<ha-labeled-slider
caption='White Value' icon='mdi:file-word-box' max='255'
value='{{wvSliderValue}}'
on-change='wvSliderChanged'
ignore-bar-touch></ha-labeled-slider>
<div class="control white_value">
<ha-labeled-slider caption="White Value" icon="mdi:file-word-box" max="255" value="{{wvSliderValue}}" on-change="wvSliderChanged" ignore-bar-touch=""></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 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='Effect'>
<div class="control effect_list">
<paper-dropdown-menu label-float="" dynamic-align="" label="Effect">
<paper-listbox slot="dropdown-content" selected="{{effectIndex}}">
<template is='dom-repeat'
items='[[stateObj.attributes.effect_list]]'>
<template is="dom-repeat" items="[[stateObj.attributes.effect_list]]">
<paper-item>[[item]]</paper-item>
</template>
</paper-listbox>
@ -116,19 +103,9 @@
<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>
</template>
</dom-module>
`;
}
<script>
{
const FEATURE_CLASS_NAMES = {
1: 'has-brightness',
2: 'has-color_temp',
4: 'has-effect_list',
16: 'has-color',
128: 'has-white_value',
};
class MoreInfoLight extends window.hassMixins.EventsMixin(Polymer.Element) {
static get is() { return 'more-info-light'; }
static get properties() {
@ -282,4 +259,3 @@
customElements.define(MoreInfoLight.is, MoreInfoLight);
}
</script>

View File

@ -1,28 +1,28 @@
<link rel='import' href='../../../../bower_components/polymer/polymer-element.html'>
import '@polymer/paper-button/paper-button.js';
import '@polymer/paper-input/paper-input.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
<link rel='import' href='../../../../bower_components/paper-button/paper-button.html'>
<link rel='import' href='../../../../bower_components/paper-input/paper-input.html'>
<link rel='import' href='../../../components/ha-attributes.html'>
import '../../../components/ha-attributes.js';
<dom-module id='more-info-lock'>
<template>
class MoreInfoLock extends PolymerElement {
static get template() {
return html`
<style>
paper-input {
display: inline-block;
}
</style>
<div hidden$='[[!stateObj.attributes.code_format]]'>
<paper-input label='code' value='{{enteredCode}}' pattern='[[stateObj.attributes.code_format]]' type='password'></paper-input>
<paper-button on-click='handleUnlockTap' hidden$='[[!isLocked]]'>Unlock</paper-button>
<paper-button on-click='handleLockTap' hidden$=[[isLocked]]>Lock</paper-button>
<div hidden\$="[[!stateObj.attributes.code_format]]">
<paper-input label="code" value="{{enteredCode}}" pattern="[[stateObj.attributes.code_format]]" type="password"></paper-input>
<paper-button on-click="handleUnlockTap" hidden\$="[[!isLocked]]">Unlock</paper-button>
<paper-button on-click="handleLockTap" hidden\$="[[isLocked]]">Lock</paper-button>
</div>
<ha-attributes state-obj='[[stateObj]]' extra-filters='code_format'></ha-attributes>
</template>
</dom-module>
<ha-attributes state-obj="[[stateObj]]" extra-filters="code_format"></ha-attributes>
`;
}
<script>
class MoreInfoLock extends Polymer.Element {
static get is() { return 'more-info-lock'; }
static get properties() {
@ -65,4 +65,3 @@ class MoreInfoLock extends Polymer.Element {
}
customElements.define(MoreInfoLock.is, MoreInfoLock);
</script>

Some files were not shown because too many files have changed in this diff Show More