Use expansion panel for dashboard conditions (#18380)

This commit is contained in:
Paul Bottein 2023-10-25 00:45:55 +02:00 committed by GitHub
parent d94f7c90c0
commit 33e0c691c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 207 additions and 133 deletions

View File

@ -8,10 +8,12 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation"; import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { handleStructError } from "../../../../common/structs/handle-errors"; import { handleStructError } from "../../../../common/structs/handle-errors";
import "../../../../components/ha-button-menu"; import "../../../../components/ha-button-menu";
import "../../../../components/ha-expansion-panel";
import "../../../../components/ha-icon-button"; import "../../../../components/ha-icon-button";
import "../../../../components/ha-list-item"; import "../../../../components/ha-list-item";
import "../../../../components/ha-svg-icon"; import "../../../../components/ha-svg-icon";
import "../../../../components/ha-yaml-editor"; import "../../../../components/ha-yaml-editor";
import "../../../../components/ha-alert";
import { haStyle } from "../../../../resources/styles"; import { haStyle } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import { ICON_CONDITION } from "../../common/icon-condition"; import { ICON_CONDITION } from "../../common/icon-condition";
@ -19,7 +21,7 @@ import { Condition, LegacyCondition } from "../../common/validate-condition";
import type { LovelaceConditionEditorConstructor } from "./types"; import type { LovelaceConditionEditorConstructor } from "./types";
@customElement("ha-card-condition-editor") @customElement("ha-card-condition-editor")
export default class HaCardConditionEditor extends LitElement { export class HaCardConditionEditor extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) condition!: Condition | LegacyCondition; @property({ attribute: false }) condition!: Condition | LegacyCondition;
@ -39,6 +41,12 @@ export default class HaCardConditionEditor extends LitElement {
) as LovelaceConditionEditorConstructor | undefined; ) as LovelaceConditionEditorConstructor | undefined;
} }
public expand() {
this.updateComplete.then(() => {
this.shadowRoot!.querySelector("ha-expansion-panel")!.expanded = true;
});
}
protected willUpdate(changedProperties: PropertyValues): void { protected willUpdate(changedProperties: PropertyValues): void {
if (changedProperties.has("condition")) { if (changedProperties.has("condition")) {
this._condition = { this._condition = {
@ -75,110 +83,130 @@ export default class HaCardConditionEditor extends LitElement {
if (!condition) return nothing; if (!condition) return nothing;
return html` return html`
<div class="header"> <ha-card outlined>
<ha-svg-icon <ha-expansion-panel leftChevron>
class="icon" <h3 slot="header">
.path=${ICON_CONDITION[condition.condition]}
></ha-svg-icon>
<span class="title">
${this.hass.localize(
`ui.panel.lovelace.editor.condition-editor.condition.${condition.condition}.label`
) || condition.condition}
</span>
<ha-button-menu
slot="icons"
@action=${this._handleAction}
@click=${preventDefault}
@closed=${stopPropagation}
fixed
.corner=${"BOTTOM_END"}
.menuCorner=${"END"}
>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
>
</ha-icon-button>
<ha-list-item graphic="icon" .disabled=${!this._uiAvailable}>
${this.hass.localize("ui.panel.lovelace.editor.edit_card.edit_ui")}
${!this._yamlMode
? html`
<ha-svg-icon
class="selected_menu_item"
slot="graphic"
.path=${mdiCheck}
></ha-svg-icon>
`
: ``}
</ha-list-item>
<ha-list-item graphic="icon">
${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.edit_yaml"
)}
${this._yamlMode
? html`
<ha-svg-icon
class="selected_menu_item"
slot="graphic"
.path=${mdiCheck}
></ha-svg-icon>
`
: ``}
</ha-list-item>
<li divider role="separator"></li>
<ha-list-item class="warning" graphic="icon">
${this.hass!.localize("ui.common.delete")}
<ha-svg-icon <ha-svg-icon
class="warning" class="condition-icon"
slot="graphic" .path=${ICON_CONDITION[condition.condition]}
.path=${mdiDelete}
></ha-svg-icon> ></ha-svg-icon>
</ha-list-item> ${
</ha-button-menu> this.hass.localize(
</div> `ui.panel.lovelace.editor.condition-editor.condition.${condition.condition}.label`
${!this._uiAvailable ) || condition.condition
? html` }
<ha-alert </h3>
alert-type="warning" <ha-button-menu
.title=${this.hass.localize( slot="icons"
"ui.errors.config.editor_not_supported" @action=${this._handleAction}
)} @click=${preventDefault}
@closed=${stopPropagation}
fixed
.corner=${"BOTTOM_END"}
.menuCorner=${"END"}
> >
${this._uiWarnings!.length > 0 && <ha-icon-button
this._uiWarnings![0] !== undefined slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
>
</ha-icon-button>
<ha-list-item graphic="icon" .disabled=${!this._uiAvailable}>
${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.edit_ui"
)}
${
!this._yamlMode
? html`
<ha-svg-icon
class="selected_menu_item"
slot="graphic"
.path=${mdiCheck}
></ha-svg-icon>
`
: ``
}
</ha-list-item>
<ha-list-item graphic="icon">
${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.edit_yaml"
)}
${
this._yamlMode
? html`
<ha-svg-icon
class="selected_menu_item"
slot="graphic"
.path=${mdiCheck}
></ha-svg-icon>
`
: ``
}
</ha-list-item>
<li divider role="separator"></li>
<ha-list-item class="warning" graphic="icon">
${this.hass!.localize("ui.common.delete")}
<ha-svg-icon
class="warning"
slot="graphic"
.path=${mdiDelete}
></ha-svg-icon>
</ha-list-item>
</ha-button-menu>
</div>
${
!this._uiAvailable
? html`
<ha-alert
alert-type="warning"
.title=${this.hass.localize(
"ui.errors.config.editor_not_supported"
)}
>
${this._uiWarnings!.length > 0 &&
this._uiWarnings![0] !== undefined
? html`
<ul>
${this._uiWarnings!.map(
(warning) => html`<li>${warning}</li>`
)}
</ul>
`
: nothing}
${this.hass.localize(
"ui.errors.config.edit_in_yaml_supported"
)}
</ha-alert>
`
: nothing
}
<div class="content">
${
this._yamlMode
? html` ? html`
<ul> <ha-yaml-editor
${this._uiWarnings!.map( .hass=${this.hass}
(warning) => html`<li>${warning}</li>` .defaultValue=${this.condition}
)} @value-changed=${this._onYamlChange}
</ul> ></ha-yaml-editor>
` `
: nothing} : html`
${this.hass.localize("ui.errors.config.edit_in_yaml_supported")} ${dynamicElement(
</ha-alert> `ha-card-condition-${condition.condition}`,
` {
: nothing} hass: this.hass,
<div class="content"> condition: condition,
${this._yamlMode }
? html` )}
<ha-yaml-editor `
.hass=${this.hass} }
.defaultValue=${this.condition} </div>
@value-changed=${this._onYamlChange} </ha-expansion-panel>
></ha-yaml-editor> </ha-card>
`
: html`
${dynamicElement(`ha-card-condition-${condition.condition}`, {
hass: this.hass,
condition: condition,
})}
`}
</div>
`; `;
} }
@ -212,27 +240,39 @@ export default class HaCardConditionEditor extends LitElement {
static styles = [ static styles = [
haStyle, haStyle,
css` css`
.header { ha-button-menu {
display: flex; --mdc-theme-text-primary-on-background: var(--primary-text-color);
flex-direction: row;
align-items: center;
justify-content: space-between;
} }
.header span {
flex: 1; ha-expansion-panel {
font-size: 16px; --expansion-panel-summary-padding: 0 0 0 8px;
--expansion-panel-content-padding: 0;
}
.condition-icon {
display: none;
}
@media (min-width: 870px) {
.condition-icon {
display: inline-block;
color: var(--secondary-text-color);
opacity: 0.9;
margin-right: 8px;
}
}
h3 {
margin: 0;
font-size: inherit;
font-weight: inherit;
} }
.content { .content {
padding: 12px; padding: 12px;
} }
.header .icon {
padding: 12px;
}
.selected_menu_item { .selected_menu_item {
color: var(--primary-color); color: var(--primary-color);
} }
li[role="separator"] { .disabled {
border-bottom-color: var(--divider-color); opacity: 0.5;
pointer-events: none;
} }
`, `,
]; ];

View File

@ -1,8 +1,9 @@
import { mdiPlus } from "@mdi/js"; import { mdiPlus } from "@mdi/js";
import { CSSResultGroup, LitElement, css, html } from "lit"; import { CSSResultGroup, LitElement, PropertyValues, css, html } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation"; import { stopPropagation } from "../../../../common/dom/stop_propagation";
import "../../../../components/ha-alert";
import "../../../../components/ha-button"; import "../../../../components/ha-button";
import "../../../../components/ha-list-item"; import "../../../../components/ha-list-item";
import type { HaSelect } from "../../../../components/ha-select"; import type { HaSelect } from "../../../../components/ha-select";
@ -11,6 +12,7 @@ import type { HomeAssistant } from "../../../../types";
import { ICON_CONDITION } from "../../common/icon-condition"; import { ICON_CONDITION } from "../../common/icon-condition";
import { Condition, LegacyCondition } from "../../common/validate-condition"; import { Condition, LegacyCondition } from "../../common/validate-condition";
import "./ha-card-condition-editor"; import "./ha-card-condition-editor";
import type { HaCardConditionEditor } from "./ha-card-condition-editor";
import { LovelaceConditionEditorConstructor } from "./types"; import { LovelaceConditionEditorConstructor } from "./types";
import "./types/ha-card-condition-numeric_state"; import "./types/ha-card-condition-numeric_state";
import "./types/ha-card-condition-screen"; import "./types/ha-card-condition-screen";
@ -33,22 +35,54 @@ export class HaCardConditionsEditor extends LitElement {
| LegacyCondition | LegacyCondition
)[]; )[];
private _focusLastConditionOnChange = false;
protected firstUpdated() {
// Expand the condition if there is only one
if (this.conditions.length === 1) {
const row = this.shadowRoot!.querySelector<HaCardConditionEditor>(
"ha-card-condition-editor"
)!;
row.updateComplete.then(() => {
row.expand();
});
}
}
protected updated(changedProperties: PropertyValues) {
if (!changedProperties.has("conditions")) {
return;
}
if (this._focusLastConditionOnChange) {
this._focusLastConditionOnChange = false;
const row = this.shadowRoot!.querySelector<HaCardConditionEditor>(
"ha-card-condition-editor:last-of-type"
)!;
row.updateComplete.then(() => {
row.expand();
row.scrollIntoView();
row.focus();
});
}
}
protected render() { protected render() {
return html` return html`
<div class="conditions"> <div class="conditions">
${this.hass!.localize( <ha-alert alert-type="info">
"ui.panel.lovelace.editor.condition-editor.explanation" ${this.hass!.localize(
)} "ui.panel.lovelace.editor.condition-editor.explanation"
)}
</ha-alert>
${this.conditions.map( ${this.conditions.map(
(cond, idx) => html` (cond, idx) => html`
<div class="condition"> <ha-card-condition-editor
<ha-card-condition-editor .index=${idx}
.index=${idx} @value-changed=${this._conditionChanged}
@value-changed=${this._conditionChanged} .hass=${this.hass}
.hass=${this.hass} .condition=${cond}
.condition=${cond} ></ha-card-condition-editor>
></ha-card-condition-editor>
</div>
` `
)} )}
<div> <div>
@ -99,6 +133,7 @@ export class HaCardConditionsEditor extends LitElement {
? { ...elClass.defaultConfig } ? { ...elClass.defaultConfig }
: { condition: condition } : { condition: condition }
); );
this._focusLastConditionOnChange = true;
fireEvent(this, "value-changed", { value: conditions }); fireEvent(this, "value-changed", { value: conditions });
} }
@ -123,15 +158,14 @@ export class HaCardConditionsEditor extends LitElement {
mwc-tab-bar { mwc-tab-bar {
border-bottom: 1px solid var(--divider-color); border-bottom: 1px solid var(--divider-color);
} }
.conditions { ha-alert {
margin-top: 8px; display: block;
margin-top: 12px;
} }
.condition { ha-card-condition-editor {
margin-top: 8px; display: block;
border: 1px solid var(--divider-color); margin-top: 12px;
} scroll-margin-top: 48px;
.condition .content {
padding: 12px;
} }
ha-button-menu { ha-button-menu {
margin-top: 12px; margin-top: 12px;