mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 16:26:43 +00:00
Add buttons header-footer (#4601)
* Add buttons header-footer * Simplify * Update src/panels/lovelace/header-footer/hui-buttons-header-footer.ts Co-Authored-By: Ian Richardson <iantrich@gmail.com> * Address comments Co-authored-by: Ian Richardson <iantrich@gmail.com>
This commit is contained in:
parent
95ba1fd0cb
commit
82fb622904
@ -20,7 +20,7 @@ import { computeActiveState } from "../../common/entity/compute_active_state";
|
||||
import { ifDefined } from "lit-html/directives/if-defined";
|
||||
import { iconColorCSS } from "../../common/style/icon_color_css";
|
||||
|
||||
class StateBadge extends LitElement {
|
||||
export class StateBadge extends LitElement {
|
||||
public hass?: HomeAssistant;
|
||||
@property() public stateObj?: HassEntity;
|
||||
@property() public overrideIcon?: string;
|
||||
|
@ -14,7 +14,11 @@ import "../components/hui-entities-toggle";
|
||||
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceRow } from "../entity-rows/types";
|
||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import {
|
||||
LovelaceCard,
|
||||
LovelaceCardEditor,
|
||||
LovelaceHeaderFooter,
|
||||
} from "../types";
|
||||
import { processConfigEntities } from "../common/process-config-entities";
|
||||
import { createRowElement } from "../create-element/create-row-element";
|
||||
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
|
||||
@ -48,6 +52,11 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||
(element as LovelaceRow).hass = hass;
|
||||
}
|
||||
);
|
||||
this.shadowRoot!.querySelectorAll(".header-footer > *").forEach(
|
||||
(element: unknown) => {
|
||||
(element as LovelaceHeaderFooter).hass = hass;
|
||||
}
|
||||
);
|
||||
const entitiesToggle = this.shadowRoot!.querySelector(
|
||||
"hui-entities-toggle"
|
||||
);
|
||||
@ -135,6 +144,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||
this.renderEntity(entityConf)
|
||||
)}
|
||||
</div>
|
||||
|
||||
${this._config.footer
|
||||
? this.renderHeaderFooter(this._config.footer, "footer")
|
||||
: ""}
|
||||
@ -192,7 +202,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||
element.hass = this._hass;
|
||||
}
|
||||
return html`
|
||||
<div class=${className}>${element}</div>
|
||||
<div class=${"header-footer " + className}>${element}</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceElementConfig } from "../elements/types";
|
||||
import { ActionConfig } from "../../../data/lovelace";
|
||||
|
||||
interface Config extends LovelaceElementConfig {
|
||||
interface Config {
|
||||
entity?: string;
|
||||
title?: string;
|
||||
tap_action?: ActionConfig;
|
||||
@ -30,6 +29,10 @@ export const computeTooltip = (hass: HomeAssistant, config: Config): string => {
|
||||
: config.entity;
|
||||
}
|
||||
|
||||
if (!config.tap_action && !config.hold_action) {
|
||||
return stateName;
|
||||
}
|
||||
|
||||
const tapTooltip = config.tap_action
|
||||
? computeActionTooltip(hass, stateName, config.tap_action, false)
|
||||
: "";
|
||||
|
@ -1,8 +1,9 @@
|
||||
import "../header-footer/hui-picture-header-footer";
|
||||
import "../header-footer/hui-buttons-header-footer";
|
||||
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||
import { createLovelaceElement } from "./create-element-base";
|
||||
|
||||
const SPECIAL_TYPES = new Set(["picture"]);
|
||||
const SPECIAL_TYPES = new Set(["picture", "buttons"]);
|
||||
|
||||
export const createHeaderFooterElement = (config: LovelaceHeaderFooterConfig) =>
|
||||
createLovelaceElement("header-footer", config, SPECIAL_TYPES);
|
||||
|
@ -31,7 +31,7 @@ import {
|
||||
EntitiesCardConfig,
|
||||
EntitiesCardEntityConfig,
|
||||
} from "../../cards/types";
|
||||
import { pictureHeaderFooterConfigStruct } from "../../header-footer/types";
|
||||
import { headerFooterConfigStructs } from "../../header-footer/types";
|
||||
|
||||
const cardConfigStruct = struct({
|
||||
type: "string",
|
||||
@ -39,8 +39,8 @@ const cardConfigStruct = struct({
|
||||
theme: "string?",
|
||||
show_header_toggle: "boolean?",
|
||||
entities: [entitiesConfigStruct],
|
||||
header: struct.optional(pictureHeaderFooterConfigStruct),
|
||||
footer: struct.optional(pictureHeaderFooterConfigStruct),
|
||||
header: struct.optional(headerFooterConfigStructs),
|
||||
footer: struct.optional(headerFooterConfigStructs),
|
||||
});
|
||||
|
||||
@customElement("hui-entities-card-editor")
|
||||
|
102
src/panels/lovelace/header-footer/hui-buttons-header-footer.ts
Normal file
102
src/panels/lovelace/header-footer/hui-buttons-header-footer.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import {
|
||||
html,
|
||||
LitElement,
|
||||
TemplateResult,
|
||||
customElement,
|
||||
css,
|
||||
CSSResult,
|
||||
queryAll,
|
||||
} 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 { 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";
|
||||
|
||||
@customElement("hui-buttons-header-footer")
|
||||
export class HuiButtonsHeaderFooter extends LitElement
|
||||
implements LovelaceHeaderFooter {
|
||||
public static getStubConfig(): object {
|
||||
return { entities: [] };
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-buttons-header-footer": HuiButtonsHeaderFooter;
|
||||
}
|
||||
}
|
@ -1,11 +1,15 @@
|
||||
import { ActionConfig } from "../../../data/lovelace";
|
||||
import { struct } from "../common/structs/struct";
|
||||
import { actionConfigStruct } from "../editor/types";
|
||||
import { actionConfigStruct, entitiesConfigStruct } from "../editor/types";
|
||||
|
||||
export interface LovelaceHeaderFooterConfig {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface ButtonsHeaderFooterConfig extends LovelaceHeaderFooterConfig {
|
||||
entities: string[];
|
||||
}
|
||||
|
||||
export interface PictureHeaderFooterConfig extends LovelaceHeaderFooterConfig {
|
||||
image: string;
|
||||
tap_action?: ActionConfig;
|
||||
@ -20,3 +24,13 @@ export const pictureHeaderFooterConfigStruct = struct({
|
||||
hold_action: struct.optional(actionConfigStruct),
|
||||
double_tap_action: struct.optional(actionConfigStruct),
|
||||
});
|
||||
|
||||
export const buttonsHeaderFooterConfigStruct = struct({
|
||||
type: "string",
|
||||
entities: [entitiesConfigStruct],
|
||||
});
|
||||
|
||||
export const headerFooterConfigStructs = struct.union([
|
||||
pictureHeaderFooterConfigStruct,
|
||||
buttonsHeaderFooterConfigStruct,
|
||||
]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user