Add header/footer support to entities card (#4496)

* Add header/footer support to entities card

Oops debug radius

Revert change to hui-picture-card

Remove unused import

* Use new createElement helper
This commit is contained in:
Paulus Schoutsen 2020-01-20 09:13:19 -08:00 committed by Bram Kragten
parent 22c8e4a455
commit d9e522e4d7
8 changed files with 179 additions and 2 deletions

View File

@ -19,6 +19,8 @@ import { processConfigEntities } from "../common/process-config-entities";
import { createRowElement } from "../create-element/create-row-element";
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { createHeaderFooterElement } from "../create-element/create-header-footer-element";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
@customElement("hui-entities-card")
class HuiEntitiesCard extends LitElement implements LovelaceCard {
@ -96,10 +98,13 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
return html`
<ha-card>
${this._config.header
? this.renderHeaderFooter(this._config.header, "header")
: ""}
${!this._config.title &&
!this._config.show_header_toggle &&
!this._config.icon
? html``
? ""
: html`
<div class="card-header">
<div class="name">
@ -130,6 +135,9 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
this.renderEntity(entityConf)
)}
</div>
${this._config.footer
? this.renderHeaderFooter(this._config.footer, "footer")
: ""}
</ha-card>
`;
}
@ -162,6 +170,33 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
.icon {
padding: 0px 18px 0px 8px;
}
.header {
border-top-left-radius: var(--ha-card-border-radius, 2px);
border-top-right-radius: var(--ha-card-border-radius, 2px);
margin-bottom: 16px;
overflow: hidden;
}
.footer {
border-bottom-left-radius: var(--ha-card-border-radius, 2px);
border-bottom-right-radius: var(--ha-card-border-radius, 2px);
margin-top: -16px;
overflow: hidden;
}
`;
}
private renderHeaderFooter(
conf: LovelaceHeaderFooterConfig,
className: string
): TemplateResult {
const element = createHeaderFooterElement(conf);
if (this._hass) {
element.hass = this._hass;
}
return html`
<div class=${className}>${element}</div>
`;
}

View File

@ -3,6 +3,7 @@ import { Condition } from "../common/validate-condition";
import { EntityConfig, EntityFilterEntityConfig } from "../entity-rows/types";
import { LovelaceElementConfig } from "../elements/types";
import { HuiImage } from "../components/hui-image";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
export interface AlarmPanelCardConfig extends LovelaceCardConfig {
entity: string;
@ -40,6 +41,8 @@ export interface EntitiesCardConfig extends LovelaceCardConfig {
entities: EntitiesCardEntityConfig[];
theme?: string;
icon?: string;
header?: LovelaceHeaderFooterConfig;
footer?: LovelaceHeaderFooterConfig;
}
export interface EntityButtonCardConfig extends LovelaceCardConfig {

View File

@ -7,10 +7,11 @@ import {
createErrorCardElement,
createErrorCardConfig,
} from "../cards/hui-error-card";
import { LovelaceCard, LovelaceBadge } from "../types";
import { LovelaceCard, LovelaceBadge, LovelaceHeaderFooter } from "../types";
import { fireEvent } from "../../../common/dom/fire_event";
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
import { EntityRow, EntityRowConfig } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
const CUSTOM_TYPE_PREFIX = "custom:";
const TIMEOUT = 2000;
@ -20,6 +21,10 @@ interface CreateElementConfigTypes {
badge: { config: LovelaceBadgeConfig; element: LovelaceBadge };
element: { config: LovelaceElementConfig; element: LovelaceElement };
row: { config: EntityRowConfig; element: EntityRow };
"header-footer": {
config: LovelaceHeaderFooterConfig;
element: LovelaceHeaderFooter;
};
}
const _createElement = <T extends keyof CreateElementConfigTypes>(

View File

@ -0,0 +1,8 @@
import "../header-footer/hui-picture-header-footer";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
import { createLovelaceElement } from "./create-element-base";
const SPECIAL_TYPES = new Set(["picture"]);
export const createHeaderFooterElement = (config: LovelaceHeaderFooterConfig) =>
createLovelaceElement("header-footer", config, SPECIAL_TYPES);

View File

@ -31,6 +31,7 @@ import {
EntitiesCardConfig,
EntitiesCardEntityConfig,
} from "../../cards/types";
import { pictureHeaderFooterConfigStruct } from "../../header-footer/types";
const cardConfigStruct = struct({
type: "string",
@ -38,6 +39,8 @@ const cardConfigStruct = struct({
theme: "string?",
show_header_toggle: "boolean?",
entities: [entitiesConfigStruct],
header: struct.optional(pictureHeaderFooterConfigStruct),
footer: struct.optional(pictureHeaderFooterConfigStruct),
});
@customElement("hui-entities-card-editor")

View File

@ -0,0 +1,95 @@
import {
html,
LitElement,
TemplateResult,
customElement,
property,
css,
CSSResult,
} from "lit-element";
import "../../../components/ha-card";
import { LovelaceHeaderFooter } from "../types";
import { HomeAssistant } from "../../../types";
import { classMap } from "lit-html/directives/class-map";
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 { ifDefined } from "lit-html/directives/if-defined";
import { PictureHeaderFooterConfig } from "./types";
@customElement("hui-picture-header-footer")
export class HuiPictureHeaderFooter extends LitElement
implements LovelaceHeaderFooter {
public static getStubConfig(): object {
return {
image:
"https://www.home-assistant.io/images/merchandise/shirt-frontpage.png",
tap_action: { action: "none" },
hold_action: { action: "none" },
};
}
public hass?: HomeAssistant;
@property() protected _config?: PictureHeaderFooterConfig;
public setConfig(config: PictureHeaderFooterConfig): void {
if (!config || !config.image) {
throw new Error("Invalid Configuration: 'image' required");
}
this._config = config;
}
protected render(): TemplateResult | void {
if (!this._config || !this.hass) {
return html``;
}
const clickable = Boolean(
this._config.tap_action || this._config.hold_action
);
return html`
<img
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config!.hold_action),
hasDoubleClick: hasAction(this._config!.double_tap_action),
})}
tabindex=${ifDefined(clickable ? 0 : undefined)}
class="${classMap({
clickable,
})}"
<img
src="${this.hass.hassUrl(this._config.image)}"
/>
`;
}
static get styles(): CSSResult {
return css`
img.clickable {
cursor: pointer;
}
img {
display: block;
width: 100%;
}
`;
}
private _handleAction(ev: ActionHandlerEvent) {
handleAction(this, this.hass!, this._config!, ev.detail.action!);
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-picture-header-footer": HuiPictureHeaderFooter;
}
}

View File

@ -0,0 +1,22 @@
import { ActionConfig } from "../../../data/lovelace";
import { struct } from "../common/structs/struct";
import { actionConfigStruct } from "../editor/types";
export interface LovelaceHeaderFooterConfig {
type: string;
}
export interface PictureHeaderFooterConfig extends LovelaceHeaderFooterConfig {
image: string;
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
}
export const pictureHeaderFooterConfigStruct = struct({
type: "string",
image: "string",
tap_action: struct.optional(actionConfigStruct),
hold_action: struct.optional(actionConfigStruct),
double_tap_action: struct.optional(actionConfigStruct),
});

View File

@ -4,6 +4,7 @@ import {
LovelaceConfig,
LovelaceBadgeConfig,
} from "../../data/lovelace";
import { LovelaceHeaderFooterConfig } from "./header-footer/types";
declare global {
// tslint:disable-next-line
@ -36,6 +37,11 @@ export interface LovelaceCard extends HTMLElement {
setConfig(config: LovelaceCardConfig): void;
}
export interface LovelaceHeaderFooter extends HTMLElement {
hass?: HomeAssistant;
setConfig(config: LovelaceHeaderFooterConfig): void;
}
export interface LovelaceCardEditor extends HTMLElement {
hass?: HomeAssistant;
setConfig(config: LovelaceCardConfig): void;