Group fields in tile editor (#14175)

* group form into multiple groups

* display appearence form as grid

* Add translations
This commit is contained in:
Paul Bottein 2022-10-26 13:51:58 +02:00 committed by GitHub
parent 9e955dbaaa
commit 3ac6e6f307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 152 additions and 53 deletions

View File

@ -1,5 +1,6 @@
import { mdiGestureTap, mdiPalette } from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket";
import { html, LitElement, TemplateResult } from "lit";
import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { assert, assign, object, optional, string } from "superstruct";
@ -8,6 +9,7 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import { computeDomain } from "../../../../common/entity/compute_domain";
import { domainIcon } from "../../../../common/entity/domain_icon";
import { capitalizeFirstLetter } from "../../../../common/string/capitalize-first-letter";
import { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/ha-form/ha-form";
import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
@ -42,63 +44,89 @@ export class HuiTileCardEditor
this._config = config;
}
private _schema = memoizeOne(
(entity: string, icon?: string, entityState?: HassEntity) =>
private _mainSchema = [{ name: "entity", selector: { entity: {} } }] as const;
private _appearanceSchema = memoizeOne(
(
localize: LocalizeFunc,
entity: string,
icon?: string,
entityState?: HassEntity
) =>
[
{ name: "entity", selector: { entity: {} } },
{ name: "name", selector: { text: {} } },
{
name: "icon",
selector: {
icon: {
placeholder: icon || entityState?.attributes.icon,
fallbackPath:
!icon && !entityState?.attributes.icon && entityState
? domainIcon(computeDomain(entity), entityState)
: undefined,
},
},
},
{
name: "color",
selector: {
select: {
options: [
{
label: "Default (based on state)",
value: "default",
name: "",
type: "grid",
schema: [
{ name: "name", selector: { text: {} } },
{
name: "icon",
selector: {
icon: {
placeholder: icon || entityState?.attributes.icon,
fallbackPath:
!icon && !entityState?.attributes.icon && entityState
? domainIcon(computeDomain(entity), entityState)
: undefined,
},
...Array.from(THEME_COLORS).map((color) => ({
label: capitalizeFirstLetter(color),
value: color,
})),
],
},
},
},
},
{
name: "tap_action",
selector: {
"ui-action": {},
},
},
{
name: "icon_tap_action",
selector: {
"ui-action": {},
},
{
name: "color",
selector: {
select: {
options: [
{
label: localize(
`ui.panel.lovelace.editor.card.tile.default_color`
),
value: "default",
},
...Array.from(THEME_COLORS).map((color) => ({
label: capitalizeFirstLetter(color),
value: color,
})),
],
},
},
},
] as const,
},
] as const
);
private _actionsSchema = [
{
name: "tap_action",
selector: {
"ui-action": {},
},
},
{
name: "icon_tap_action",
selector: {
"ui-action": {},
},
},
] as const;
protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;
}
const entity = this.hass.states[this._config.entity ?? ""];
const entity = this.hass.states[this._config.entity ?? ""] as
| HassEntity
| undefined;
const schema = this._schema(this._config.entity, this._config.icon, entity);
const mainSchema = this._mainSchema;
const appareanceSchema = this._appearanceSchema(
this.hass.localize,
this._config.entity,
this._config.icon,
entity
);
const actionsSchema = this._actionsSchema;
const data = {
color: "default",
@ -106,13 +134,55 @@ export class HuiTileCardEditor
};
return html`
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${schema}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
<div class="container">
<div class="group">
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${mainSchema}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
</div>
<div class="group">
<ha-expansion-panel>
<div slot="header">
<ha-svg-icon .path=${mdiPalette}></ha-svg-icon>
${this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.appearance`
)}
</div>
<div class="content">
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${appareanceSchema}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
</div>
</ha-expansion-panel>
</div>
<div class="group">
<ha-expansion-panel>
<div slot="header">
<ha-svg-icon .path=${mdiGestureTap}></ha-svg-icon>
${this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.actions`
)}
</div>
<div class="content">
<ha-form
.hass=${this.hass}
.data=${data}
.schema=${actionsSchema}
.computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged}
></ha-form>
</div>
</ha-expansion-panel>
</div>
</div>
`;
}
@ -127,7 +197,10 @@ export class HuiTileCardEditor
}
private _computeLabelCallback = (
schema: SchemaUnion<ReturnType<typeof this._schema>>
schema:
| SchemaUnion<typeof this._mainSchema>
| SchemaUnion<ReturnType<typeof this._appearanceSchema>>
| SchemaUnion<typeof this._actionsSchema>
) => {
switch (schema.name) {
case "color":
@ -141,6 +214,29 @@ export class HuiTileCardEditor
);
}
};
static get styles() {
return css`
.container {
display: flex;
flex-direction: column;
}
.group:not(:last-child) {
margin-bottom: 12px;
}
.content {
padding: 12px;
}
ha-expansion-panel {
--expansion-panel-content-padding: 0;
border: 1px solid var(--divider-color);
border-radius: 6px;
}
ha-svg-icon {
color: var(--secondary-text-color);
}
`;
}
}
declare global {

View File

@ -4137,7 +4137,10 @@
"name": "Tile",
"description": "The tile card gives you a quick overview of your entity. The card allow you to toggle the entity, show the more info dialog or custom actions.",
"color": "Color",
"icon_tap_action": "Icon tap action"
"icon_tap_action": "Icon tap action",
"actions": "Actions",
"appearance": "Appearance",
"default_color": "Default color (state)"
},
"vertical-stack": {
"name": "Vertical Stack",