Skip to content

Commit

Permalink
Add visibility option to heading entities (#22064)
Browse files Browse the repository at this point in the history
* Add visibility option to heading entity

* Fix types
  • Loading branch information
piitaya authored Sep 24, 2024
1 parent c4a700a commit c30e4a6
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 7 deletions.
70 changes: 69 additions & 1 deletion src/panels/lovelace/cards/heading/hui-heading-entity.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
import {
CSSResultGroup,
LitElement,
PropertyValues,
css,
html,
nothing,
} from "lit";
import { customElement, property } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one";
import { MediaQueriesListener } from "../../../../common/dom/media_query";
import "../../../../components/ha-card";
import "../../../../components/ha-icon";
import "../../../../components/ha-icon-next";
Expand All @@ -12,6 +20,10 @@ import { HomeAssistant } from "../../../../types";
import { actionHandler } from "../../common/directives/action-handler-directive";
import { handleAction } from "../../common/handle-action";
import { hasAction } from "../../common/has-action";
import {
attachConditionMediaQueriesListeners,
checkConditionsMet,
} from "../../common/validate-condition";
import type { HeadingEntityConfig } from "../types";

@customElement("hui-heading-entity")
Expand All @@ -20,6 +32,10 @@ export class HuiHeadingEntity extends LitElement {

@property({ attribute: false }) public config!: HeadingEntityConfig | string;

@property({ type: Boolean }) public preview = false;

private _listeners: MediaQueriesListener[] = [];

private _handleAction(ev: ActionHandlerEvent) {
const config: HeadingEntityConfig = {
tap_action: {
Expand All @@ -46,6 +62,58 @@ export class HuiHeadingEntity extends LitElement {
}
);

public disconnectedCallback() {
super.disconnectedCallback();
this._clearMediaQueries();
}

public connectedCallback() {
super.connectedCallback();
this._listenMediaQueries();
this._updateVisibility();
}

protected update(changedProps: PropertyValues<typeof this>): void {
super.update(changedProps);
if (changedProps.has("hass") || changedProps.has("preview")) {
this._updateVisibility();
}
}

private _updateVisibility(forceVisible?: boolean) {
const config = this._config(this.config);
const visible =
forceVisible ||
this.preview ||
!config.visibility ||
checkConditionsMet(config.visibility, this.hass);
this.toggleAttribute("hidden", !visible);
}

private _clearMediaQueries() {
this._listeners.forEach((unsub) => unsub());
this._listeners = [];
}

private _listenMediaQueries() {
const config = this._config(this.config);
if (!config?.visibility) {
return;
}
const conditions = config.visibility;
const hasOnlyMediaQuery =
conditions.length === 1 &&
conditions[0].condition === "screen" &&
!!conditions[0].media_query;

this._listeners = attachConditionMediaQueriesListeners(
config.visibility,
(matches) => {
this._updateVisibility(hasOnlyMediaQuery && matches);
}
);
}

protected render() {
const config = this._config(this.config);

Expand Down
8 changes: 7 additions & 1 deletion src/panels/lovelace/cards/hui-heading-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export class HuiHeadingCard extends LitElement implements LovelaceCard {

@property({ attribute: false }) public hass?: HomeAssistant;

@property({ type: Boolean }) public preview = false;

@state() private _config?: HeadingCardConfig;

public setConfig(config: HeadingCardConfig): void {
Expand Down Expand Up @@ -94,7 +96,11 @@ export class HuiHeadingCard extends LitElement implements LovelaceCard {
<div class="entities">
${this._config.entities.map(
(config) => html`
<hui-heading-entity .config=${config} .hass=${this.hass}>
<hui-heading-entity
.config=${config}
.hass=${this.hass}
.preview=${this.preview}
>
</hui-heading-entity>
`
)}
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/cards/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ export interface HeadingEntityConfig {
content?: string | string[];
icon?: string;
tap_action?: ActionConfig;
visibility?: Condition[];
}

export interface HeadingCardConfig extends LovelaceCardConfig {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { mdiGestureTap } from "@mdi/js";
import { mdiEye, mdiGestureTap } from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { array, assert, object, optional, string, union } from "superstruct";
import {
any,
array,
assert,
object,
optional,
string,
union,
} from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-expansion-panel";
import "../../../../components/ha-form/ha-form";
import type {
HaFormSchema,
SchemaUnion,
} from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
import type { HeadingCardConfig, HeadingEntityConfig } from "../../cards/types";
import type { HeadingEntityConfig } from "../../cards/types";
import { Condition } from "../../common/validate-condition";
import type { LovelaceGenericElementEditor } from "../../types";
import "../conditions/ha-card-conditions-editor";
import { configElementStyle } from "../config-elements/config-elements-style";
import { actionConfigStruct } from "../structs/action-struct";

Expand All @@ -20,6 +31,7 @@ const entityConfigStruct = object({
content: optional(union([string(), array(string())])),
icon: optional(string()),
tap_action: optional(actionConfigStruct),
visibility: optional(array(any())),
});

@customElement("hui-heading-entity-editor")
Expand All @@ -29,6 +41,8 @@ export class HuiHeadingEntityEditor
{
@property({ attribute: false }) public hass?: HomeAssistant;

@property({ type: Boolean }) public preview = false;

@state() private _config?: HeadingEntityConfig;

public setConfig(config: HeadingEntityConfig): void {
Expand Down Expand Up @@ -79,6 +93,7 @@ export class HuiHeadingEntityEditor

const schema = this._schema();

const conditions = this._config.visibility ?? [];
return html`
<ha-form
.hass=${this.hass}
Expand All @@ -87,6 +102,27 @@ export class HuiHeadingEntityEditor
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
<ha-expansion-panel outlined>
<h3 slot="header">
<ha-svg-icon .path=${mdiEye}></ha-svg-icon>
${this.hass!.localize(
"ui.panel.lovelace.editor.card.heading.entity_config.visibility"
)}
</h3>
<div class="content">
<p class="intro">
${this.hass.localize(
"ui.panel.lovelace.editor.card.heading.entity_config.visibility_explanation"
)}
</p>
<ha-card-conditions-editor
.hass=${this.hass}
.conditions=${conditions}
@value-changed=${this._conditionChanged}
>
</ha-card-conditions-editor>
</div>
</ha-expansion-panel>
`;
}

Expand All @@ -96,11 +132,30 @@ export class HuiHeadingEntityEditor
return;
}

const config = ev.detail.value as HeadingCardConfig;
const config = ev.detail.value as HeadingEntityConfig;

fireEvent(this, "config-changed", { config });
}

private _conditionChanged(ev: CustomEvent): void {
ev.stopPropagation();
if (!this._config || !this.hass) {
return;
}

const conditions = ev.detail.value as Condition[];

const newConfig: HeadingEntityConfig = {
...this._config,
visibility: conditions,
};
if (newConfig.visibility?.length === 0) {
delete newConfig.visibility;
}

fireEvent(this, "config-changed", { config: newConfig });
}

private _computeLabelCallback = (
schema: SchemaUnion<ReturnType<typeof this._schema>>
) => {
Expand Down Expand Up @@ -128,6 +183,11 @@ export class HuiHeadingEntityEditor
display: block;
margin-bottom: 24px;
}
.intro {
margin: 0;
color: var(--secondary-text-color);
margin-bottom: 8px;
}
`,
];
}
Expand Down
4 changes: 3 additions & 1 deletion src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -6007,7 +6007,9 @@
},
"entities": "Entities",
"entity_config": {
"content": "Content"
"content": "Content",
"visibility": "Visibility",
"visibility_explanation": "The entity will be shown when ALL conditions below are fulfilled. If no conditions are set, the entity will always be shown."
},
"default_heading": "Kitchen"
},
Expand Down

0 comments on commit c30e4a6

Please sign in to comment.