mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
✨ Add buttons row (#4714)
* ✨ Add buttons row
* refactor to composition
* Add action handler
* address review
This commit is contained in:
parent
4be1040a14
commit
7046cba1f7
102
src/panels/lovelace/components/hui-buttons-base.ts
Normal file
102
src/panels/lovelace/components/hui-buttons-base.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ const LAZY_LOAD_TYPES = {
|
|||||||
section: () => import("../special-rows/hui-section-row"),
|
section: () => import("../special-rows/hui-section-row"),
|
||||||
weblink: () => import("../special-rows/hui-weblink-row"),
|
weblink: () => import("../special-rows/hui-weblink-row"),
|
||||||
cast: () => import("../special-rows/hui-cast-row"),
|
cast: () => import("../special-rows/hui-cast-row"),
|
||||||
|
buttons: () => import("../special-rows/hui-buttons-row"),
|
||||||
};
|
};
|
||||||
const DOMAIN_TO_ELEMENT_TYPE = {
|
const DOMAIN_TO_ELEMENT_TYPE = {
|
||||||
_domain_not_found: "text",
|
_domain_not_found: "text",
|
||||||
|
@ -42,13 +42,19 @@ export interface CastConfig {
|
|||||||
// Hide the row if either unsupported browser or no API available.
|
// Hide the row if either unsupported browser or no API available.
|
||||||
hide_if_unavailable: boolean;
|
hide_if_unavailable: boolean;
|
||||||
}
|
}
|
||||||
|
export interface ButtonsRowConfig {
|
||||||
|
type: "buttons";
|
||||||
|
entities: Array<string | EntityConfig>;
|
||||||
|
}
|
||||||
export type LovelaceRowConfig =
|
export type LovelaceRowConfig =
|
||||||
| EntityConfig
|
| EntityConfig
|
||||||
| DividerConfig
|
| DividerConfig
|
||||||
| SectionConfig
|
| SectionConfig
|
||||||
| WeblinkConfig
|
| WeblinkConfig
|
||||||
| CallServiceConfig
|
| CallServiceConfig
|
||||||
| CastConfig;
|
| CastConfig
|
||||||
|
| ButtonsRowConfig
|
||||||
|
| ConditionalRowConfig;
|
||||||
|
|
||||||
export interface LovelaceRow extends HTMLElement {
|
export interface LovelaceRow extends HTMLElement {
|
||||||
hass?: HomeAssistant;
|
hass?: HomeAssistant;
|
||||||
|
@ -1,28 +1,18 @@
|
|||||||
import {
|
import {
|
||||||
html,
|
|
||||||
LitElement,
|
|
||||||
TemplateResult,
|
|
||||||
customElement,
|
customElement,
|
||||||
css,
|
LitElement,
|
||||||
CSSResult,
|
html,
|
||||||
queryAll,
|
property,
|
||||||
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "@material/mwc-ripple";
|
|
||||||
|
|
||||||
import "../../../components/entity/state-badge";
|
import "../components/hui-buttons-base";
|
||||||
import "../../../components/ha-card";
|
|
||||||
import "../../../components/ha-icon";
|
|
||||||
import "../components/hui-warning-element";
|
|
||||||
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import { LovelaceHeaderFooter } from "../types";
|
import { LovelaceHeaderFooter } from "../types";
|
||||||
import { ButtonsHeaderFooterConfig } from "./types";
|
import { ButtonsHeaderFooterConfig } from "./types";
|
||||||
import { EntityConfig } from "../entity-rows/types";
|
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
import { toggleEntity } from "../common/entity/toggle-entity";
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
import { computeTooltip } from "../common/compute-tooltip";
|
import { HomeAssistant } from "../../../types";
|
||||||
// tslint:disable-next-line: no-duplicate-imports
|
|
||||||
import { StateBadge } from "../../../components/entity/state-badge";
|
|
||||||
|
|
||||||
@customElement("hui-buttons-header-footer")
|
@customElement("hui-buttons-header-footer")
|
||||||
export class HuiButtonsHeaderFooter extends LitElement
|
export class HuiButtonsHeaderFooter extends LitElement
|
||||||
@ -31,66 +21,20 @@ export class HuiButtonsHeaderFooter extends LitElement
|
|||||||
return { entities: [] };
|
return { entities: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property() public hass?: HomeAssistant;
|
||||||
private _configEntities?: EntityConfig[];
|
private _configEntities?: EntityConfig[];
|
||||||
private _hass?: HomeAssistant;
|
|
||||||
@queryAll("state-badge") private _badges!: StateBadge[];
|
|
||||||
|
|
||||||
public setConfig(config: ButtonsHeaderFooterConfig): void {
|
public setConfig(config: ButtonsHeaderFooterConfig): void {
|
||||||
this._configEntities = processConfigEntities(config.entities);
|
this._configEntities = processConfigEntities(config.entities);
|
||||||
this.requestUpdate();
|
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 {
|
protected render(): TemplateResult | void {
|
||||||
return html`
|
return html`
|
||||||
${(this._configEntities || []).map((entityConf) => {
|
<hui-buttons-base
|
||||||
const stateObj = this._hass!.states[entityConf.entity];
|
.hass=${this.hass}
|
||||||
if (!stateObj) {
|
.configEntities=${this._configEntities}
|
||||||
return html`<div class='missing'><iron-icon icon="hass:alert"></div>`;
|
></hui-buttons-base>
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { ActionConfig } from "../../../data/lovelace";
|
import { ActionConfig } from "../../../data/lovelace";
|
||||||
import { struct } from "../common/structs/struct";
|
import { struct } from "../common/structs/struct";
|
||||||
import { actionConfigStruct, entitiesConfigStruct } from "../editor/types";
|
import { actionConfigStruct, entitiesConfigStruct } from "../editor/types";
|
||||||
|
import { EntityConfig } from "../entity-rows/types";
|
||||||
|
|
||||||
export interface LovelaceHeaderFooterConfig {
|
export interface LovelaceHeaderFooterConfig {
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonsHeaderFooterConfig extends LovelaceHeaderFooterConfig {
|
export interface ButtonsHeaderFooterConfig extends LovelaceHeaderFooterConfig {
|
||||||
entities: string[];
|
entities: Array<string | EntityConfig>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PictureHeaderFooterConfig extends LovelaceHeaderFooterConfig {
|
export interface PictureHeaderFooterConfig extends LovelaceHeaderFooterConfig {
|
||||||
|
47
src/panels/lovelace/special-rows/hui-buttons-row.ts
Normal file
47
src/panels/lovelace/special-rows/hui-buttons-row.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user