mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Add basic overview page (#1668)
* Add basic overview page * Add empty state * Show hub devices * Add more info to config entries page * Lint
This commit is contained in:
parent
650d2d7a47
commit
c593e2789c
10
src/common/string/compare.js
Normal file
10
src/common/string/compare.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export default (a, b) => {
|
||||||
|
if (a < b) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a > b) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
@ -129,7 +129,7 @@ class HaSidebar extends LocalizeMixin(PolymerElement) {
|
|||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
|
|
||||||
<paper-listbox attr-for-selected="data-panel" selected="[[hass.panelUrl]]">
|
<paper-listbox attr-for-selected="data-panel" selected="[[hass.panelUrl]]">
|
||||||
<a href='[[_computeUrl(defaultPage)]]' data-panel$="[[defaultPage]]">
|
<a href='[[_computeUrl(defaultPage)]]' data-panel$="[[defaultPage]]" tabindex="-1">
|
||||||
<paper-icon-item>
|
<paper-icon-item>
|
||||||
<ha-icon slot="item-icon" icon="hass:apps"></ha-icon>
|
<ha-icon slot="item-icon" icon="hass:apps"></ha-icon>
|
||||||
<span class="item-text">[[localize('panel.states')]]</span>
|
<span class="item-text">[[localize('panel.states')]]</span>
|
||||||
@ -137,7 +137,7 @@ class HaSidebar extends LocalizeMixin(PolymerElement) {
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<template is="dom-repeat" items="[[panels]]">
|
<template is="dom-repeat" items="[[panels]]">
|
||||||
<a href='[[_computeUrl(item.url_path)]]' data-panel$='[[item.url_path]]'>
|
<a href='[[_computeUrl(item.url_path)]]' data-panel$='[[item.url_path]]' tabindex="-1">
|
||||||
<paper-icon-item>
|
<paper-icon-item>
|
||||||
<ha-icon slot="item-icon" icon="[[item.icon]]"></ha-icon>
|
<ha-icon slot="item-icon" icon="[[item.icon]]"></ha-icon>
|
||||||
<span class="item-text">[[_computePanelName(localize, item)]]</span>
|
<span class="item-text">[[_computePanelName(localize, item)]]</span>
|
||||||
@ -159,14 +159,14 @@ class HaSidebar extends LocalizeMixin(PolymerElement) {
|
|||||||
<div class="subheader">[[localize('ui.sidebar.developer_tools')]]</div>
|
<div class="subheader">[[localize('ui.sidebar.developer_tools')]]</div>
|
||||||
|
|
||||||
<div class="dev-tools layout horizontal justified">
|
<div class="dev-tools layout horizontal justified">
|
||||||
<a href="/dev-service">
|
<a href="/dev-service" tabindex="-1">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:remote"
|
icon="hass:remote"
|
||||||
alt="[[localize('panel.dev-services')]]"
|
alt="[[localize('panel.dev-services')]]"
|
||||||
title="[[localize('panel.dev-services')]]"
|
title="[[localize('panel.dev-services')]]"
|
||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
</a>
|
</a>
|
||||||
<a href="/dev-state">
|
<a href="/dev-state" tabindex="-1">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:code-tags"
|
icon="hass:code-tags"
|
||||||
alt="[[localize('panel.dev-states')]]"
|
alt="[[localize('panel.dev-states')]]"
|
||||||
@ -174,7 +174,7 @@ class HaSidebar extends LocalizeMixin(PolymerElement) {
|
|||||||
|
|
||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
</a>
|
</a>
|
||||||
<a href="/dev-event">
|
<a href="/dev-event" tabindex="-1">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:radio-tower"
|
icon="hass:radio-tower"
|
||||||
alt="[[localize('panel.dev-events')]]"
|
alt="[[localize('panel.dev-events')]]"
|
||||||
@ -182,7 +182,7 @@ class HaSidebar extends LocalizeMixin(PolymerElement) {
|
|||||||
|
|
||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
</a>
|
</a>
|
||||||
<a href="/dev-template">
|
<a href="/dev-template" tabindex="-1">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:file-xml"
|
icon="hass:file-xml"
|
||||||
alt="[[localize('panel.dev-templates')]]"
|
alt="[[localize('panel.dev-templates')]]"
|
||||||
@ -191,7 +191,7 @@ class HaSidebar extends LocalizeMixin(PolymerElement) {
|
|||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
</a>
|
</a>
|
||||||
<template is="dom-if" if="[[_mqttLoaded(hass)]]">
|
<template is="dom-if" if="[[_mqttLoaded(hass)]]">
|
||||||
<a href="/dev-mqtt">
|
<a href="/dev-mqtt" tabindex="-1">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:altimeter"
|
icon="hass:altimeter"
|
||||||
alt="[[localize('panel.dev-mqtt')]]"
|
alt="[[localize('panel.dev-mqtt')]]"
|
||||||
@ -200,7 +200,7 @@ class HaSidebar extends LocalizeMixin(PolymerElement) {
|
|||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
<a href="/dev-info">
|
<a href="/dev-info" tabindex="-1">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:information-outline"
|
icon="hass:information-outline"
|
||||||
alt="[[localize('panel.dev-info')]]"
|
alt="[[localize('panel.dev-info')]]"
|
||||||
|
@ -41,6 +41,9 @@ class HaConfigManager extends
|
|||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
}
|
}
|
||||||
|
ha-state-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<hass-subpage header="Integrations">
|
<hass-subpage header="Integrations">
|
||||||
@ -78,7 +81,7 @@ class HaConfigManager extends
|
|||||||
<div secondary>
|
<div secondary>
|
||||||
<template is='dom-repeat' items='[[_computeConfigEntryEntities(hass, item, _entities)]]'>
|
<template is='dom-repeat' items='[[_computeConfigEntryEntities(hass, item, _entities)]]'>
|
||||||
<span>
|
<span>
|
||||||
<ha-state-icon state-obj='[[item]]'></ha-state-icon>
|
<ha-state-icon state-obj='[[item]]' on-click='_handleMoreInfo'></ha-state-icon>
|
||||||
<paper-tooltip position="bottom">[[_computeStateName(item)]]</paper-tooltip>
|
<paper-tooltip position="bottom">[[_computeStateName(item)]]</paper-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
@ -227,6 +230,10 @@ class HaConfigManager extends
|
|||||||
_computeStateName(stateObj) {
|
_computeStateName(stateObj) {
|
||||||
return computeStateName(stateObj);
|
return computeStateName(stateObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleMoreInfo(ev) {
|
||||||
|
this.fire('hass-more-info', { entityId: ev.model.item.entity_id });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define('ha-config-entries', HaConfigManager);
|
customElements.define('ha-config-entries', HaConfigManager);
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
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 NavigateMixin from '../../../mixins/navigate-mixin.js';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin NavigateMixin
|
|
||||||
*/
|
|
||||||
class HaConfigCloudMenu extends 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="">Connect with Google Home and Amazon Alexa</div>
|
|
||||||
</template>
|
|
||||||
</paper-item-body>
|
|
||||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
|
||||||
</paper-item>
|
|
||||||
</paper-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
isWide: Boolean,
|
|
||||||
account: Object,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_navigate() {
|
|
||||||
this.navigate('/config/cloud');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define('ha-config-cloud-menu', HaConfigCloudMenu);
|
|
@ -1,30 +1,39 @@
|
|||||||
import '@polymer/app-layout/app-header-layout/app-header-layout.js';
|
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-header/app-header.js';
|
||||||
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
|
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
|
||||||
|
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 { html } from '@polymer/polymer/lib/utils/html-tag.js';
|
||||||
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
||||||
|
|
||||||
import '../../../components/ha-menu-button.js';
|
import '../../../components/ha-menu-button.js';
|
||||||
|
|
||||||
import '../ha-config-section.js';
|
import '../ha-config-section.js';
|
||||||
import './ha-config-cloud-menu.js';
|
|
||||||
import './ha-config-entries-menu.js';
|
|
||||||
import './ha-config-users-menu.js';
|
|
||||||
import './ha-config-navigation.js';
|
import './ha-config-navigation.js';
|
||||||
|
|
||||||
import isComponentLoaded from '../../../common/config/is_component_loaded.js';
|
import isComponentLoaded from '../../../common/config/is_component_loaded.js';
|
||||||
import LocalizeMixin from '../../../mixins/localize-mixin.js';
|
import LocalizeMixin from '../../../mixins/localize-mixin.js';
|
||||||
|
import NavigateMixin from '../../../mixins/navigate-mixin.js';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin LocalizeMixin
|
* @appliesMixin LocalizeMixin
|
||||||
*/
|
*/
|
||||||
class HaConfigDashboard extends LocalizeMixin(PolymerElement) {
|
class HaConfigDashboard extends NavigateMixin(LocalizeMixin(PolymerElement)) {
|
||||||
static get template() {
|
static get template() {
|
||||||
return html`
|
return html`
|
||||||
<style include="iron-flex ha-style">
|
<style include="iron-flex ha-style">
|
||||||
.content {
|
.content {
|
||||||
padding-bottom: 32px;
|
padding-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<app-header-layout has-scrolling-region="">
|
<app-header-layout has-scrolling-region="">
|
||||||
@ -41,16 +50,57 @@ class HaConfigDashboard extends LocalizeMixin(PolymerElement) {
|
|||||||
<span slot="introduction">[[localize('ui.panel.config.introduction')]]</span>
|
<span slot="introduction">[[localize('ui.panel.config.introduction')]]</span>
|
||||||
|
|
||||||
<template is="dom-if" if="[[computeIsLoaded(hass, 'cloud')]]">
|
<template is="dom-if" if="[[computeIsLoaded(hass, 'cloud')]]">
|
||||||
<ha-config-cloud-menu hass="[[hass]]" account="[[account]]"></ha-config-cloud-menu>
|
<paper-card>
|
||||||
|
<a href='/config/cloud' tabindex="-1">
|
||||||
|
<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="hass:chevron-right"></iron-icon>
|
||||||
|
</paper-item>
|
||||||
|
</paper-card>
|
||||||
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template is="dom-if" if="[[computeIsLoaded(hass, 'config.config_entries')]]">
|
<paper-card>
|
||||||
<ha-config-entries-menu hass="[[hass]]"></ha-config-entries-menu>
|
<a href='/config/overview' tabindex="-1">
|
||||||
</template>
|
<paper-item>
|
||||||
|
<paper-item-body two-line>
|
||||||
|
Overview
|
||||||
|
<div secondary>Find out how your config, devices and entities relate</div>
|
||||||
|
</paper-item-body>
|
||||||
|
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||||
|
</paper-item>
|
||||||
|
</a>
|
||||||
|
|
||||||
<template is="dom-if" if="[[hass.user.is_owner]]">
|
<a href='/config/integrations' tabindex="-1">
|
||||||
<ha-config-users-menu hass="[[hass]]"></ha-config-users-menu>
|
<paper-item>
|
||||||
</template>
|
<paper-item-body two-line>
|
||||||
|
Integrations
|
||||||
|
<div secondary>Manage connected devices and services</div>
|
||||||
|
</paper-item-body>
|
||||||
|
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||||
|
</paper-item>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href='/config/users' tabindex="-1">
|
||||||
|
<paper-item>
|
||||||
|
<paper-item-body two-line>
|
||||||
|
[[localize('ui.panel.config.users.caption')]]
|
||||||
|
<div secondary>
|
||||||
|
[[localize('ui.panel.config.users.description')]]
|
||||||
|
</div>
|
||||||
|
</paper-item-body>
|
||||||
|
<iron-icon icon="hass:chevron-right"></iron-icon>
|
||||||
|
</paper-item>
|
||||||
|
</a>
|
||||||
|
</paper-card>
|
||||||
|
|
||||||
<ha-config-navigation hass="[[hass]]"></ha-config-navigation>
|
<ha-config-navigation hass="[[hass]]"></ha-config-navigation>
|
||||||
</ha-config-section>
|
</ha-config-section>
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
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 NavigateMixin from '../../../mixins/navigate-mixin.js';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin NavigateMixin
|
|
||||||
*/
|
|
||||||
class HaConfigEntriesMenu extends 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="">Manage connected devices and services</div>
|
|
||||||
</paper-item-body>
|
|
||||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
|
||||||
</paper-item>
|
|
||||||
</paper-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
isWide: Boolean,
|
|
||||||
account: Object,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_navigate() {
|
|
||||||
this.navigate('/config/integrations');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define('ha-config-entries-menu', HaConfigEntriesMenu);
|
|
@ -1,48 +0,0 @@
|
|||||||
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 LocalizeMixin from '../../../mixins/localize-mixin.js';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin LocalizeMixin
|
|
||||||
*/
|
|
||||||
class HaConfigUsersMenu extends LocalizeMixin(PolymerElement) {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<style include="iron-flex">
|
|
||||||
paper-card {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<paper-card>
|
|
||||||
<a href='/config/users'>
|
|
||||||
<paper-item>
|
|
||||||
<paper-item-body two-line>
|
|
||||||
[[localize('ui.panel.config.users.caption')]]
|
|
||||||
<div secondary>
|
|
||||||
[[localize('ui.panel.config.users.description')]]
|
|
||||||
</div>
|
|
||||||
</paper-item-body>
|
|
||||||
<iron-icon icon="hass:chevron-right"></iron-icon>
|
|
||||||
</paper-item>
|
|
||||||
</a>
|
|
||||||
</paper-card>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define('ha-config-users-menu', HaConfigUsersMenu);
|
|
@ -5,19 +5,20 @@ import { PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|||||||
|
|
||||||
import '../../layouts/hass-error-screen.js';
|
import '../../layouts/hass-error-screen.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 './users/ha-config-users.js';
|
|
||||||
import './zwave/ha-config-zwave.js';
|
|
||||||
|
|
||||||
import isComponentLoaded from '../../common/config/is_component_loaded.js';
|
import isComponentLoaded from '../../common/config/is_component_loaded.js';
|
||||||
import NavigateMixin from '../../mixins/navigate-mixin.js';
|
import NavigateMixin from '../../mixins/navigate-mixin.js';
|
||||||
|
|
||||||
|
import(/* webpackChunkName: "panel-config-automation" */ './automation/ha-config-automation.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-cloud" */ './cloud/ha-config-cloud.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-config" */ './config-entries/ha-config-entries.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-core" */ './core/ha-config-core.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-customize" */ './customize/ha-config-customize.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-dashboard" */ './dashboard/ha-config-dashboard.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-script" */ './script/ha-config-script.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-users" */ './users/ha-config-users.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-zwave" */ './zwave/ha-config-zwave.js');
|
||||||
|
import(/* webpackChunkName: "panel-config-overview" */ './overview/ha-config-overview.js');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin NavigateMixin
|
* @appliesMixin NavigateMixin
|
||||||
*/
|
*/
|
||||||
@ -113,6 +114,14 @@ class HaPanelConfig extends NavigateMixin(PolymerElement) {
|
|||||||
hass='[[hass]]'
|
hass='[[hass]]'
|
||||||
></ha-config-users>
|
></ha-config-users>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template is="dom-if" if='[[_equals(_routeData.page, "overview")]]' restamp>
|
||||||
|
<ha-config-overview
|
||||||
|
page-name='overview'
|
||||||
|
route='[[route]]'
|
||||||
|
hass='[[hass]]'
|
||||||
|
></ha-config-overview>
|
||||||
|
</template>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
178
src/panels/config/overview/ha-config-overview.js
Normal file
178
src/panels/config/overview/ha-config-overview.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
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 '../../../layouts/hass-subpage.js';
|
||||||
|
|
||||||
|
import computeStateName from '../../../common/entity/compute_state_name.js';
|
||||||
|
import '../../../components/entity/state-badge.js';
|
||||||
|
|
||||||
|
import './ha-overview-device-row.js';
|
||||||
|
import compare from '../../../common/string/compare.js';
|
||||||
|
|
||||||
|
class HaConfigOverview extends PolymerElement {
|
||||||
|
static get template() {
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
paper-card {
|
||||||
|
display: block;
|
||||||
|
margin: 16px auto;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
.secondary {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.device-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.device {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
.device .name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.device .model,
|
||||||
|
.device .manuf,
|
||||||
|
.device .hub {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.entity-rows {
|
||||||
|
padding-top: 12px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.entity-row {
|
||||||
|
margin: 8px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
state-badge {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
.entity-row .entity-id {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<hass-subpage header="Overview">
|
||||||
|
<div class='content'>
|
||||||
|
<template is='dom-if' if='[[!_configs.length]]'>
|
||||||
|
<paper-card heading='No integrations'>
|
||||||
|
<div class='card-content'>
|
||||||
|
No integrations found. <a href='/config/integrations'>Configure an integration</a>
|
||||||
|
</div>
|
||||||
|
</paper-card>
|
||||||
|
</template>
|
||||||
|
<template is='dom-repeat' items='[[_configs]]' as='configEntry'>
|
||||||
|
<paper-card heading='[[configEntry.title]]'>
|
||||||
|
<div class='card-content'>
|
||||||
|
<!-- <h1>[[configEntry.title]] ([[_computeIntegrationTitle(localize, configEntry.domain)]])</h1> -->
|
||||||
|
|
||||||
|
<template is='dom-repeat' items='[[_computeConfigEntryDevices(configEntry, _devices)]]' as='device'>
|
||||||
|
<ha-overview-device-row
|
||||||
|
hass='[[hass]]'
|
||||||
|
devices='[[_devices]]'
|
||||||
|
device='[[device]]'
|
||||||
|
entities='[[_entities]]'
|
||||||
|
></ha-overview-device-row>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</paper-card>
|
||||||
|
</dom-repeat>
|
||||||
|
</div>
|
||||||
|
</hass-subpage>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
hass: Object,
|
||||||
|
isWide: Boolean,
|
||||||
|
|
||||||
|
_loading: {
|
||||||
|
type: Boolean,
|
||||||
|
computed: '_computeLoading(_configs, _devices, _entities)'
|
||||||
|
},
|
||||||
|
_configs: {
|
||||||
|
type: Array,
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
_devices: {
|
||||||
|
type: Array,
|
||||||
|
value: null,
|
||||||
|
},
|
||||||
|
_entities: {
|
||||||
|
type: Array,
|
||||||
|
value: null,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ready() {
|
||||||
|
super.ready();
|
||||||
|
this._loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
_loadData() {
|
||||||
|
this.hass.callWS({ type: 'config/entity_registry/list' })
|
||||||
|
.then((entities) => { this._entities = entities; });
|
||||||
|
this.hass.callWS({ type: 'config/device_registry/list' })
|
||||||
|
.then((devices) => { this._devices = devices; });
|
||||||
|
this.hass.callApi('get', 'config/config_entries/entry')
|
||||||
|
.then((configs) => {
|
||||||
|
this._configs = configs.sort((conf1, conf2) => compare(conf1.title, conf2.title));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeLoading(configs, devices, entities) {
|
||||||
|
return configs && devices && entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeIntegrationTitle(localize, integration) {
|
||||||
|
return localize(`component.${integration}.config.title`);
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeConfigEntryDevices(configEntry, devices) {
|
||||||
|
return devices.filter(device =>
|
||||||
|
device.config_entries.includes(configEntry.entry_id) &&
|
||||||
|
!device.hub_device_id).sort((dev1, dev2) => compare(dev1.name, dev2.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeDeviceEntities(device, entities) {
|
||||||
|
return entities.filter(entity => entity.device_id === device.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeStateObj(entity, hass) {
|
||||||
|
return hass.states[entity.entity_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeEntityName(entity, hass) {
|
||||||
|
const state = hass.states[entity.entity_id];
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
return computeStateName(state);
|
||||||
|
}
|
||||||
|
return `${entity.name || ''} (entity unavailable)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeDeviceName(devices, deviceId) {
|
||||||
|
const device = devices.find(dev => dev.id === deviceId);
|
||||||
|
return device ? device.name : '(device unavailable)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('ha-config-overview', HaConfigOverview);
|
144
src/panels/config/overview/ha-overview-device-row.js
Normal file
144
src/panels/config/overview/ha-overview-device-row.js
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
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 '../../../layouts/hass-subpage.js';
|
||||||
|
|
||||||
|
import EventsMixin from '../../../mixins/events-mixin.js';
|
||||||
|
import computeStateName from '../../../common/entity/compute_state_name.js';
|
||||||
|
import '../../../components/entity/state-badge.js';
|
||||||
|
import compare from '../../../common/string/compare.js';
|
||||||
|
|
||||||
|
function computeEntityName(hass, entity) {
|
||||||
|
if (entity.name) return entity.name;
|
||||||
|
const state = hass.states[entity.entity_id];
|
||||||
|
return state ? computeStateName(state) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @appliesMixin EventsMixin
|
||||||
|
*/
|
||||||
|
class HaDeviceRow extends EventsMixin(PolymerElement) {
|
||||||
|
static get template() {
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.device-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.device {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
.device .name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.device .model,
|
||||||
|
.device .manuf {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.entity-rows {
|
||||||
|
padding-top: 12px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.entity-row {
|
||||||
|
margin: 8px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
state-badge {
|
||||||
|
margin-right: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.entity-row .entity-id {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
ha-overview-device-row {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div>
|
||||||
|
<div class='device-row'>
|
||||||
|
<div class='device'>
|
||||||
|
<div class='name'>[[device.name]]</div>
|
||||||
|
<div class='model'>[[device.model]]</div>
|
||||||
|
<div class='manuf'>by [[device.manufacturer]]</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='entity-rows'>
|
||||||
|
<template is='dom-repeat' items='[[_computeDeviceEntities(hass, device, entities)]]' as='entity'>
|
||||||
|
<div class='entity-row'>
|
||||||
|
<state-badge
|
||||||
|
state-obj="[[_computeStateObj(entity, hass)]]"
|
||||||
|
on-click='_openMoreInfo'
|
||||||
|
></state-badge>
|
||||||
|
<div>
|
||||||
|
<div class='name'>[[_computeEntityName(entity, hass)]]</div>
|
||||||
|
<div class='entity-id'>[[entity.entity_id]]</div>
|
||||||
|
</div>
|
||||||
|
</div class='entity-row'>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template is='dom-repeat' items='[[_childDevices]]' as='device'>
|
||||||
|
<ha-overview-device-row
|
||||||
|
hass='[[hass]]'
|
||||||
|
devices='[[devices]]'
|
||||||
|
device='[[device]]'
|
||||||
|
entities='[[entities]]'
|
||||||
|
></ha-overview-device-row>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
device: Object,
|
||||||
|
devices: Array,
|
||||||
|
entities: Array,
|
||||||
|
hass: Object,
|
||||||
|
_childDevices: {
|
||||||
|
type: Array,
|
||||||
|
computed: '_computeChildDevices(device, devices)',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeChildDevices(device, devices) {
|
||||||
|
return devices
|
||||||
|
.filter(dev => dev.hub_device_id === device.id)
|
||||||
|
.sort((dev1, dev2) => compare(dev1.name, dev2.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeDeviceEntities(hass, device, entities) {
|
||||||
|
return entities
|
||||||
|
.filter(entity => entity.device_id === device.id)
|
||||||
|
.sort((ent1, ent2) => compare(
|
||||||
|
computeEntityName(hass, ent1) || `zzz${ent1.entity_id}`,
|
||||||
|
computeEntityName(hass, ent2) || `zzz${ent2.entity_id}`
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeStateObj(entity, hass) {
|
||||||
|
return hass.states[entity.entity_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeEntityName(entity, hass) {
|
||||||
|
return computeEntityName(hass, entity) || '(entity unavailable)';
|
||||||
|
}
|
||||||
|
|
||||||
|
_computeDeviceName(devices, deviceId) {
|
||||||
|
const device = devices.find(dev => dev.id === deviceId);
|
||||||
|
return device ? device.name : '(device unavailable)';
|
||||||
|
}
|
||||||
|
|
||||||
|
_openMoreInfo(ev) {
|
||||||
|
this.fire('hass-more-info', { entityId: ev.model.entity.entity_id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('ha-overview-device-row', HaDeviceRow);
|
Loading…
x
Reference in New Issue
Block a user