20221208.0 (#14644)

This commit is contained in:
Bram Kragten 2022-12-08 15:17:56 +01:00 committed by GitHub
commit af82c0d0c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 133 additions and 59 deletions

View File

@ -1,5 +1,5 @@
--- ---
title: Alerts title: Alert
subtitle: An alert displays a short, important message in a way that attracts the user's attention without interrupting the user's task. subtitle: An alert displays a short, important message in a way that attracts the user's attention without interrupting the user's task.
--- ---

View File

@ -1,3 +1,4 @@
--- ---
title: Progress Bars title: Bar
subtitle: Can be used to communicate progress of a task.
--- ---

View File

@ -1,5 +1,5 @@
--- ---
title: Selectors title: Selector
--- ---
See the website for [list of available selectors](https://www.home-assistant.io/docs/blueprint/selectors/). See the website for [list of available selectors](https://www.home-assistant.io/docs/blueprint/selectors/).

View File

@ -142,6 +142,25 @@ const CONFIGS = [
heading: "Basic", heading: "Basic",
config: ` config: `
- type: entities - type: entities
entities:
- scene.romantic_lights
- device_tracker.demo_paulus
- cover.kitchen_window
- group.kitchen
- lock.kitchen_door
- light.bed_light
- light.non_existing
- climate.ecobee
- input_number.number
- sensor.humidity
- text.message
`,
},
{
heading: "With enabled state color",
config: `
- type: entities
state_color: true
entities: entities:
- scene.romantic_lights - scene.romantic_lights
- device_tracker.demo_paulus - device_tracker.demo_paulus

View File

@ -35,11 +35,11 @@ const CONFIGS = [
`, `,
}, },
{ {
heading: "Without State", heading: "With State",
config: ` config: `
- type: button - type: button
entity: light.bed_light entity: light.bed_light
show_state: false show_state: true
`, `,
}, },
{ {

View File

@ -62,6 +62,21 @@ const CONFIGS = [
heading: "Basic example", heading: "Basic example",
config: ` config: `
- type: glance - type: glance
entities:
- device_tracker.demo_paulus
- media_player.living_room
- sun.sun
- cover.kitchen_window
- light.kitchen_lights
- lock.kitchen_door
- light.ceiling_lights
`,
},
{
heading: "No state colors",
config: `
- type: glance
state_color: false
entities: entities:
- device_tracker.demo_paulus - device_tracker.demo_paulus
- media_player.living_room - media_player.living_room

View File

@ -1,3 +1,3 @@
--- ---
title: Grid And Stack Card title: Grid and Stack Card
--- ---

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "home-assistant-frontend" name = "home-assistant-frontend"
version = "20221207.0" version = "20221208.0"
license = {text = "Apache-2.0"} license = {text = "Apache-2.0"}
description = "The Home Assistant frontend" description = "The Home Assistant frontend"
readme = "README.md" readme = "README.md"

View File

@ -1,7 +1,5 @@
import { HassEntity } from "home-assistant-js-websocket"; export const batteryStateColor = (state: string) => {
const value = Number(state);
export const batteryStateColor = (stateObj: HassEntity) => {
const value = Number(stateObj.state);
if (isNaN(value)) { if (isNaN(value)) {
return "sensor-battery-unknown"; return "sensor-battery-unknown";
} }

View File

@ -1,7 +1,5 @@
import { HassEntity } from "home-assistant-js-websocket"; export const personColor = (state: string): string | undefined => {
switch (state) {
export const personColor = (stateObj: HassEntity): string | undefined => {
switch (stateObj.state) {
case "home": case "home":
return "person-home"; return "person-home";
default: default:

View File

@ -1,11 +1,14 @@
import { HassEntity } from "home-assistant-js-websocket"; import { HassEntity } from "home-assistant-js-websocket";
import { batteryStateColor } from "./battery_color"; import { batteryStateColor } from "./battery_color";
export const sensorColor = (stateObj: HassEntity): string | undefined => { export const sensorColor = (
stateObj: HassEntity,
compareState: string
): string | undefined => {
const deviceClass = stateObj?.attributes.device_class; const deviceClass = stateObj?.attributes.device_class;
if (deviceClass === "battery") { if (deviceClass === "battery") {
return batteryStateColor(stateObj); return batteryStateColor(compareState);
} }
return undefined; return undefined;

View File

@ -67,10 +67,10 @@ export const stateColor = (stateObj: HassEntity, state?: string) => {
case "person": case "person":
case "device_tracker": case "device_tracker":
return personColor(stateObj); return personColor(compareState);
case "sensor": case "sensor":
return sensorColor(stateObj); return sensorColor(stateObj, compareState);
case "sun": case "sun":
return compareState === "above_horizon" ? "sun-day" : "sun-night"; return compareState === "above_horizon" ? "sun-day" : "sun-night";

View File

@ -47,7 +47,7 @@ class StateHistoryChartLine extends LitElement {
} }
public willUpdate(changedProps: PropertyValues) { public willUpdate(changedProps: PropertyValues) {
if (!this.hasUpdated) { if (!this.hasUpdated || changedProps.has("showNames")) {
this._chartOptions = { this._chartOptions = {
parsing: false, parsing: false,
animation: false, animation: false,

View File

@ -64,7 +64,11 @@ export class StateHistoryChartTimeline extends LitElement {
this._generateData(); this._generateData();
} }
if (changedProps.has("startTime") || changedProps.has("endTime")) { if (
changedProps.has("startTime") ||
changedProps.has("endTime") ||
changedProps.has("showNames")
) {
this._createOptions(); this._createOptions();
} }
} }

View File

@ -32,14 +32,26 @@ import {
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import "./ha-chart-base"; import "./ha-chart-base";
export type ExtendedStatisticType = StatisticType | "state" | "change"; export type ExtendedStatisticType = StatisticType | "change";
export const supportedStatTypeMap: Record<
ExtendedStatisticType,
StatisticType
> = {
mean: "mean",
min: "min",
max: "max",
sum: "sum",
state: "sum",
change: "sum",
};
export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = { export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = {
mean: "mean", mean: "mean",
min: "min", min: "min",
max: "max", max: "max",
sum: "sum", sum: "sum",
state: "sum", state: "state",
change: "sum", change: "sum",
}; };

View File

@ -57,7 +57,10 @@ export class HaDateInput extends LitElement {
readonly readonly
@click=${this._openDialog} @click=${this._openDialog}
.value=${this.value .value=${this.value
? formatDateNumeric(new Date(`${this.value}T00:00:00`), this.locale) ? formatDateNumeric(
new Date(`${this.value.split("T")[0]}T00:00:00`),
this.locale
)
: ""} : ""}
.required=${this.required} .required=${this.required}
> >

View File

@ -53,7 +53,7 @@ export function canStart(stateObj: VacuumEntity): boolean {
} }
export function canStop(stateObj: VacuumEntity): boolean { export function canStop(stateObj: VacuumEntity): boolean {
return !["docked", "off"].includes(stateObj.state); return !["docked", "off", "idle"].includes(stateObj.state);
} }
export function canReturnHome(stateObj: VacuumEntity): boolean { export function canReturnHome(stateObj: VacuumEntity): boolean {

View File

@ -11,6 +11,7 @@ import {
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event";
import { isDate } from "../../common/string/is_date"; import { isDate } from "../../common/string/is_date";
import "../../components/ha-date-input"; import "../../components/ha-date-input";
import "../../components/ha-textarea"; import "../../components/ha-textarea";
@ -94,6 +95,21 @@ class DialogCalendarEventEditor extends LitElement {
} }
} }
public closeDialog(): void {
if (!this._params) {
return;
}
this._calendars = [];
this._calendarId = undefined;
this._params = undefined;
this._dtstart = undefined;
this._dtend = undefined;
this._summary = "";
this._description = "";
this._rrule = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this._params) { if (!this._params) {
return html``; return html``;
@ -108,7 +124,7 @@ class DialogCalendarEventEditor extends LitElement {
return html` return html`
<ha-dialog <ha-dialog
open open
@closed=${this._close} @closed=${this.closeDialog}
scrimClickAction scrimClickAction
escapeKeyAction escapeKeyAction
.heading=${html` .heading=${html`
@ -432,11 +448,12 @@ class DialogCalendarEventEditor extends LitElement {
); );
} catch (err: any) { } catch (err: any) {
this._error = err ? err.message : "Unknown error"; this._error = err ? err.message : "Unknown error";
return;
} finally { } finally {
this._submitting = false; this._submitting = false;
} }
await this._params!.updated(); await this._params!.updated();
this._params = undefined; this.closeDialog();
} }
private async _saveEvent() { private async _saveEvent() {
@ -490,18 +507,7 @@ class DialogCalendarEventEditor extends LitElement {
this._submitting = false; this._submitting = false;
} }
await this._params!.updated(); await this._params!.updated();
this._close(); this.closeDialog();
}
private _close(): void {
this._calendars = [];
this._calendarId = undefined;
this._params = undefined;
this._dtstart = undefined;
this._dtend = undefined;
this._summary = "";
this._description = "";
this._rrule = undefined;
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {

View File

@ -144,7 +144,9 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
.historyData=${this._stateHistory} .historyData=${this._stateHistory}
.names=${this._names} .names=${this._names}
up-to-now up-to-now
.showNames=${this._config.show_names} .showNames=${this._config.show_names !== undefined
? this._config.show_names
: true}
></state-history-charts> ></state-history-charts>
</div> </div>
</ha-card> </ha-card>

View File

@ -9,7 +9,10 @@ import {
} from "lit"; } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import "../../../components/chart/statistics-chart"; import {
ExtendedStatisticType,
statTypeMap,
} from "../../../components/chart/statistics-chart";
import "../../../components/ha-card"; import "../../../components/ha-card";
import { import {
fetchStatistics, fetchStatistics,
@ -17,7 +20,6 @@ import {
getStatisticMetadata, getStatisticMetadata,
Statistics, Statistics,
StatisticsMetaData, StatisticsMetaData,
StatisticsTypes,
} from "../../../data/recorder"; } from "../../../data/recorder";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { findEntities } from "../common/find-entities"; import { findEntities } from "../common/find-entities";
@ -70,7 +72,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
private _interval?: number; private _interval?: number;
private _statTypes?: StatisticsTypes; private _statTypes?: Array<ExtendedStatisticType>;
public disconnectedCallback() { public disconnectedCallback() {
super.disconnectedCallback(); super.disconnectedCallback();
@ -152,7 +154,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
if ( if (
changedProps.has("_config") && changedProps.has("_config") &&
(oldConfig?.entities !== this._config.entities || (oldConfig?.stat_types !== this._config.stat_types ||
oldConfig?.days_to_show !== this._config.days_to_show || oldConfig?.days_to_show !== this._config.days_to_show ||
oldConfig?.period !== this._config.period || oldConfig?.period !== this._config.period ||
oldConfig?.unit !== this._config.unit) oldConfig?.unit !== this._config.unit)
@ -249,7 +251,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
this._entities, this._entities,
this._config!.period, this._config!.period,
unitconfig, unitconfig,
this._statTypes this._statTypes?.map((stat_type) => statTypeMap[stat_type])
); );
} catch (err) { } catch (err) {
this._statistics = undefined; this._statistics = undefined;

View File

@ -12,6 +12,7 @@ import { computeStateDisplay } from "../../../common/entity/compute_state_displa
import { stateActive } from "../../../common/entity/state_active"; import { stateActive } from "../../../common/entity/state_active";
import { stateColorCss } from "../../../common/entity/state_color"; import { stateColorCss } from "../../../common/entity/state_color";
import { stateIconPath } from "../../../common/entity/state_icon_path"; import { stateIconPath } from "../../../common/entity/state_icon_path";
import { blankBeforePercent } from "../../../common/translations/blank_before_percent";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/tile/ha-tile-badge"; import "../../../components/tile/ha-tile-badge";
import "../../../components/tile/ha-tile-icon"; import "../../../components/tile/ha-tile-icon";
@ -192,30 +193,35 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
if (domain === "light" && stateObj.state === ON) { if (domain === "light" && stateObj.state === ON) {
const brightness = (stateObj as LightEntity).attributes.brightness; const brightness = (stateObj as LightEntity).attributes.brightness;
if (brightness) { if (brightness) {
return `${Math.round((brightness * 100) / 255)}%`; return `${Math.round((brightness * 100) / 255)}${blankBeforePercent(
} this.hass!.locale
} )}%`;
if (domain === "cover" && stateObj.state === "open") {
const position = (stateObj as CoverEntity).attributes.current_position;
if (position) {
return `${Math.round(position)}%`;
} }
} }
if (domain === "fan" && stateObj.state === ON) { if (domain === "fan" && stateObj.state === ON) {
const speed = (stateObj as FanEntity).attributes.percentage; const speed = (stateObj as FanEntity).attributes.percentage;
if (speed) { if (speed) {
return `${Math.round(speed)}%`; return `${Math.round(speed)}${blankBeforePercent(this.hass!.locale)}%`;
} }
} }
return computeStateDisplay( const stateDisplay = computeStateDisplay(
this.hass!.localize, this.hass!.localize,
stateObj, stateObj,
this.hass!.locale, this.hass!.locale,
this.hass!.entities this.hass!.entities
); );
if (domain === "cover" && stateObj.state === "open") {
const position = (stateObj as CoverEntity).attributes.current_position;
if (position && position !== 100) {
return `${stateDisplay} - ${Math.round(position)}${blankBeforePercent(
this.hass!.locale
)}%`;
}
}
return stateDisplay;
} }
protected render(): TemplateResult { protected render(): TemplateResult {

View File

@ -1,4 +1,4 @@
import { Statistic, StatisticType } from "../../../data/recorder"; import { Statistic } from "../../../data/recorder";
import { ActionConfig, LovelaceCardConfig } from "../../../data/lovelace"; import { ActionConfig, LovelaceCardConfig } from "../../../data/lovelace";
import { FullCalendarView, TranslationDict } from "../../../types"; import { FullCalendarView, TranslationDict } from "../../../types";
import { Condition } from "../common/validate-condition"; import { Condition } from "../common/validate-condition";
@ -10,6 +10,7 @@ import {
LovelaceRowConfig, LovelaceRowConfig,
} from "../entity-rows/types"; } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types"; import { LovelaceHeaderFooterConfig } from "../header-footer/types";
import { ExtendedStatisticType } from "../../../components/chart/statistics-chart";
import { HaDurationData } from "../../../components/ha-duration-input"; import { HaDurationData } from "../../../components/ha-duration-input";
import { LovelaceTileFeatureConfig } from "../tile-features/types"; import { LovelaceTileFeatureConfig } from "../tile-features/types";
@ -309,7 +310,7 @@ export interface StatisticsGraphCardConfig extends LovelaceCardConfig {
unit?: string; unit?: string;
days_to_show?: number; days_to_show?: number;
period?: "5minute" | "hour" | "day" | "month"; period?: "5minute" | "hour" | "day" | "month";
stat_types?: StatisticType | StatisticType[]; stat_types?: ExtendedStatisticType | ExtendedStatisticType[];
chart_type?: "line" | "bar"; chart_type?: "line" | "bar";
} }

View File

@ -26,6 +26,7 @@ import { deepEqual } from "../../../../common/util/deep-equal";
import { import {
ExtendedStatisticType, ExtendedStatisticType,
statTypeMap, statTypeMap,
supportedStatTypeMap,
} from "../../../../components/chart/statistics-chart"; } from "../../../../components/chart/statistics-chart";
import "../../../../components/entity/ha-statistics-picker"; import "../../../../components/entity/ha-statistics-picker";
import "../../../../components/ha-form/ha-form"; import "../../../../components/ha-form/ha-form";
@ -185,7 +186,10 @@ export class HuiStatisticsGraphCardEditor
disabled: disabled:
!metaDatas || !metaDatas ||
!metaDatas.every((metaData) => !metaDatas.every((metaData) =>
statisticsMetaHasType(metaData, statTypeMap[stat_type]) statisticsMetaHasType(
metaData,
supportedStatTypeMap[stat_type]
)
), ),
})), })),
}, },

View File

@ -85,7 +85,7 @@ export const VACUUM_COMMANDS_BUTTONS: Record<
translationKey: "start", translationKey: "start",
icon: mdiPlay, icon: mdiPlay,
serviceName: "start", serviceName: "start",
disabled: canStart(stateObj), disabled: !canStart(stateObj),
}; };
}, },
stop: (stateObj) => ({ stop: (stateObj) => ({