mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Add support for state content customization in tile card (#18180)
* Add support for state content customization * Add reorder option * Do not display null attributes * Always return a value * Add hide state option * Add missing attribute unit * Fix sortable create and destroy
This commit is contained in:
parent
c9f5d16745
commit
6ffc0625d3
@ -1,12 +1,16 @@
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import { mdiClose } from "@mdi/js";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { mdiClose, mdiDrag } from "@mdi/js";
|
||||
import { LitElement, PropertyValues, css, html, nothing } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { repeat } from "lit/directives/repeat";
|
||||
import { SortableEvent } from "sortablejs";
|
||||
import { ensureArray } from "../../common/array/ensure-array";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { stopPropagation } from "../../common/dom/stop_propagation";
|
||||
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
||||
import type { SelectOption, SelectSelector } from "../../data/selector";
|
||||
import { sortableStyles } from "../../resources/ha-sortable-style";
|
||||
import { SortableInstance } from "../../resources/sortable";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import "../ha-checkbox";
|
||||
import "../ha-chip";
|
||||
@ -38,6 +42,68 @@ export class HaSelectSelector extends LitElement {
|
||||
|
||||
@query("ha-combo-box", true) private comboBox!: HaComboBox;
|
||||
|
||||
private _sortable?: SortableInstance;
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
if (changedProps.has("value") || changedProps.has("selector")) {
|
||||
const sortableNeeded =
|
||||
this.selector.select?.multiple &&
|
||||
this.selector.select.reorder &&
|
||||
this.value?.length;
|
||||
if (!this._sortable && sortableNeeded) {
|
||||
this._createSortable();
|
||||
} else if (this._sortable && !sortableNeeded) {
|
||||
this._destroySortable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async _createSortable() {
|
||||
const Sortable = (await import("../../resources/sortable")).default;
|
||||
this._sortable = new Sortable(
|
||||
this.shadowRoot!.querySelector("ha-chip-set")!,
|
||||
{
|
||||
animation: 150,
|
||||
fallbackClass: "sortable-fallback",
|
||||
draggable: "ha-chip",
|
||||
onChoose: (evt: SortableEvent) => {
|
||||
(evt.item as any).placeholder =
|
||||
document.createComment("sort-placeholder");
|
||||
evt.item.after((evt.item as any).placeholder);
|
||||
},
|
||||
onEnd: (evt: SortableEvent) => {
|
||||
// put back in original location
|
||||
if ((evt.item as any).placeholder) {
|
||||
(evt.item as any).placeholder.replaceWith(evt.item);
|
||||
delete (evt.item as any).placeholder;
|
||||
}
|
||||
this._dragged(evt);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _dragged(ev: SortableEvent): void {
|
||||
if (ev.oldIndex === ev.newIndex) return;
|
||||
this._move(ev.oldIndex!, ev.newIndex!);
|
||||
}
|
||||
|
||||
private _move(index: number, newIndex: number) {
|
||||
const value = this.value as string[];
|
||||
const newValue = value.concat();
|
||||
const element = newValue.splice(index, 1)[0];
|
||||
newValue.splice(newIndex, 0, element);
|
||||
this.value = newValue;
|
||||
fireEvent(this, "value-changed", {
|
||||
value: newValue,
|
||||
});
|
||||
}
|
||||
|
||||
private _destroySortable() {
|
||||
this._sortable?.destroy();
|
||||
this._sortable = undefined;
|
||||
}
|
||||
|
||||
private _filter = "";
|
||||
|
||||
protected render() {
|
||||
@ -71,7 +137,11 @@ export class HaSelectSelector extends LitElement {
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.selector.select?.custom_value && this._mode === "list") {
|
||||
if (
|
||||
!this.selector.select?.custom_value &&
|
||||
!this.selector.select?.reorder &&
|
||||
this._mode === "list"
|
||||
) {
|
||||
if (!this.selector.select?.multiple) {
|
||||
return html`
|
||||
<div>
|
||||
@ -124,23 +194,39 @@ export class HaSelectSelector extends LitElement {
|
||||
|
||||
return html`
|
||||
${value?.length
|
||||
? html`<ha-chip-set>
|
||||
${value.map(
|
||||
(item, idx) => html`
|
||||
<ha-chip hasTrailingIcon>
|
||||
${options.find((option) => option.value === item)?.label ||
|
||||
item}
|
||||
<ha-svg-icon
|
||||
slot="trailing-icon"
|
||||
.path=${mdiClose}
|
||||
.idx=${idx}
|
||||
@click=${this._removeItem}
|
||||
></ha-svg-icon>
|
||||
</ha-chip>
|
||||
`
|
||||
)}
|
||||
</ha-chip-set>`
|
||||
: ""}
|
||||
? html`
|
||||
<ha-chip-set>
|
||||
${repeat(
|
||||
value,
|
||||
(item) => item,
|
||||
(item, idx) => html`
|
||||
<ha-chip
|
||||
hasTrailingIcon
|
||||
.hasIcon=${this.selector.select?.reorder}
|
||||
>
|
||||
${this.selector.select?.reorder
|
||||
? html`
|
||||
<ha-svg-icon
|
||||
slot="icon"
|
||||
.path=${mdiDrag}
|
||||
data-handle
|
||||
></ha-svg-icon>
|
||||
`
|
||||
: nothing}
|
||||
${options.find((option) => option.value === item)
|
||||
?.label || item}
|
||||
<ha-svg-icon
|
||||
slot="trailing-icon"
|
||||
.path=${mdiClose}
|
||||
.idx=${idx}
|
||||
@click=${this._removeItem}
|
||||
></ha-svg-icon>
|
||||
</ha-chip>
|
||||
`
|
||||
)}
|
||||
</ha-chip-set>
|
||||
`
|
||||
: nothing}
|
||||
|
||||
<ha-combo-box
|
||||
item-value-path="value"
|
||||
@ -331,19 +417,22 @@ export class HaSelectSelector extends LitElement {
|
||||
this.comboBox.filteredItems = filteredItems;
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
position: relative;
|
||||
}
|
||||
ha-select,
|
||||
mwc-formfield,
|
||||
ha-formfield {
|
||||
display: block;
|
||||
}
|
||||
mwc-list-item[disabled] {
|
||||
--mdc-theme-text-primary-on-background: var(--disabled-text-color);
|
||||
}
|
||||
`;
|
||||
static styles = [
|
||||
sortableStyles,
|
||||
css`
|
||||
:host {
|
||||
position: relative;
|
||||
}
|
||||
ha-select,
|
||||
mwc-formfield,
|
||||
ha-formfield {
|
||||
display: block;
|
||||
}
|
||||
mwc-list-item[disabled] {
|
||||
--mdc-theme-text-primary-on-background: var(--disabled-text-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -28,6 +28,7 @@ export const TEMPERATURE_ATTRIBUTES = new Set([
|
||||
"target_temperature",
|
||||
"target_temp_temp",
|
||||
"target_temp_high",
|
||||
"target_temp_low",
|
||||
"target_temp_step",
|
||||
"min_temp",
|
||||
"max_temp",
|
||||
@ -70,4 +71,7 @@ export const DOMAIN_ATTRIBUTES_UNITS: Record<string, Record<string, string>> = {
|
||||
vacuum: {
|
||||
battery_level: "%",
|
||||
},
|
||||
sensor: {
|
||||
battery_level: "%",
|
||||
},
|
||||
};
|
||||
|
@ -309,6 +309,7 @@ export interface SelectSelector {
|
||||
options: readonly string[] | readonly SelectOption[];
|
||||
translation_key?: string;
|
||||
sort?: boolean;
|
||||
reorder?: boolean;
|
||||
} | null;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import { classMap } from "lit/directives/class-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { ensureArray } from "../../../common/array/ensure-array";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { hsv2rgb, rgb2hex, rgb2hsv } from "../../../common/color/convert-color";
|
||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||
@ -34,15 +35,7 @@ import "../../../components/tile/ha-tile-icon";
|
||||
import "../../../components/tile/ha-tile-image";
|
||||
import "../../../components/tile/ha-tile-info";
|
||||
import { cameraUrlWithWidthHeight } from "../../../data/camera";
|
||||
import {
|
||||
CoverEntity,
|
||||
computeCoverPositionStateDisplay,
|
||||
} from "../../../data/cover";
|
||||
import { isUnavailableState } from "../../../data/entity";
|
||||
import { FanEntity, computeFanSpeedStateDisplay } from "../../../data/fan";
|
||||
import type { HumidifierEntity } from "../../../data/humidifier";
|
||||
import type { ClimateEntity } from "../../../data/climate";
|
||||
import type { LightEntity } from "../../../data/light";
|
||||
import type { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { SENSOR_DEVICE_CLASS_TIMESTAMP } from "../../../data/sensor";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
@ -181,80 +174,89 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
);
|
||||
|
||||
private _formatState(stateObj: HassEntity): TemplateResult | string {
|
||||
private _renderStateContent(
|
||||
stateObj: HassEntity,
|
||||
stateContent: string | string[]
|
||||
) {
|
||||
const contents = ensureArray(stateContent);
|
||||
|
||||
const values = contents
|
||||
.map((content) => {
|
||||
if (content === "state") {
|
||||
const domain = computeDomain(stateObj.entity_id);
|
||||
if (
|
||||
(stateObj.attributes.device_class ===
|
||||
SENSOR_DEVICE_CLASS_TIMESTAMP ||
|
||||
TIMESTAMP_STATE_DOMAINS.includes(domain)) &&
|
||||
!isUnavailableState(stateObj.state)
|
||||
) {
|
||||
return html`
|
||||
<hui-timestamp-display
|
||||
.hass=${this.hass}
|
||||
.ts=${new Date(stateObj.state)}
|
||||
format="relative"
|
||||
capitalize
|
||||
></hui-timestamp-display>
|
||||
`;
|
||||
}
|
||||
|
||||
return this.hass!.formatEntityState(stateObj);
|
||||
}
|
||||
if (content === "last-changed") {
|
||||
return html`
|
||||
<ha-relative-time
|
||||
.hass=${this.hass}
|
||||
.datetime=${stateObj.last_changed}
|
||||
></ha-relative-time>
|
||||
`;
|
||||
}
|
||||
if (stateObj.attributes[content] == null) {
|
||||
return undefined;
|
||||
}
|
||||
return this.hass!.formatEntityAttributeValue(stateObj, content);
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
if (!values.length) {
|
||||
return html`${this.hass!.formatEntityState(stateObj)}`;
|
||||
}
|
||||
|
||||
return html`
|
||||
${values.map(
|
||||
(value, index, array) =>
|
||||
html`${value}${index < array.length - 1 ? " ⸱ " : nothing}`
|
||||
)}
|
||||
`;
|
||||
}
|
||||
|
||||
private _renderState(stateObj: HassEntity): TemplateResult | typeof nothing {
|
||||
const domain = computeDomain(stateObj.entity_id);
|
||||
const active = stateActive(stateObj);
|
||||
|
||||
if (
|
||||
(stateObj.attributes.device_class === SENSOR_DEVICE_CLASS_TIMESTAMP ||
|
||||
TIMESTAMP_STATE_DOMAINS.includes(domain)) &&
|
||||
!isUnavailableState(stateObj.state)
|
||||
) {
|
||||
return html`
|
||||
<hui-timestamp-display
|
||||
.hass=${this.hass}
|
||||
.ts=${new Date(stateObj.state)}
|
||||
format="relative"
|
||||
capitalize
|
||||
></hui-timestamp-display>
|
||||
`;
|
||||
if (domain === "light" && active) {
|
||||
return this._renderStateContent(stateObj, ["brightness"]);
|
||||
}
|
||||
|
||||
if (domain === "light" && stateActive(stateObj)) {
|
||||
const brightness = (stateObj as LightEntity).attributes.brightness;
|
||||
if (brightness) {
|
||||
return this.hass!.formatEntityAttributeValue(stateObj, "brightness");
|
||||
}
|
||||
if (domain === "fan" && active) {
|
||||
return this._renderStateContent(stateObj, ["percentage"]);
|
||||
}
|
||||
|
||||
if (domain === "fan") {
|
||||
const speedStateDisplay = computeFanSpeedStateDisplay(
|
||||
stateObj as FanEntity,
|
||||
this.hass!
|
||||
);
|
||||
if (speedStateDisplay) {
|
||||
return speedStateDisplay;
|
||||
}
|
||||
if (domain === "cover" && active) {
|
||||
return this._renderStateContent(stateObj, ["state", "current_position"]);
|
||||
}
|
||||
|
||||
const stateDisplay = this.hass!.formatEntityState(stateObj);
|
||||
|
||||
if (domain === "cover") {
|
||||
const positionStateDisplay = computeCoverPositionStateDisplay(
|
||||
stateObj as CoverEntity,
|
||||
this.hass!
|
||||
);
|
||||
if (positionStateDisplay) {
|
||||
return `${stateDisplay} ⸱ ${positionStateDisplay}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (domain === "humidifier" && stateActive(stateObj)) {
|
||||
const humidity = (stateObj as HumidifierEntity).attributes.humidity;
|
||||
if (humidity) {
|
||||
const formattedHumidity = this.hass!.formatEntityAttributeValue(
|
||||
stateObj,
|
||||
"humidity",
|
||||
Math.round(humidity)
|
||||
);
|
||||
return `${stateDisplay} ⸱ ${formattedHumidity}`;
|
||||
}
|
||||
if (domain === "humidifier") {
|
||||
return this._renderStateContent(stateObj, ["state", "current_humidity"]);
|
||||
}
|
||||
|
||||
if (domain === "climate") {
|
||||
const current_temperature = (stateObj as ClimateEntity).attributes
|
||||
.current_temperature;
|
||||
if (current_temperature) {
|
||||
const formattedCurrentTemperature =
|
||||
this.hass!.formatEntityAttributeValue(
|
||||
stateObj,
|
||||
"current_temperature",
|
||||
current_temperature
|
||||
);
|
||||
return `${stateDisplay} ⸱ ${formattedCurrentTemperature}`;
|
||||
}
|
||||
return this._renderStateContent(stateObj, [
|
||||
"state",
|
||||
"current_temperature",
|
||||
]);
|
||||
}
|
||||
|
||||
return stateDisplay;
|
||||
return this._renderStateContent(stateObj, "state");
|
||||
}
|
||||
|
||||
@queryAsync("mwc-ripple") private _ripple!: Promise<Ripple | null>;
|
||||
@ -323,7 +325,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
|
||||
|
||||
const name = this._config.name || stateObj.attributes.friendly_name;
|
||||
|
||||
const localizedState = this._formatState(stateObj);
|
||||
const localizedState = this._config.hide_state
|
||||
? nothing
|
||||
: this._config.state_content
|
||||
? this._renderStateContent(stateObj, this._config.state_content)
|
||||
: this._renderState(stateObj);
|
||||
|
||||
const active = stateActive(stateObj);
|
||||
const color = this._computeStateColor(stateObj, this._config.color);
|
||||
|
@ -520,6 +520,8 @@ export interface EnergyFlowCardConfig extends LovelaceCardConfig {
|
||||
export interface TileCardConfig extends LovelaceCardConfig {
|
||||
entity: string;
|
||||
name?: string;
|
||||
hide_state?: boolean;
|
||||
state_content?: string | string[];
|
||||
icon?: string;
|
||||
color?: string;
|
||||
show_entity_picture?: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { mdiGestureTap, mdiPalette } from "@mdi/js";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import {
|
||||
@ -12,11 +12,17 @@ import {
|
||||
object,
|
||||
optional,
|
||||
string,
|
||||
union,
|
||||
} from "superstruct";
|
||||
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||
import { ensureArray } from "../../../../common/array/ensure-array";
|
||||
import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { formatEntityAttributeNameFunc } from "../../../../common/translations/entity-state";
|
||||
import { LocalizeFunc } from "../../../../common/translations/localize";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import type { SchemaUnion } from "../../../../components/ha-form/types";
|
||||
import type {
|
||||
HaFormSchema,
|
||||
SchemaUnion,
|
||||
} from "../../../../components/ha-form/types";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { TileCardConfig } from "../../cards/types";
|
||||
import {
|
||||
@ -31,12 +37,65 @@ import { EditSubElementEvent, SubElementEditorConfig } from "../types";
|
||||
import { configElementStyle } from "./config-elements-style";
|
||||
import "./hui-tile-card-features-editor";
|
||||
|
||||
const HIDDEN_ATTRIBUTES = [
|
||||
"access_token",
|
||||
"available_modes",
|
||||
"code_arm_required",
|
||||
"code_format",
|
||||
"color_modes",
|
||||
"device_class",
|
||||
"editable",
|
||||
"effect_list",
|
||||
"entity_id",
|
||||
"entity_picture",
|
||||
"event_types",
|
||||
"fan_modes",
|
||||
"fan_speed_list",
|
||||
"friendly_name",
|
||||
"frontend_stream_type",
|
||||
"has_date",
|
||||
"has_time",
|
||||
"hvac_modes",
|
||||
"icon",
|
||||
"id",
|
||||
"max_color_temp_kelvin",
|
||||
"max_mireds",
|
||||
"max_temp",
|
||||
"max",
|
||||
"min_color_temp_kelvin",
|
||||
"min_mireds",
|
||||
"min_temp",
|
||||
"min",
|
||||
"mode",
|
||||
"operation_list",
|
||||
"options",
|
||||
"percentage_step",
|
||||
"precipitation_unit",
|
||||
"preset_modes",
|
||||
"pressure_unit",
|
||||
"sound_mode_list",
|
||||
"source_list",
|
||||
"state_class",
|
||||
"step",
|
||||
"supported_color_modes",
|
||||
"supported_features",
|
||||
"swing_modes",
|
||||
"target_temp_step",
|
||||
"temperature_unit",
|
||||
"token",
|
||||
"unit_of_measurement",
|
||||
"visibility_unit",
|
||||
"wind_speed_unit",
|
||||
];
|
||||
|
||||
const cardConfigStruct = assign(
|
||||
baseLovelaceCardConfig,
|
||||
object({
|
||||
entity: optional(string()),
|
||||
name: optional(string()),
|
||||
icon: optional(string()),
|
||||
hide_state: optional(boolean()),
|
||||
state_content: optional(union([string(), array(string())])),
|
||||
color: optional(string()),
|
||||
show_entity_picture: optional(boolean()),
|
||||
vertical: optional(boolean()),
|
||||
@ -63,7 +122,12 @@ export class HuiTileCardEditor
|
||||
}
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(localize: LocalizeFunc) =>
|
||||
(
|
||||
localize: LocalizeFunc,
|
||||
formatEntityAttributeName: formatEntityAttributeNameFunc,
|
||||
stateObj: HassEntity | undefined,
|
||||
hideState: boolean
|
||||
) =>
|
||||
[
|
||||
{ name: "entity", selector: { entity: {} } },
|
||||
{
|
||||
@ -102,9 +166,49 @@ export class HuiTileCardEditor
|
||||
boolean: {},
|
||||
},
|
||||
},
|
||||
] as const,
|
||||
{
|
||||
name: "hide_state",
|
||||
selector: {
|
||||
boolean: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
] as const,
|
||||
...(!hideState
|
||||
? ([
|
||||
{
|
||||
name: "state_content",
|
||||
selector: {
|
||||
select: {
|
||||
mode: "dropdown",
|
||||
reorder: true,
|
||||
custom_value: true,
|
||||
multiple: true,
|
||||
options: [
|
||||
{
|
||||
label: "State",
|
||||
value: "state",
|
||||
},
|
||||
{
|
||||
label: "Last changed",
|
||||
value: "last-changed",
|
||||
},
|
||||
...Object.keys(stateObj?.attributes ?? {})
|
||||
.filter((a) => !HIDDEN_ATTRIBUTES.includes(a))
|
||||
.map((attribute) => ({
|
||||
value: attribute,
|
||||
label: formatEntityAttributeName(
|
||||
stateObj!,
|
||||
attribute
|
||||
),
|
||||
})),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
] as const satisfies readonly HaFormSchema[])
|
||||
: []),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "",
|
||||
@ -124,9 +228,9 @@ export class HuiTileCardEditor
|
||||
ui_action: {},
|
||||
},
|
||||
},
|
||||
] as const,
|
||||
],
|
||||
},
|
||||
] as const
|
||||
] as const satisfies readonly HaFormSchema[]
|
||||
);
|
||||
|
||||
private _context = memoizeOne(
|
||||
@ -142,7 +246,12 @@ export class HuiTileCardEditor
|
||||
| HassEntity
|
||||
| undefined;
|
||||
|
||||
const schema = this._schema(this.hass!.localize);
|
||||
const schema = this._schema(
|
||||
this.hass!.localize,
|
||||
this.hass.formatEntityAttributeName,
|
||||
stateObj,
|
||||
this._config.hide_state ?? false
|
||||
);
|
||||
|
||||
if (this._subElementEditorConfig) {
|
||||
return html`
|
||||
@ -157,10 +266,15 @@ export class HuiTileCardEditor
|
||||
`;
|
||||
}
|
||||
|
||||
const data = {
|
||||
...this._config,
|
||||
state_content: ensureArray(this._config.state_content),
|
||||
};
|
||||
|
||||
return html`
|
||||
<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this._config}
|
||||
.data=${data}
|
||||
.schema=${schema}
|
||||
.computeLabel=${this._computeLabelCallback}
|
||||
@value-changed=${this._valueChanged}
|
||||
@ -181,10 +295,25 @@ export class HuiTileCardEditor
|
||||
return;
|
||||
}
|
||||
|
||||
const newConfig = ev.detail.value as TileCardConfig;
|
||||
|
||||
const config: TileCardConfig = {
|
||||
features: this._config.features,
|
||||
...ev.detail.value,
|
||||
...newConfig,
|
||||
};
|
||||
|
||||
if (config.hide_state) {
|
||||
delete config.state_content;
|
||||
}
|
||||
|
||||
if (config.state_content) {
|
||||
if (config.state_content.length === 0) {
|
||||
delete config.state_content;
|
||||
} else if (config.state_content.length === 1) {
|
||||
config.state_content = config.state_content[0];
|
||||
}
|
||||
}
|
||||
|
||||
fireEvent(this, "config-changed", { config });
|
||||
}
|
||||
|
||||
@ -252,6 +381,8 @@ export class HuiTileCardEditor
|
||||
case "icon_tap_action":
|
||||
case "show_entity_picture":
|
||||
case "vertical":
|
||||
case "hide_state":
|
||||
case "state_content":
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.tile.${schema.name}`
|
||||
);
|
||||
|
@ -5063,6 +5063,8 @@
|
||||
"default_color": "Default color (state)",
|
||||
"show_entity_picture": "Show entity picture",
|
||||
"vertical": "Vertical",
|
||||
"hide_state": "Hide state",
|
||||
"state_content": "State content",
|
||||
"features": {
|
||||
"name": "Features",
|
||||
"not_compatible": "Not compatible",
|
||||
|
Loading…
x
Reference in New Issue
Block a user