Add visibility editor to card editor (#20926)

* Add visibility editor to card editor

* Add translations

* AI suggestion
This commit is contained in:
Paul Bottein 2024-06-03 18:23:47 +02:00 committed by GitHub
parent e48286c2a0
commit 0297ec5a7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 161 additions and 28 deletions

View File

@ -1,11 +1,22 @@
import { customElement } from "lit/decorators";
import "@polymer/paper-tabs/paper-tab";
import "@polymer/paper-tabs/paper-tabs";
import { CSSResultGroup, TemplateResult, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
import { getCardElementClass } from "../../create-element/create-card-element";
import type { LovelaceCardEditor, LovelaceConfigForm } from "../../types";
import { HuiElementEditor } from "../hui-element-editor";
import "./hui-card-visibility-editor";
const TABS = ["config", "visibility"] as const;
@customElement("hui-card-element-editor")
export class HuiCardElementEditor extends HuiElementEditor<LovelaceCardConfig> {
@state() private _curTab: (typeof TABS)[number] = TABS[0];
@property({ type: Boolean, attribute: "show-visibility-tab" })
public showVisibilityTab = false;
protected async getConfigElement(): Promise<LovelaceCardEditor | undefined> {
const elClass = await getCardElementClass(this.configElementType!);
@ -27,6 +38,73 @@ export class HuiCardElementEditor extends HuiElementEditor<LovelaceCardConfig> {
return undefined;
}
private _handleTabSelected(ev: CustomEvent): void {
if (!ev.detail.value) {
return;
}
this._curTab = ev.detail.value.id;
}
private _configChanged(ev: CustomEvent): void {
ev.stopPropagation();
this.value = ev.detail.value;
}
protected renderConfigElement(): TemplateResult {
if (!this.showVisibilityTab) return super.renderConfigElement();
let content: TemplateResult<1> | typeof nothing = nothing;
switch (this._curTab) {
case "config":
content = html`${super.renderConfigElement()}`;
break;
case "visibility":
content = html`
<hui-card-visibility-editor
.hass=${this.hass}
.config=${this.value}
@value-changed=${this._configChanged}
></hui-card-visibility-editor>
`;
break;
}
return html`
<paper-tabs
scrollable
hide-scroll-buttons
.selected=${TABS.indexOf(this._curTab)}
@selected-item-changed=${this._handleTabSelected}
>
${TABS.map(
(tab, index) => html`
<paper-tab id=${tab} .dialogInitialFocus=${index === 0}>
${this.hass.localize(
`ui.panel.lovelace.editor.edit_card.tab-${tab}`
)}
</paper-tab>
`
)}
</paper-tabs>
${content}
`;
}
static get styles(): CSSResultGroup {
return [
HuiElementEditor.styles,
css`
paper-tabs {
--paper-tabs-selection-bar-color: var(--primary-color);
color: var(--primary-text-color);
text-transform: uppercase;
margin-bottom: 16px;
border-bottom: 1px solid var(--divider-color);
}
`,
];
}
}
declare global {

View File

@ -0,0 +1,51 @@
import { LitElement, html } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-alert";
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
import { HomeAssistant } from "../../../../types";
import { Condition } from "../../common/validate-condition";
import "../conditions/ha-card-conditions-editor";
@customElement("hui-card-visibility-editor")
export class HuiCardVisibilityEditor extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public config!: LovelaceCardConfig;
render() {
const conditions = this.config.visibility ?? [];
return html`
<ha-alert alert-type="info">
${this.hass.localize(
`ui.panel.lovelace.editor.edit_card.visibility.explanation`
)}
</ha-alert>
<ha-card-conditions-editor
.hass=${this.hass}
.conditions=${conditions}
@value-changed=${this._valueChanged}
>
</ha-card-conditions-editor>
`;
}
private _valueChanged(ev: CustomEvent): void {
ev.stopPropagation();
const conditions = ev.detail.value as Condition[];
const newConfig: LovelaceCardConfig = {
...this.config,
visibility: conditions,
};
if (newConfig.visibility?.length === 0) {
delete newConfig.visibility;
}
fireEvent(this, "value-changed", { value: newConfig });
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-card-visibility-editor": HuiCardVisibilityEditor;
}
}

View File

@ -234,6 +234,7 @@ export class HuiDialogEditCard
<div class="content">
<div class="element-editor">
<hui-card-element-editor
.showVisibilityTab=${this._cardConfig?.type !== "conditional"}
.hass=${this.hass}
.lovelace=${this._params.lovelaceConfig}
.value=${this._cardConfig}
@ -407,30 +408,31 @@ export class HuiDialogEditCard
--code-mirror-max-height: calc(100vh - 176px);
}
ha-dialog {
--mdc-dialog-max-width: 100px;
--dialog-z-index: 6;
--dialog-surface-position: fixed;
--dialog-surface-top: 40px;
--mdc-dialog-max-width: 90vw;
--dialog-content-padding: 24px 12px;
}
@media all and (max-width: 450px), all and (max-height: 500px) {
/* overrule the ha-style-dialog max-height on small screens */
ha-dialog {
--mdc-dialog-max-height: 100%;
height: 100%;
--mdc-dialog-max-height: 100%;
--dialog-surface-top: 0px;
--mdc-dialog-max-width: 100vw;
}
}
@media all and (min-width: 850px) {
ha-dialog {
--mdc-dialog-min-width: 845px;
--mdc-dialog-max-height: calc(100% - 72px);
}
}
ha-dialog {
--mdc-dialog-max-width: 845px;
--dialog-z-index: 6;
.content {
width: 1000px;
max-width: calc(90vw - 48px);
}
@media all and (min-width: 451px) and (min-height: 501px) {
ha-dialog {
--mdc-dialog-max-width: 90vw;
}
:host([large]) .content {
width: calc(90vw - 48px);
}
@ -444,8 +446,8 @@ export class HuiDialogEditCard
.content {
display: flex;
flex-direction: column;
margin: 0 -10px;
}
.content hui-card-preview {
margin: 4px auto;
max-width: 390px;
@ -454,15 +456,7 @@ export class HuiDialogEditCard
margin: 0 10px;
}
@media (min-width: 1200px) {
ha-dialog {
--mdc-dialog-max-width: calc(100% - 32px);
--mdc-dialog-min-width: 1000px;
--dialog-surface-position: fixed;
--dialog-surface-top: 40px;
--mdc-dialog-max-height: calc(100% - 72px);
}
@media (min-width: 1000px) {
.content {
flex-direction: row;
}

View File

@ -20,13 +20,14 @@ import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import { LovelaceConfig } from "../../../data/lovelace/config/types";
import type { HomeAssistant } from "../../../types";
import { LovelaceCardFeatureConfig } from "../card-features/types";
import type { LovelaceRowConfig } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
import { LovelaceCardFeatureConfig } from "../card-features/types";
import type {
LovelaceConfigForm,
LovelaceGenericElementEditor,
} from "../types";
import "./card-editor/hui-card-visibility-editor";
import type { HuiFormEditor } from "./config-elements/hui-form-editor";
import "./config-elements/hui-generic-entity-row-editor";
import { GUISupportError } from "./gui-support-error";
@ -198,6 +199,10 @@ export abstract class HuiElementEditor<T, C = any> extends LitElement {
return this.value ? (this.value as any).type : undefined;
}
protected renderConfigElement(): TemplateResult {
return html`${this._configElement}`;
}
protected render(): TemplateResult {
return html`
<div class="wrapper">
@ -211,7 +216,7 @@ export abstract class HuiElementEditor<T, C = any> extends LitElement {
class="center margin-bot"
></ha-circular-progress>
`
: this._configElement}
: this.renderConfigElement()}
</div>
`
: html`

View File

@ -5518,7 +5518,12 @@
"decrease_position": "Decrease card position",
"increase_position": "Increase card position",
"options": "More options",
"search_cards": "Search cards"
"search_cards": "Search cards",
"tab-config": "Config",
"tab-visibility": "Visibility",
"visibility": {
"explanation": "The card will be shown when ALL conditions below are fulfilled. If no conditions are set, the card will always be shown."
}
},
"move_card": {
"header": "Choose a view to move the card to",