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>

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