mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 03:36:44 +00:00
Migrate more-info-dialog to mwc and Lit (#6345)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
e1cb549b28
commit
b429fe8254
@ -2,7 +2,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|||||||
/* eslint-plugin-disable lit */
|
/* eslint-plugin-disable lit */
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import "../../../src/dialogs/more-info/controls/more-info-content";
|
import "../../../src/dialogs/more-info/more-info-content";
|
||||||
import "../../../src/state-summary/state-card-content";
|
import "../../../src/state-summary/state-card-content";
|
||||||
|
|
||||||
class DemoMoreInfo extends PolymerElement {
|
class DemoMoreInfo extends PolymerElement {
|
||||||
|
@ -3,7 +3,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import { SUPPORT_BRIGHTNESS } from "../../../src/data/light";
|
import { SUPPORT_BRIGHTNESS } from "../../../src/data/light";
|
||||||
import "../../../src/dialogs/more-info/controls/more-info-content";
|
import "../../../src/dialogs/more-info/more-info-content";
|
||||||
import { getEntity } from "../../../src/fake_data/entity";
|
import { getEntity } from "../../../src/fake_data/entity";
|
||||||
import { provideHass } from "../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||||
import "../components/demo-more-infos";
|
import "../components/demo-more-infos";
|
||||||
|
@ -23,6 +23,12 @@ export const createCloseHeading = (hass: HomeAssistant, title: string) => html`
|
|||||||
|
|
||||||
@customElement("ha-dialog")
|
@customElement("ha-dialog")
|
||||||
export class HaDialog extends MwcDialog {
|
export class HaDialog extends MwcDialog {
|
||||||
|
protected renderHeading() {
|
||||||
|
return html`<slot name="heading">
|
||||||
|
${super.renderHeading()}
|
||||||
|
</slot>`;
|
||||||
|
}
|
||||||
|
|
||||||
protected static get styles(): CSSResult[] {
|
protected static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
style,
|
style,
|
||||||
@ -43,6 +49,9 @@ export class HaDialog extends MwcDialog {
|
|||||||
.mdc-dialog .mdc-dialog__content {
|
.mdc-dialog .mdc-dialog__content {
|
||||||
padding: var(--dialog-content-padding, 20px 24px);
|
padding: var(--dialog-content-padding, 20px 24px);
|
||||||
}
|
}
|
||||||
|
.mdc-dialog .mdc-dialog__surface {
|
||||||
|
min-height: var(--mdc-dialog-min-height, auto);
|
||||||
|
}
|
||||||
.header_button {
|
.header_button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
|
@ -10,6 +10,7 @@ class HaLabeledSlider extends PolymerElement {
|
|||||||
<style>
|
<style>
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
@ -17,13 +18,17 @@ class HaLabeledSlider extends PolymerElement {
|
|||||||
opacity: var(--dark-primary-opacity);
|
opacity: var(--dark-primary-opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.slider-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
ha-icon {
|
ha-icon {
|
||||||
float: left;
|
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
opacity: var(--dark-secondary-opacity);
|
opacity: var(--dark-secondary-opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-paper-slider {
|
ha-paper-slider {
|
||||||
|
flex-grow: 1;
|
||||||
background-image: var(--ha-slider-background);
|
background-image: var(--ha-slider-background);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,155 +0,0 @@
|
|||||||
import "@polymer/paper-dialog-behavior/paper-dialog-shared-styles";
|
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|
||||||
/* eslint-plugin-disable lit */
|
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
import { computeStateDomain } from "../common/entity/compute_state_domain";
|
|
||||||
import DialogMixin from "../mixins/dialog-mixin";
|
|
||||||
import "../styles/polymer-ha-style-dialog";
|
|
||||||
import "./more-info/more-info-controls";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin DialogMixin
|
|
||||||
*/
|
|
||||||
class HaMoreInfoDialog extends DialogMixin(PolymerElement) {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<style include="ha-style-dialog paper-dialog-shared-styles">
|
|
||||||
:host {
|
|
||||||
font-size: 14px;
|
|
||||||
width: 365px;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
more-info-controls {
|
|
||||||
--more-info-header-background: var(--secondary-background-color);
|
|
||||||
--more-info-header-color: var(--primary-text-color);
|
|
||||||
--ha-more-info-app-toolbar-title: {
|
|
||||||
/* Design guideline states 24px, changed to 16 to align with state info */
|
|
||||||
margin-left: 16px;
|
|
||||||
line-height: 1.3em;
|
|
||||||
max-height: 2.6em;
|
|
||||||
overflow: hidden;
|
|
||||||
/* webkit and blink still support simple multiline text-overflow */
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* overrule the ha-style-dialog max-height on small screens */
|
|
||||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
|
||||||
more-info-controls {
|
|
||||||
--more-info-header-background: var(--app-header-background-color);
|
|
||||||
--more-info-header-color: var(--app-header-text-color, white);
|
|
||||||
}
|
|
||||||
:host {
|
|
||||||
width: 100% !important;
|
|
||||||
border-radius: 0px;
|
|
||||||
position: fixed !important;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
:host::before {
|
|
||||||
content: "";
|
|
||||||
position: fixed;
|
|
||||||
z-index: -1;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
right: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
background-color: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:host([data-domain="camera"]) {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host([data-domain="history_graph"]),
|
|
||||||
:host([large]) {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<more-info-controls
|
|
||||||
class="no-padding"
|
|
||||||
hass="[[hass]]"
|
|
||||||
state-obj="[[stateObj]]"
|
|
||||||
dialog-element="[[_dialogElement()]]"
|
|
||||||
large="{{large}}"
|
|
||||||
></more-info-controls>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
stateObj: {
|
|
||||||
type: Object,
|
|
||||||
computed: "_computeStateObj(hass)",
|
|
||||||
observer: "_stateObjChanged",
|
|
||||||
},
|
|
||||||
|
|
||||||
large: {
|
|
||||||
type: Boolean,
|
|
||||||
reflectToAttribute: true,
|
|
||||||
observer: "_largeChanged",
|
|
||||||
},
|
|
||||||
|
|
||||||
dataDomain: {
|
|
||||||
computed: "_computeDomain(stateObj)",
|
|
||||||
reflectToAttribute: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static get observers() {
|
|
||||||
return ["_dialogOpenChanged(opened)"];
|
|
||||||
}
|
|
||||||
|
|
||||||
_dialogElement() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeDomain(stateObj) {
|
|
||||||
return stateObj ? computeStateDomain(stateObj) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeStateObj(hass) {
|
|
||||||
return hass.states[hass.moreInfoEntityId] || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async _stateObjChanged(newVal) {
|
|
||||||
if (!newVal) {
|
|
||||||
this.setProperties({
|
|
||||||
opened: false,
|
|
||||||
large: false,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestAnimationFrame(() =>
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
// allow dialog to render content before showing it so it will be
|
|
||||||
// positioned correctly.
|
|
||||||
this.opened = true;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_dialogOpenChanged(newVal) {
|
|
||||||
if (!newVal && this.stateObj) {
|
|
||||||
this.fire("hass-more-info", { entityId: null });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_equals(a, b) {
|
|
||||||
return a === b;
|
|
||||||
}
|
|
||||||
|
|
||||||
_largeChanged() {
|
|
||||||
this.notifyResize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customElements.define("ha-more-info-dialog", HaMoreInfoDialog);
|
|
@ -28,6 +28,12 @@ class MoreInfoLight extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
return html`
|
return html`
|
||||||
<style include="iron-flex"></style>
|
<style include="iron-flex"></style>
|
||||||
<style>
|
<style>
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.effect_list,
|
.effect_list,
|
||||||
.brightness,
|
.brightness,
|
||||||
.color_temp,
|
.color_temp,
|
||||||
@ -50,7 +56,6 @@ class MoreInfoLight extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
|
|
||||||
.segmentationContainer {
|
.segmentationContainer {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-color-picker {
|
ha-color-picker {
|
||||||
@ -118,10 +123,22 @@ class MoreInfoLight extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
--ha-color-picker-marker-bordercolor: white;
|
--ha-color-picker-marker-bordercolor: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.control {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.is-unavailable .control {
|
.is-unavailable .control {
|
||||||
max-height: 0px;
|
max-height: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ha-attributes {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-paper-dropdown-menu {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
paper-item {
|
paper-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@ -275,7 +292,10 @@ class MoreInfoLight extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
computeClassNames(stateObj) {
|
computeClassNames(stateObj) {
|
||||||
const classes = [featureClassNames(stateObj, FEATURE_CLASS_NAMES)];
|
const classes = [
|
||||||
|
"content",
|
||||||
|
featureClassNames(stateObj, FEATURE_CLASS_NAMES),
|
||||||
|
];
|
||||||
if (stateObj && stateObj.state === "on") {
|
if (stateObj && stateObj.state === "on") {
|
||||||
classes.push("is-on");
|
classes.push("is-on");
|
||||||
}
|
}
|
||||||
|
313
src/dialogs/more-info/ha-more-info-dialog.ts
Normal file
313
src/dialogs/more-info/ha-more-info-dialog.ts
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
import "@material/mwc-button";
|
||||||
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
|
import "../../components/ha-icon-button";
|
||||||
|
import "../../components/ha-dialog";
|
||||||
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
|
import { DOMAINS_MORE_INFO_NO_HISTORY } from "../../common/const";
|
||||||
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
|
import { navigate } from "../../common/navigate";
|
||||||
|
import "../../components/state-history-charts";
|
||||||
|
import { removeEntityRegistryEntry } from "../../data/entity_registry";
|
||||||
|
import { showEntityEditorDialog } from "../../panels/config/entities/show-dialog-entity-editor";
|
||||||
|
import "../../state-summary/state-card-content";
|
||||||
|
import { showConfirmationDialog } from "../generic/show-dialog-box";
|
||||||
|
import "./more-info-content";
|
||||||
|
import {
|
||||||
|
customElement,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
} from "lit-element";
|
||||||
|
import { haStyleDialog } from "../../resources/styles";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { getRecentWithCache } from "../../data/cached-history";
|
||||||
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
|
import { mdiClose, mdiSettings, mdiPencil } from "@mdi/js";
|
||||||
|
import { HistoryResult } from "../../data/history";
|
||||||
|
|
||||||
|
const DOMAINS_NO_INFO = ["camera", "configurator", "history_graph"];
|
||||||
|
const EDITABLE_DOMAINS_WITH_ID = ["scene", "automation"];
|
||||||
|
const EDITABLE_DOMAINS = ["script"];
|
||||||
|
|
||||||
|
@customElement("ha-more-info-dialog")
|
||||||
|
export class MoreInfoDialog extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ type: Boolean, reflect: true }) public large = false;
|
||||||
|
|
||||||
|
@internalProperty() private _stateHistory?: HistoryResult;
|
||||||
|
|
||||||
|
private _historyRefreshInterval?: number;
|
||||||
|
|
||||||
|
protected updated(changedProperties) {
|
||||||
|
super.updated(changedProperties);
|
||||||
|
if (!changedProperties.has("hass")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const oldHass = changedProperties.get("hass");
|
||||||
|
if (oldHass && oldHass.moreInfoEntityId === this.hass.moreInfoEntityId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.hass.moreInfoEntityId) {
|
||||||
|
this.large = false;
|
||||||
|
this._stateHistory = undefined;
|
||||||
|
if (this._computeShowHistoryComponent(this.hass.moreInfoEntityId)) {
|
||||||
|
this._getStateHistory();
|
||||||
|
clearInterval(this._historyRefreshInterval);
|
||||||
|
this._historyRefreshInterval = window.setInterval(() => {
|
||||||
|
this._getStateHistory();
|
||||||
|
}, 60 * 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._stateHistory = undefined;
|
||||||
|
clearInterval(this._historyRefreshInterval);
|
||||||
|
this._historyRefreshInterval = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this.hass.moreInfoEntityId) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
const entityId = this.hass.moreInfoEntityId;
|
||||||
|
const stateObj = this.hass.states[entityId];
|
||||||
|
const domain = computeDomain(entityId);
|
||||||
|
|
||||||
|
if (!stateObj) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-dialog
|
||||||
|
open
|
||||||
|
@closed=${this._close}
|
||||||
|
.heading=${true}
|
||||||
|
hideActions
|
||||||
|
data-domain=${domain}
|
||||||
|
>
|
||||||
|
<app-toolbar slot="heading">
|
||||||
|
<mwc-icon-button
|
||||||
|
.label=${this.hass.localize("ui.dialogs.more_info_control.dismiss")}
|
||||||
|
dialogAction="cancel"
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>
|
||||||
|
<div class="main-title" main-title @click=${this._enlarge}>
|
||||||
|
${computeStateName(stateObj)}
|
||||||
|
</div>
|
||||||
|
${this.hass.user!.is_admin
|
||||||
|
? html`<mwc-icon-button
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.settings"
|
||||||
|
)}
|
||||||
|
@click=${this._gotoSettings}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiSettings}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>`
|
||||||
|
: ""}
|
||||||
|
${this.hass.user!.is_admin &&
|
||||||
|
((EDITABLE_DOMAINS_WITH_ID.includes(domain) &&
|
||||||
|
stateObj.attributes.id) ||
|
||||||
|
EDITABLE_DOMAINS.includes(domain))
|
||||||
|
? html` <mwc-icon-button
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.edit"
|
||||||
|
)}
|
||||||
|
@click=${this._gotoEdit}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiPencil}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>`
|
||||||
|
: ""}
|
||||||
|
</app-toolbar>
|
||||||
|
<div class="content">
|
||||||
|
${DOMAINS_NO_INFO.includes(domain)
|
||||||
|
? ""
|
||||||
|
: html`
|
||||||
|
<state-card-content
|
||||||
|
.stateObj=${stateObj}
|
||||||
|
.hass=${this.hass}
|
||||||
|
in-dialog
|
||||||
|
></state-card-content>
|
||||||
|
`}
|
||||||
|
${this._computeShowHistoryComponent(entityId)
|
||||||
|
? html`
|
||||||
|
<state-history-charts
|
||||||
|
.hass=${this.hass}
|
||||||
|
.historyData=${this._stateHistory}
|
||||||
|
up-to-now
|
||||||
|
.isLoadingData=${!this._stateHistory}
|
||||||
|
></state-history-charts>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
<more-info-content
|
||||||
|
.stateObj=${stateObj}
|
||||||
|
.hass=${this.hass}
|
||||||
|
></more-info-content>
|
||||||
|
|
||||||
|
${stateObj.attributes.restored
|
||||||
|
? html`${this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.restored.not_provided"
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.restored.remove_intro"
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
<mwc-button class="warning" @click=${this._removeEntity}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.restored.remove_action"
|
||||||
|
)}
|
||||||
|
</mwc-button>`
|
||||||
|
: ""}
|
||||||
|
</div>
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _enlarge() {
|
||||||
|
this.large = !this.large;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _getStateHistory(): Promise<void> {
|
||||||
|
if (!this.hass.moreInfoEntityId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._stateHistory = await getRecentWithCache(
|
||||||
|
this.hass!,
|
||||||
|
this.hass.moreInfoEntityId,
|
||||||
|
{
|
||||||
|
refresh: 60,
|
||||||
|
cacheKey: `more_info.${this.hass.moreInfoEntityId}`,
|
||||||
|
hoursToShow: 24,
|
||||||
|
},
|
||||||
|
this.hass!.localize,
|
||||||
|
this.hass!.language
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeShowHistoryComponent(entityId) {
|
||||||
|
return (
|
||||||
|
isComponentLoaded(this.hass, "history") &&
|
||||||
|
!DOMAINS_MORE_INFO_NO_HISTORY.includes(computeDomain(entityId))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _removeEntity() {
|
||||||
|
const entityId = this.hass.moreInfoEntityId!;
|
||||||
|
showConfirmationDialog(this, {
|
||||||
|
title: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.restored.confirm_remove_title"
|
||||||
|
),
|
||||||
|
text: this.hass.localize(
|
||||||
|
"ui.dialogs.more_info_control.restored.confirm_remove_text"
|
||||||
|
),
|
||||||
|
confirmText: this.hass.localize("ui.common.yes"),
|
||||||
|
dismissText: this.hass.localize("ui.common.no"),
|
||||||
|
confirm: () => {
|
||||||
|
removeEntityRegistryEntry(this.hass, entityId);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _gotoSettings() {
|
||||||
|
showEntityEditorDialog(this, {
|
||||||
|
entity_id: this.hass.moreInfoEntityId!,
|
||||||
|
});
|
||||||
|
fireEvent(this, "hass-more-info", { entityId: null });
|
||||||
|
}
|
||||||
|
|
||||||
|
private _gotoEdit() {
|
||||||
|
const stateObj = this.hass.states[this.hass.moreInfoEntityId!];
|
||||||
|
const domain = computeDomain(this.hass.moreInfoEntityId!);
|
||||||
|
navigate(
|
||||||
|
this,
|
||||||
|
`/config/${domain}/edit/${
|
||||||
|
EDITABLE_DOMAINS_WITH_ID.includes(domain)
|
||||||
|
? stateObj.attributes.id
|
||||||
|
: stateObj.entity_id
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _close() {
|
||||||
|
fireEvent(this, "hass-more-info", { entityId: null });
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return [
|
||||||
|
haStyleDialog,
|
||||||
|
css`
|
||||||
|
app-toolbar {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
background-color: var(--secondary-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
app-toolbar [main-title] {
|
||||||
|
/* Design guideline states 24px, changed to 16 to align with state info */
|
||||||
|
margin-left: 16px;
|
||||||
|
line-height: 1.3em;
|
||||||
|
max-height: 2.6em;
|
||||||
|
overflow: hidden;
|
||||||
|
/* webkit and blink still support simple multiline text-overflow */
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
|
app-toolbar {
|
||||||
|
background-color: var(--app-header-background-color);
|
||||||
|
color: var(--app-header-text-color, white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (min-width: 451px) and (min-height: 501px) {
|
||||||
|
ha-dialog {
|
||||||
|
--mdc-dialog-max-width: 90vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
app-toolbar {
|
||||||
|
max-width: 368px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
width: 352px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-title {
|
||||||
|
pointer-events: auto;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-dialog[data-domain="camera"] .content {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-dialog[data-domain="history_graph"] .content,
|
||||||
|
:host([large]) .content {
|
||||||
|
width: calc(90vw - 48px);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([large]) app-toolbar {
|
||||||
|
max-width: calc(90vw - 32px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state-history-charts {
|
||||||
|
margin-top: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-dialog[data-domain="camera"] {
|
||||||
|
--dialog-content-padding: 0;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +1,31 @@
|
|||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { property, PropertyValues, UpdatingElement } from "lit-element";
|
import { property, PropertyValues, UpdatingElement } from "lit-element";
|
||||||
import dynamicContentUpdater from "../../../common/dom/dynamic_content_updater";
|
import dynamicContentUpdater from "../../common/dom/dynamic_content_updater";
|
||||||
import { stateMoreInfoType } from "../../../common/entity/state_more_info_type";
|
import { stateMoreInfoType } from "../../common/entity/state_more_info_type";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "./more-info-alarm_control_panel";
|
import "./controls/more-info-alarm_control_panel";
|
||||||
import "./more-info-automation";
|
import "./controls/more-info-automation";
|
||||||
import "./more-info-camera";
|
import "./controls/more-info-camera";
|
||||||
import "./more-info-climate";
|
import "./controls/more-info-climate";
|
||||||
import "./more-info-configurator";
|
import "./controls/more-info-configurator";
|
||||||
import "./more-info-counter";
|
import "./controls/more-info-counter";
|
||||||
import "./more-info-cover";
|
import "./controls/more-info-cover";
|
||||||
import "./more-info-default";
|
import "./controls/more-info-default";
|
||||||
import "./more-info-fan";
|
import "./controls/more-info-fan";
|
||||||
import "./more-info-group";
|
import "./controls/more-info-group";
|
||||||
import "./more-info-history_graph";
|
import "./controls/more-info-history_graph";
|
||||||
import "./more-info-humidifier";
|
import "./controls/more-info-humidifier";
|
||||||
import "./more-info-input_datetime";
|
import "./controls/more-info-input_datetime";
|
||||||
import "./more-info-light";
|
import "./controls/more-info-light";
|
||||||
import "./more-info-lock";
|
import "./controls/more-info-lock";
|
||||||
import "./more-info-media_player";
|
import "./controls/more-info-media_player";
|
||||||
import "./more-info-person";
|
import "./controls/more-info-person";
|
||||||
import "./more-info-script";
|
import "./controls/more-info-script";
|
||||||
import "./more-info-sun";
|
import "./controls/more-info-sun";
|
||||||
import "./more-info-timer";
|
import "./controls/more-info-timer";
|
||||||
import "./more-info-vacuum";
|
import "./controls/more-info-vacuum";
|
||||||
import "./more-info-water_heater";
|
import "./controls/more-info-water_heater";
|
||||||
import "./more-info-weather";
|
import "./controls/more-info-weather";
|
||||||
|
|
||||||
class MoreInfoContent extends UpdatingElement {
|
class MoreInfoContent extends UpdatingElement {
|
||||||
@property() public hass?: HomeAssistant;
|
@property() public hass?: HomeAssistant;
|
@ -1,284 +0,0 @@
|
|||||||
import "@material/mwc-button";
|
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
|
||||||
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
|
||||||
import "../../components/ha-icon-button";
|
|
||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|
||||||
/* eslint-plugin-disable lit */
|
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
|
||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
|
||||||
import { DOMAINS_MORE_INFO_NO_HISTORY } from "../../common/const";
|
|
||||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
|
||||||
import { navigate } from "../../common/navigate";
|
|
||||||
import { computeRTL } from "../../common/util/compute_rtl";
|
|
||||||
import "../../components/state-history-charts";
|
|
||||||
import { removeEntityRegistryEntry } from "../../data/entity_registry";
|
|
||||||
import "../../data/ha-state-history-data";
|
|
||||||
import { EventsMixin } from "../../mixins/events-mixin";
|
|
||||||
import LocalizeMixin from "../../mixins/localize-mixin";
|
|
||||||
import { showEntityEditorDialog } from "../../panels/config/entities/show-dialog-entity-editor";
|
|
||||||
import "../../styles/polymer-ha-style-dialog";
|
|
||||||
import "../../state-summary/state-card-content";
|
|
||||||
import { showConfirmationDialog } from "../generic/show-dialog-box";
|
|
||||||
import "./controls/more-info-content";
|
|
||||||
|
|
||||||
const DOMAINS_NO_INFO = ["camera", "configurator", "history_graph"];
|
|
||||||
const EDITABLE_DOMAINS_WITH_ID = ["scene", "automation"];
|
|
||||||
const EDITABLE_DOMAINS = ["script"];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @appliesMixin EventsMixin
|
|
||||||
*/
|
|
||||||
class MoreInfoControls extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|
||||||
static get template() {
|
|
||||||
return html`
|
|
||||||
<style include="ha-style-dialog">
|
|
||||||
app-toolbar {
|
|
||||||
color: var(--more-info-header-color);
|
|
||||||
background-color: var(--more-info-header-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
app-toolbar [main-title] {
|
|
||||||
@apply --ha-more-info-app-toolbar-title;
|
|
||||||
}
|
|
||||||
|
|
||||||
state-card-content {
|
|
||||||
display: block;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
state-history-charts {
|
|
||||||
max-width: 100%;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (min-width: 451px) and (min-height: 501px) {
|
|
||||||
.main-title {
|
|
||||||
pointer-events: auto;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
paper-dialog-scrollable {
|
|
||||||
padding-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
mwc-button.warning {
|
|
||||||
--mdc-theme-primary: var(--error-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host([domain="camera"]) paper-dialog-scrollable {
|
|
||||||
margin: 0 -24px -21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host([rtl]) app-toolbar {
|
|
||||||
direction: rtl;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<app-toolbar>
|
|
||||||
<ha-icon-button
|
|
||||||
aria-label$="[[localize('ui.dialogs.more_info_control.dismiss')]]"
|
|
||||||
icon="hass:close"
|
|
||||||
dialog-dismiss
|
|
||||||
></ha-icon-button>
|
|
||||||
<div class="main-title" main-title="" on-click="enlarge">
|
|
||||||
[[_computeStateName(stateObj)]]
|
|
||||||
</div>
|
|
||||||
<template is="dom-if" if="[[hass.user.is_admin]]">
|
|
||||||
<ha-icon-button
|
|
||||||
aria-label$="[[localize('ui.dialogs.more_info_control.settings')]]"
|
|
||||||
icon="hass:settings"
|
|
||||||
on-click="_gotoSettings"
|
|
||||||
></ha-icon-button>
|
|
||||||
</template>
|
|
||||||
<template is="dom-if" if="[[_computeEdit(hass, stateObj)]]">
|
|
||||||
<ha-icon-button
|
|
||||||
aria-label$="[[localize('ui.dialogs.more_info_control.edit')]]"
|
|
||||||
icon="hass:pencil"
|
|
||||||
on-click="_gotoEdit"
|
|
||||||
></ha-icon-button>
|
|
||||||
</template>
|
|
||||||
</app-toolbar>
|
|
||||||
|
|
||||||
<template is="dom-if" if="[[_computeShowStateInfo(stateObj)]]" restamp="">
|
|
||||||
<state-card-content
|
|
||||||
state-obj="[[stateObj]]"
|
|
||||||
hass="[[hass]]"
|
|
||||||
in-dialog=""
|
|
||||||
></state-card-content>
|
|
||||||
</template>
|
|
||||||
<paper-dialog-scrollable dialog-element="[[dialogElement]]">
|
|
||||||
<template
|
|
||||||
is="dom-if"
|
|
||||||
if="[[_computeShowHistoryComponent(hass, stateObj)]]"
|
|
||||||
restamp=""
|
|
||||||
>
|
|
||||||
<ha-state-history-data
|
|
||||||
hass="[[hass]]"
|
|
||||||
filter-type="recent-entity"
|
|
||||||
entity-id="[[stateObj.entity_id]]"
|
|
||||||
data="{{_stateHistory}}"
|
|
||||||
is-loading="{{_stateHistoryLoading}}"
|
|
||||||
cache-config="[[_cacheConfig]]"
|
|
||||||
></ha-state-history-data>
|
|
||||||
<state-history-charts
|
|
||||||
hass="[[hass]]"
|
|
||||||
history-data="[[_stateHistory]]"
|
|
||||||
is-loading-data="[[_stateHistoryLoading]]"
|
|
||||||
up-to-now
|
|
||||||
></state-history-charts>
|
|
||||||
</template>
|
|
||||||
<more-info-content
|
|
||||||
state-obj="[[stateObj]]"
|
|
||||||
hass="[[hass]]"
|
|
||||||
></more-info-content>
|
|
||||||
<template
|
|
||||||
is="dom-if"
|
|
||||||
if="[[_computeShowRestored(stateObj)]]"
|
|
||||||
restamp=""
|
|
||||||
>
|
|
||||||
[[localize('ui.dialogs.more_info_control.restored.not_provided')]] <br />
|
|
||||||
[[localize('ui.dialogs.more_info_control.restored.remove_intro')]] <br />
|
|
||||||
<mwc-button class="warning" on-click="_removeEntity">[[localize('ui.dialogs.more_info_control.restored.remove_action')]]</mwc-buttom>
|
|
||||||
</template>
|
|
||||||
</paper-dialog-scrollable>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
hass: Object,
|
|
||||||
|
|
||||||
stateObj: {
|
|
||||||
type: Object,
|
|
||||||
observer: "_stateObjChanged",
|
|
||||||
},
|
|
||||||
|
|
||||||
dialogElement: Object,
|
|
||||||
registryEntry: Object,
|
|
||||||
|
|
||||||
domain: {
|
|
||||||
type: String,
|
|
||||||
reflectToAttribute: true,
|
|
||||||
computed: "_computeDomain(stateObj)",
|
|
||||||
},
|
|
||||||
|
|
||||||
_stateHistory: Object,
|
|
||||||
_stateHistoryLoading: Boolean,
|
|
||||||
|
|
||||||
large: {
|
|
||||||
type: Boolean,
|
|
||||||
value: false,
|
|
||||||
notify: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
_cacheConfig: {
|
|
||||||
type: Object,
|
|
||||||
value: {
|
|
||||||
refresh: 60,
|
|
||||||
cacheKey: null,
|
|
||||||
hoursToShow: 24,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rtl: {
|
|
||||||
type: Boolean,
|
|
||||||
reflectToAttribute: true,
|
|
||||||
computed: "_computeRTL(hass)",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
enlarge() {
|
|
||||||
this.large = !this.large;
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeShowStateInfo(stateObj) {
|
|
||||||
return !stateObj || !DOMAINS_NO_INFO.includes(computeStateDomain(stateObj));
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeShowRestored(stateObj) {
|
|
||||||
return stateObj && stateObj.attributes.restored;
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeShowHistoryComponent(hass, stateObj) {
|
|
||||||
return (
|
|
||||||
hass &&
|
|
||||||
stateObj &&
|
|
||||||
isComponentLoaded(hass, "history") &&
|
|
||||||
!DOMAINS_MORE_INFO_NO_HISTORY.includes(computeStateDomain(stateObj))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeDomain(stateObj) {
|
|
||||||
return stateObj ? computeStateDomain(stateObj) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeStateName(stateObj) {
|
|
||||||
return stateObj ? computeStateName(stateObj) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeEdit(hass, stateObj) {
|
|
||||||
const domain = this._computeDomain(stateObj);
|
|
||||||
return (
|
|
||||||
stateObj &&
|
|
||||||
hass.user.is_admin &&
|
|
||||||
((EDITABLE_DOMAINS_WITH_ID.includes(domain) && stateObj.attributes.id) ||
|
|
||||||
EDITABLE_DOMAINS.includes(domain))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_stateObjChanged(newVal) {
|
|
||||||
if (!newVal) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._cacheConfig.cacheKey !== `more_info.${newVal.entity_id}`) {
|
|
||||||
this._cacheConfig = {
|
|
||||||
...this._cacheConfig,
|
|
||||||
cacheKey: `more_info.${newVal.entity_id}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_removeEntity() {
|
|
||||||
showConfirmationDialog(this, {
|
|
||||||
title: this.localize(
|
|
||||||
"ui.dialogs.more_info_control.restored.confirm_remove_title"
|
|
||||||
),
|
|
||||||
text: this.localize(
|
|
||||||
"ui.dialogs.more_info_control.restored.confirm_remove_text"
|
|
||||||
),
|
|
||||||
confirmText: this.localize("ui.common.yes"),
|
|
||||||
dismissText: this.localize("ui.common.no"),
|
|
||||||
confirm: () =>
|
|
||||||
removeEntityRegistryEntry(this.hass, this.stateObj.entity_id),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_gotoSettings() {
|
|
||||||
showEntityEditorDialog(this, {
|
|
||||||
entity_id: this.stateObj.entity_id,
|
|
||||||
});
|
|
||||||
this.fire("hass-more-info", { entityId: null });
|
|
||||||
}
|
|
||||||
|
|
||||||
_gotoEdit() {
|
|
||||||
const domain = this._computeDomain(this.stateObj);
|
|
||||||
navigate(
|
|
||||||
this,
|
|
||||||
`/config/${domain}/edit/${
|
|
||||||
EDITABLE_DOMAINS_WITH_ID.includes(domain)
|
|
||||||
? this.stateObj.attributes.id
|
|
||||||
: this.stateObj.entity_id
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
this.fire("hass-more-info", { entityId: null });
|
|
||||||
}
|
|
||||||
|
|
||||||
_computeRTL(hass) {
|
|
||||||
return computeRTL(hass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
customElements.define("more-info-controls", MoreInfoControls);
|
|
@ -147,19 +147,14 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getStateHistory(): void {
|
private async _getStateHistory(): Promise<void> {
|
||||||
getRecentWithCache(
|
this._stateHistory = getRecentWithCache(
|
||||||
this.hass!,
|
this.hass!,
|
||||||
this._cacheConfig!.cacheKey,
|
this._cacheConfig!.cacheKey,
|
||||||
this._cacheConfig!,
|
this._cacheConfig!,
|
||||||
this.hass!.localize,
|
this.hass!.localize,
|
||||||
this.hass!.language
|
this.hass!.language
|
||||||
).then((stateHistory) => {
|
);
|
||||||
this._stateHistory = {
|
|
||||||
...this._stateHistory,
|
|
||||||
...stateHistory,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _clearInterval(): void {
|
private _clearInterval(): void {
|
||||||
|
@ -241,7 +241,9 @@ export const haStyleDialog = css`
|
|||||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
ha-dialog {
|
ha-dialog {
|
||||||
--mdc-dialog-min-width: 100vw;
|
--mdc-dialog-min-width: 100vw;
|
||||||
--mdc-dialog-max-height: 100vh;
|
--mdc-dialog-max-width: 100vw;
|
||||||
|
--mdc-dialog-min-height: 100%;
|
||||||
|
--mdc-dialog-max-height: 100%;
|
||||||
--mdc-shape-medium: 0px;
|
--mdc-shape-medium: 0px;
|
||||||
--vertial-align-dialog: flex-end;
|
--vertial-align-dialog: flex-end;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
|||||||
|
|
||||||
// Load it once we are having the initial rendering done.
|
// Load it once we are having the initial rendering done.
|
||||||
import(
|
import(
|
||||||
/* webpackChunkName: "more-info-dialog" */ "../dialogs/ha-more-info-dialog"
|
/* webpackChunkName: "more-info-dialog" */ "../dialogs/more-info/ha-more-info-dialog"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user