20231027.0 (#18448)

This commit is contained in:
Bram Kragten 2023-10-27 16:55:37 +02:00 committed by GitHub
commit 3d674cf237
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 138 additions and 32 deletions

View File

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

View File

@ -14,7 +14,7 @@ export const slugify = (value: string, delimiter = "_") => {
.toString()
.toLowerCase()
.replace(p, (c) => b.charAt(a.indexOf(c))) // Replace special characters
.replace(/(?<=\d),(?=\d)/g, "") // Remove Commas between numbers
.replace(/(\d),(?=\d)/g, "$1") // Remove Commas between numbers
.replace(/[^a-z0-9]+/g, delimiter) // Replace all non-word characters
.replace(new RegExp(`(${delimiter})\\1+`, "g"), "$1") // Replace multiple delimiters with single delimiter
.replace(new RegExp(`^${delimiter}+`), "") // Trim delimiter from start of text

View File

@ -20,6 +20,10 @@ export class HaButton extends Button {
.trailing-icon {
display: flex;
}
.slot-container {
width: 100%;
overflow: hidden;
}
`,
];
}

View File

@ -46,6 +46,8 @@ export class HaDateRangePicker extends LitElement {
@property() public ranges?: DateRangePickerRanges | false;
@state() private _ranges?: DateRangePickerRanges;
@property() public autoApply = false;
@property() public timePicker = true;
@ -93,7 +95,7 @@ export class HaDateRangePicker extends LitElement {
}
);
this.ranges = {
this._ranges = {
[this.hass.localize("ui.components.date-range-picker.ranges.today")]: [
calcDate(today, startOfDay, this.hass.locale, this.hass.config, {
weekStartsOn,
@ -206,14 +208,14 @@ export class HaDateRangePicker extends LitElement {
.path=${mdiCalendar}
></ha-icon-button>`}
</div>
${this.ranges
${this.ranges !== false && (this.ranges || this._ranges)
? html`<div
slot="ranges"
class="date-range-ranges"
.dir=${this._rtlDirection}
>
<mwc-list @action=${this._setDateRange} activatable>
${Object.keys(this.ranges).map(
${Object.keys(this.ranges || this._ranges!).map(
(name) => html`<mwc-list-item>${name}</mwc-list-item>`
)}
</mwc-list>
@ -234,7 +236,9 @@ export class HaDateRangePicker extends LitElement {
}
private _setDateRange(ev: CustomEvent<ActionDetail>) {
const dateRange = Object.values(this.ranges!)[ev.detail.index];
const dateRange = Object.values(this.ranges || this._ranges!)[
ev.detail.index
];
const dateRangePicker = this._dateRangePicker;
dateRangePicker.clickRange(dateRange);
dateRangePicker.clickedApply();

View File

@ -94,6 +94,8 @@ export class HaDialog extends DialogBase {
}
.mdc-dialog__title {
padding: 24px 24px 0 24px;
text-overflow: ellipsis;
overflow: hidden;
}
.mdc-dialog__actions {
padding: 12px 24px 12px 24px;

View File

@ -200,6 +200,8 @@ export class EntityRegistrySettingsEditor extends LitElement {
this._name = this.entry.name || "";
this._icon = this.entry.icon || "";
this._deviceClass =
this.entry.device_class || this.entry.original_device_class;
this._origEntityId = this.entry.entity_id;
this._areaId = this.entry.area_id;
this._entityId = this.entry.entity_id;

View File

@ -1,5 +1,12 @@
import { mdiPlus } from "@mdi/js";
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoize from "memoize-one";
import { stringCompare } from "../../../../common/string/compare";
@ -7,6 +14,7 @@ import {
DataTableColumnContainer,
RowClickedEvent,
} from "../../../../components/data-table/ha-data-table";
import "../../../../components/ha-card";
import "../../../../components/ha-fab";
import "../../../../components/ha-svg-icon";
import {
@ -21,7 +29,9 @@ import {
showConfirmationDialog,
} from "../../../../dialogs/generic/show-dialog-box";
import "../../../../layouts/hass-loading-screen";
import "../../../../layouts/hass-subpage";
import "../../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../../resources/styles";
import { HomeAssistant, Route } from "../../../../types";
import { loadLovelaceResources } from "../../../lovelace/common/load-resources";
import { lovelaceTabs } from "../ha-config-lovelace";
@ -72,6 +82,36 @@ export class HaConfigLovelaceRescources extends LitElement {
return html` <hass-loading-screen></hass-loading-screen> `;
}
if (this.hass.config.safe_mode) {
return html`
<hass-subpage
.hass=${this.hass}
.narrow=${this.narrow}
back-path="/config"
.header=${this.hass.localize(
"ui.panel.config.lovelace.resources.caption"
)}
>
<div class="content">
<ha-card outlined>
<div class="card-content">
<h2>
${this.hass.localize(
"ui.panel.config.lovelace.resources.unavailable"
)}
</h2>
<p>
${this.hass.localize(
"ui.panel.config.lovelace.resources.unavailable_safe_mode"
)}
</p>
</div>
</ha-card>
</div>
</hass-subpage>
`;
}
return html`
<hass-tabs-subpage-data-table
.hass=${this.hass}
@ -192,4 +232,24 @@ export class HaConfigLovelaceRescources extends LitElement {
},
});
}
static get styles(): CSSResultGroup {
return [
haStyle,
css`
.content {
padding: 28px 20px 0;
max-width: 1040px;
margin: 0 auto;
}
h2 {
margin-top: 0;
margin-bottom: 12px;
}
p {
margin: 0;
}
`,
];
}
}

View File

@ -125,7 +125,7 @@ class HaPanelDevState extends LitElement {
autofocus
.hass=${this.hass}
.value=${this._entityId}
@change=${this._entityIdChanged}
@value-changed=${this._entityIdChanged}
allow-custom-entity
item-label-path="entity_id"
></ha-entity-picker>
@ -347,7 +347,8 @@ class HaPanelDevState extends LitElement {
ev.preventDefault();
}
private _entityIdChanged() {
private _entityIdChanged(ev: CustomEvent) {
this._entityId = ev.detail.value;
if (!this._entityId) {
this._entity = undefined;
this._state = "";

View File

@ -48,6 +48,9 @@ class PanelEnergy extends LitElement {
if (oldHass?.locale !== this.hass.locale) {
this._setLovelace();
}
if (oldHass && oldHass.localize !== this.hass.localize) {
this._reloadView();
}
}
protected render(): TemplateResult {

View File

@ -135,10 +135,14 @@ export class HuiTodoListCard
public hassSubscribe(): Promise<UnsubscribeFunc>[] {
return [
this.hass!.connection.subscribeEvents(
() => this._fetchData(),
"shopping_list_updated"
),
this.hass!.connection.subscribeEvents(() => {
if (
this._entityId &&
this.hass!.entities[this._entityId]?.platform === "shopping_list"
) {
this._fetchData();
}
}, "shopping_list_updated"),
];
}
@ -159,6 +163,15 @@ export class HuiTodoListCard
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
if (
this._entityId &&
oldHass &&
oldHass.states[this._entityId] !== this.hass.states[this._entityId] &&
this.hass.entities[this._entityId]?.platform !== "shopping_list"
) {
this._fetchData();
}
}
protected render() {

View File

@ -10,11 +10,6 @@ export const loadLovelaceResources = (
resources: NonNullable<LovelaceResource[]>,
hass: HomeAssistant
) => {
// Don't load ressources on safe mode
// Sometimes, hass.config is null but it should not.
if (hass.config?.safe_mode) {
return;
}
resources.forEach((resource) => {
const normalizedUrl = new URL(
resource.url,

View File

@ -65,7 +65,7 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) {
@state() _endDate?: Date;
@state() private _ranges?: DateRangePickerRanges;
@state() private _ranges: DateRangePickerRanges = {};
@state() private _compare = false;

View File

@ -2,10 +2,10 @@ import { ResizeController } from "@lit-labs/observers/resize-controller";
import "@material/mwc-list";
import {
mdiChevronDown,
mdiCommentProcessingOutline,
mdiDelete,
mdiDotsVertical,
mdiInformationOutline,
mdiMicrophone,
mdiPlus,
} from "@mdi/js";
import {
@ -173,11 +173,13 @@ class PanelTodo extends LitElement {
.x=${this.mobile ? 0 : undefined}
>
<ha-button slot="trigger">
<div>
${this._entityId
? this._entityId in this.hass.states
? computeStateName(this.hass.states[this._entityId])
: this._entityId
: ""}
</div>
<ha-svg-icon
slot="trailingIcon"
.path=${mdiChevronDown}
@ -190,7 +192,7 @@ class PanelTodo extends LitElement {
${this.hass.localize("ui.panel.todo.create_list")}
</ha-list-item>
</ha-button-menu>`
: "Lists"}
: this.hass.localize("panel.todo")}
</div>
<mwc-list slot="pane" activatable>${listItems}</mwc-list>
<ha-list-item graphic="icon" slot="pane-footer" @click=${this._addList}>
@ -216,8 +218,9 @@ class PanelTodo extends LitElement {
: nothing}
<li divider role="separator"></li>
<ha-list-item graphic="icon" @click=${this._showVoiceCommandDialog}>
<ha-svg-icon .path=${mdiMicrophone} slot="graphic"> </ha-svg-icon>
${this.hass.localize("ui.panel.todo.start_conversation")}
<ha-svg-icon .path=${mdiCommentProcessingOutline} slot="graphic">
</ha-svg-icon>
${this.hass.localize("ui.panel.todo.assist")}
</ha-list-item>
${entityRegistryEntry?.platform === "local_todo"
? html` <li divider role="separator"></li>
@ -335,11 +338,18 @@ class PanelTodo extends LitElement {
:host([mobile]) .lists {
--mdc-menu-min-width: 100vw;
}
:host(:not([mobile])) .lists ha-list-item {
max-width: calc(100vw - 120px);
}
:host([mobile]) ha-button-menu {
--mdc-shape-medium: 0 0 var(--mdc-shape-medium)
var(--mdc-shape-medium);
}
ha-button-menu {
max-width: 100%;
}
ha-button-menu ha-button {
max-width: 100%;
--mdc-theme-primary: currentColor;
--mdc-typography-button-text-transform: none;
--mdc-typography-button-font-size: var(
@ -360,6 +370,13 @@ class PanelTodo extends LitElement {
);
--button-height: 40px;
}
ha-button-menu ha-button div {
text-overflow: ellipsis;
width: 100%;
overflow: hidden;
white-space: nowrap;
display: block;
}
`,
];
}

View File

@ -274,6 +274,10 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
// on reconnect always fetch config as we might miss an update while we were disconnected
// @ts-ignore
this.hass!.callWS({ type: "get_config" }).then((config: HassConfig) => {
if (config.safe_mode) {
// @ts-ignore Firefox supports forceGet
location.reload(true);
}
this._updateHass({ config });
this.checkDataBaseMigration();
});

View File

@ -2140,6 +2140,8 @@
"js": "JavaScript file (deprecated)",
"module": "JavaScript module"
},
"unavailable": "Resources unavailable",
"unavailable_safe_mode": "Resources are not available in safe mode",
"picker": {
"headers": {
"url": "URL",
@ -4520,7 +4522,6 @@
"never_triggered": "Never triggered"
},
"todo-list": {
"lists": "To-do Lists",
"checked_items": "Checked items",
"clear_items": "Clear checked items",
"add_item": "Add item",
@ -5094,7 +5095,7 @@
"description": "The Sensor card gives you a quick overview of your sensors state with an optional graph to visualize change over time."
},
"todo-list": {
"name": "Todo list",
"name": "To-do list",
"description": "The to-do list card allows you to add, edit, check-off, and clear items from your to-do list.",
"integration_not_loaded": "This card requires the `todo` integration to be set up."
},
@ -5515,7 +5516,7 @@
}
},
"todo": {
"start_conversation": "Start conversation",
"assist": "[%key:ui::panel::lovelace::menu::assist%]",
"create_list": "Create list",
"delete_list": "Delete list",
"information": "Information",