mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 07:16:39 +00:00
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:
parent
22c8e4a455
commit
d9e522e4d7
@ -19,6 +19,8 @@ import { processConfigEntities } from "../common/process-config-entities";
|
|||||||
import { createRowElement } from "../create-element/create-row-element";
|
import { createRowElement } from "../create-element/create-row-element";
|
||||||
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
|
import { EntitiesCardConfig, EntitiesCardEntityConfig } from "./types";
|
||||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
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")
|
@customElement("hui-entities-card")
|
||||||
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||||
@ -96,10 +98,13 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-card>
|
<ha-card>
|
||||||
|
${this._config.header
|
||||||
|
? this.renderHeaderFooter(this._config.header, "header")
|
||||||
|
: ""}
|
||||||
${!this._config.title &&
|
${!this._config.title &&
|
||||||
!this._config.show_header_toggle &&
|
!this._config.show_header_toggle &&
|
||||||
!this._config.icon
|
!this._config.icon
|
||||||
? html``
|
? ""
|
||||||
: html`
|
: html`
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
@ -130,6 +135,9 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
this.renderEntity(entityConf)
|
this.renderEntity(entityConf)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
${this._config.footer
|
||||||
|
? this.renderHeaderFooter(this._config.footer, "footer")
|
||||||
|
: ""}
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -162,6 +170,33 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
|||||||
.icon {
|
.icon {
|
||||||
padding: 0px 18px 0px 8px;
|
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>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { Condition } from "../common/validate-condition";
|
|||||||
import { EntityConfig, EntityFilterEntityConfig } from "../entity-rows/types";
|
import { EntityConfig, EntityFilterEntityConfig } from "../entity-rows/types";
|
||||||
import { LovelaceElementConfig } from "../elements/types";
|
import { LovelaceElementConfig } from "../elements/types";
|
||||||
import { HuiImage } from "../components/hui-image";
|
import { HuiImage } from "../components/hui-image";
|
||||||
|
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||||
|
|
||||||
export interface AlarmPanelCardConfig extends LovelaceCardConfig {
|
export interface AlarmPanelCardConfig extends LovelaceCardConfig {
|
||||||
entity: string;
|
entity: string;
|
||||||
@ -40,6 +41,8 @@ export interface EntitiesCardConfig extends LovelaceCardConfig {
|
|||||||
entities: EntitiesCardEntityConfig[];
|
entities: EntitiesCardEntityConfig[];
|
||||||
theme?: string;
|
theme?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
header?: LovelaceHeaderFooterConfig;
|
||||||
|
footer?: LovelaceHeaderFooterConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityButtonCardConfig extends LovelaceCardConfig {
|
export interface EntityButtonCardConfig extends LovelaceCardConfig {
|
||||||
|
@ -7,10 +7,11 @@ import {
|
|||||||
createErrorCardElement,
|
createErrorCardElement,
|
||||||
createErrorCardConfig,
|
createErrorCardConfig,
|
||||||
} from "../cards/hui-error-card";
|
} from "../cards/hui-error-card";
|
||||||
import { LovelaceCard, LovelaceBadge } from "../types";
|
import { LovelaceCard, LovelaceBadge, LovelaceHeaderFooter } from "../types";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
|
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
|
||||||
import { EntityRow, EntityRowConfig } from "../entity-rows/types";
|
import { EntityRow, EntityRowConfig } from "../entity-rows/types";
|
||||||
|
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||||
|
|
||||||
const CUSTOM_TYPE_PREFIX = "custom:";
|
const CUSTOM_TYPE_PREFIX = "custom:";
|
||||||
const TIMEOUT = 2000;
|
const TIMEOUT = 2000;
|
||||||
@ -20,6 +21,10 @@ interface CreateElementConfigTypes {
|
|||||||
badge: { config: LovelaceBadgeConfig; element: LovelaceBadge };
|
badge: { config: LovelaceBadgeConfig; element: LovelaceBadge };
|
||||||
element: { config: LovelaceElementConfig; element: LovelaceElement };
|
element: { config: LovelaceElementConfig; element: LovelaceElement };
|
||||||
row: { config: EntityRowConfig; element: EntityRow };
|
row: { config: EntityRowConfig; element: EntityRow };
|
||||||
|
"header-footer": {
|
||||||
|
config: LovelaceHeaderFooterConfig;
|
||||||
|
element: LovelaceHeaderFooter;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const _createElement = <T extends keyof CreateElementConfigTypes>(
|
const _createElement = <T extends keyof CreateElementConfigTypes>(
|
||||||
|
@ -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);
|
@ -31,6 +31,7 @@ import {
|
|||||||
EntitiesCardConfig,
|
EntitiesCardConfig,
|
||||||
EntitiesCardEntityConfig,
|
EntitiesCardEntityConfig,
|
||||||
} from "../../cards/types";
|
} from "../../cards/types";
|
||||||
|
import { pictureHeaderFooterConfigStruct } from "../../header-footer/types";
|
||||||
|
|
||||||
const cardConfigStruct = struct({
|
const cardConfigStruct = struct({
|
||||||
type: "string",
|
type: "string",
|
||||||
@ -38,6 +39,8 @@ const cardConfigStruct = struct({
|
|||||||
theme: "string?",
|
theme: "string?",
|
||||||
show_header_toggle: "boolean?",
|
show_header_toggle: "boolean?",
|
||||||
entities: [entitiesConfigStruct],
|
entities: [entitiesConfigStruct],
|
||||||
|
header: struct.optional(pictureHeaderFooterConfigStruct),
|
||||||
|
footer: struct.optional(pictureHeaderFooterConfigStruct),
|
||||||
});
|
});
|
||||||
|
|
||||||
@customElement("hui-entities-card-editor")
|
@customElement("hui-entities-card-editor")
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
22
src/panels/lovelace/header-footer/types.ts
Normal file
22
src/panels/lovelace/header-footer/types.ts
Normal 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),
|
||||||
|
});
|
@ -4,6 +4,7 @@ import {
|
|||||||
LovelaceConfig,
|
LovelaceConfig,
|
||||||
LovelaceBadgeConfig,
|
LovelaceBadgeConfig,
|
||||||
} from "../../data/lovelace";
|
} from "../../data/lovelace";
|
||||||
|
import { LovelaceHeaderFooterConfig } from "./header-footer/types";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
@ -36,6 +37,11 @@ export interface LovelaceCard extends HTMLElement {
|
|||||||
setConfig(config: LovelaceCardConfig): void;
|
setConfig(config: LovelaceCardConfig): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LovelaceHeaderFooter extends HTMLElement {
|
||||||
|
hass?: HomeAssistant;
|
||||||
|
setConfig(config: LovelaceHeaderFooterConfig): void;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LovelaceCardEditor extends HTMLElement {
|
export interface LovelaceCardEditor extends HTMLElement {
|
||||||
hass?: HomeAssistant;
|
hass?: HomeAssistant;
|
||||||
setConfig(config: LovelaceCardConfig): void;
|
setConfig(config: LovelaceCardConfig): void;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user