mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 16:56:35 +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"),
|
||||
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",
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
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