Add buttons row (#4714)

*  Add buttons row

* refactor to composition

* Add action handler

* address review
This commit is contained in:
Ian Richardson 2020-02-19 03:25:42 -06:00 committed by GitHub
parent 4be1040a14
commit 7046cba1f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 171 additions and 70 deletions

View File

@ -0,0 +1,102 @@
import {
html,
LitElement,
TemplateResult,
customElement,
css,
CSSResult,
queryAll,
property,
} from "lit-element";
import "@material/mwc-ripple";
import "../../../components/entity/state-badge";
import "../../../components/ha-icon";
import { HomeAssistant } from "../../../types";
import { computeTooltip } from "../common/compute-tooltip";
// tslint:disable-next-line: no-duplicate-imports
import { StateBadge } from "../../../components/entity/state-badge";
import { actionHandler } from "../common/directives/action-handler-directive";
import { hasAction } from "../common/has-action";
import { ActionHandlerEvent } from "../../../data/lovelace";
import { handleAction } from "../common/handle-action";
import { EntitiesCardEntityConfig } from "../cards/types";
@customElement("hui-buttons-base")
export class HuiButtonsBase extends LitElement {
@property() public configEntities?: EntitiesCardEntityConfig[];
@queryAll("state-badge") protected _badges!: StateBadge[];
private _hass?: HomeAssistant;
set hass(hass: HomeAssistant) {
this._hass = hass;
this._badges.forEach((badge, index: number) => {
badge.hass = hass;
badge.stateObj = hass.states[this.configEntities![index].entity];
});
}
protected render(): TemplateResult | void {
return html`
${(this.configEntities || []).map((entityConf) => {
const stateObj = this._hass!.states[entityConf.entity];
if (!stateObj) {
return html`<div class='missing'><iron-icon icon="hass:alert"></div>`;
}
return html`
<div>
<state-badge
title=${computeTooltip(this._hass!, entityConf)}
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(entityConf.hold_action),
hasDoubleClick: hasAction(entityConf.double_tap_action),
})}
.config=${entityConf}
.hass=${this._hass}
.stateObj=${stateObj}
.overrideIcon=${entityConf.icon}
.overrideImage=${entityConf.image}
stateColor
tabindex="0"
></state-badge>
<mwc-ripple unbounded></mwc-ripple>
</div>
`;
})}
`;
}
private _handleAction(ev: ActionHandlerEvent) {
const config = (ev.currentTarget as any).config as EntitiesCardEntityConfig;
handleAction(
this,
this.hass!,
{ tap_action: { action: "toggle" }, ...config },
ev.detail.action!
);
}
static get styles(): CSSResult {
return css`
:host {
display: flex;
justify-content: space-evenly;
}
.missing {
color: #fce588;
}
state-badge {
cursor: pointer;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-buttons-base": HuiButtonsBase;
}
}

View File

@ -35,6 +35,7 @@ const LAZY_LOAD_TYPES = {
section: () => import("../special-rows/hui-section-row"),
weblink: () => import("../special-rows/hui-weblink-row"),
cast: () => import("../special-rows/hui-cast-row"),
buttons: () => import("../special-rows/hui-buttons-row"),
};
const DOMAIN_TO_ELEMENT_TYPE = {
_domain_not_found: "text",

View File

@ -42,13 +42,19 @@ export interface CastConfig {
// Hide the row if either unsupported browser or no API available.
hide_if_unavailable: boolean;
}
export interface ButtonsRowConfig {
type: "buttons";
entities: Array<string | EntityConfig>;
}
export type LovelaceRowConfig =
| EntityConfig
| DividerConfig
| SectionConfig
| WeblinkConfig
| CallServiceConfig
| CastConfig;
| CastConfig
| ButtonsRowConfig
| ConditionalRowConfig;
export interface LovelaceRow extends HTMLElement {
hass?: HomeAssistant;

View File

@ -1,28 +1,18 @@
import {
html,
LitElement,
TemplateResult,
customElement,
css,
CSSResult,
queryAll,
LitElement,
html,
property,
TemplateResult,
} from "lit-element";
import "@material/mwc-ripple";
import "../../../components/entity/state-badge";
import "../../../components/ha-card";
import "../../../components/ha-icon";
import "../components/hui-warning-element";
import "../components/hui-buttons-base";
import { HomeAssistant } from "../../../types";
import { LovelaceHeaderFooter } from "../types";
import { ButtonsHeaderFooterConfig } from "./types";
import { EntityConfig } from "../entity-rows/types";
import { processConfigEntities } from "../common/process-config-entities";
import { toggleEntity } from "../common/entity/toggle-entity";
import { computeTooltip } from "../common/compute-tooltip";
// tslint:disable-next-line: no-duplicate-imports
import { StateBadge } from "../../../components/entity/state-badge";
import { EntityConfig } from "../entity-rows/types";
import { HomeAssistant } from "../../../types";
@customElement("hui-buttons-header-footer")
export class HuiButtonsHeaderFooter extends LitElement
@ -31,66 +21,20 @@ export class HuiButtonsHeaderFooter extends LitElement
return { entities: [] };
}
@property() public hass?: HomeAssistant;
private _configEntities?: EntityConfig[];
private _hass?: HomeAssistant;
@queryAll("state-badge") private _badges!: StateBadge[];
public setConfig(config: ButtonsHeaderFooterConfig): void {
this._configEntities = processConfigEntities(config.entities);
this.requestUpdate();
}
set hass(hass: HomeAssistant) {
this._hass = hass;
this._badges.forEach((badge, index: number) => {
badge.hass = hass;
badge.stateObj = hass.states[this._configEntities![index].entity];
});
}
protected render(): TemplateResult | void {
return html`
${(this._configEntities || []).map((entityConf) => {
const stateObj = this._hass!.states[entityConf.entity];
if (!stateObj) {
return html`<div class='missing'><iron-icon icon="hass:alert"></div>`;
}
return html`
<div>
<state-badge
title=${computeTooltip(this._hass!, entityConf)}
@click=${this._toggle}
.hass=${this._hass}
.stateObj=${stateObj}
.overrideIcon=${entityConf.icon}
.overrideImage=${entityConf.image}
stateColor
tabindex="0"
></state-badge>
<mwc-ripple unbounded></mwc-ripple>
</div>
`;
})}
`;
}
private async _toggle(ev) {
await toggleEntity(this._hass!, ev.target.stateObj.entity_id);
}
static get styles(): CSSResult {
return css`
:host {
display: flex;
justify-content: space-evenly;
}
.missing {
color: #fce588;
}
state-badge {
cursor: pointer;
}
<hui-buttons-base
.hass=${this.hass}
.configEntities=${this._configEntities}
></hui-buttons-base>
`;
}
}

View File

@ -1,13 +1,14 @@
import { ActionConfig } from "../../../data/lovelace";
import { struct } from "../common/structs/struct";
import { actionConfigStruct, entitiesConfigStruct } from "../editor/types";
import { EntityConfig } from "../entity-rows/types";
export interface LovelaceHeaderFooterConfig {
type: string;
}
export interface ButtonsHeaderFooterConfig extends LovelaceHeaderFooterConfig {
entities: string[];
entities: Array<string | EntityConfig>;
}
export interface PictureHeaderFooterConfig extends LovelaceHeaderFooterConfig {

View File

@ -0,0 +1,47 @@
import {
customElement,
LitElement,
html,
property,
TemplateResult,
} from "lit-element";
import "../components/hui-buttons-base";
import {
ButtonsRowConfig,
EntityConfig,
LovelaceRow,
} from "../entity-rows/types";
import { processConfigEntities } from "../common/process-config-entities";
import { HomeAssistant } from "../../../types";
@customElement("hui-buttons-row")
export class HuiButtonsRow extends LitElement implements LovelaceRow {
public static getStubConfig(): object {
return { entities: [] };
}
@property() public hass?: HomeAssistant;
private _configEntities?: EntityConfig[];
public setConfig(config: ButtonsRowConfig): void {
this._configEntities = processConfigEntities(config.entities);
this.requestUpdate();
}
protected render(): TemplateResult | void {
return html`
<hui-buttons-base
.hass=${this.hass}
.configEntities=${this._configEntities}
></hui-buttons-base>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-buttons-row": HuiButtonsRow;
}
}