From 6e8c1f1a634a6ba61266edddc8ae74114a4aecba Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 7 Nov 2024 09:53:34 +0100 Subject: [PATCH 01/12] Update value of password field on change event (#22706) --- src/components/ha-password-field.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/ha-password-field.ts b/src/components/ha-password-field.ts index f149264fdb8a..15fd9666dd34 100644 --- a/src/components/ha-password-field.ts +++ b/src/components/ha-password-field.ts @@ -117,8 +117,8 @@ export class HaPasswordField extends LitElement { .autocapitalize=${this.autocapitalize} .type=${this._unmaskedPassword ? "text" : "password"} .suffix=${html`
`} - @input=${this._handleInputChange} - @change=${this._reDispatchEvent} + @input=${this._handleInputEvent} + @change=${this._handleChangeEvent} > Date: Thu, 7 Nov 2024 09:40:18 +0100 Subject: [PATCH 02/12] Fix typo for fixed background attribute (#22707) --- src/panels/lovelace/views/hui-view-container.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/views/hui-view-container.ts b/src/panels/lovelace/views/hui-view-container.ts index 6ea5969dea36..bf74f55dc654 100644 --- a/src/panels/lovelace/views/hui-view-container.ts +++ b/src/panels/lovelace/views/hui-view-container.ts @@ -47,7 +47,7 @@ class HuiViewContainer extends LitElement { private _isFixedBackground(background?: BackgroundConfig) { if (typeof background === "string") { - return background.includes(" fixed"); + return background.split(" ").includes("fixed"); } return false; } @@ -126,7 +126,7 @@ class HuiViewContainer extends LitElement { ); background-attachment: scroll !important; } - :host(:not(fixed-background)) { + :host(:not([fixed-background])) { background: var( --view-background, var(--lovelace-background, var(--primary-background-color)) From 1181ddcbbfe164d29089e025c23019b39480e31d Mon Sep 17 00:00:00 2001 From: Wendelin <12148533+wendevlin@users.noreply.github.com> Date: Thu, 7 Nov 2024 09:45:58 +0100 Subject: [PATCH 03/12] Fix hassio logs for core < 2024.11 (#22708) --- src/data/hassio/supervisor.ts | 9 +++++++++ src/panels/config/logs/error-log-card.ts | 4 ++-- src/state/connection-mixin.ts | 1 + src/types.ts | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/data/hassio/supervisor.ts b/src/data/hassio/supervisor.ts index a0966d1baeaa..b14ffd8e56c0 100644 --- a/src/data/hassio/supervisor.ts +++ b/src/data/hassio/supervisor.ts @@ -185,6 +185,15 @@ export const fetchHassioInfo = async ( export const fetchHassioBoots = async (hass: HomeAssistant) => hass.callApi>("GET", `hassio/host/logs/boots`); +export const fetchHassioLogsLegacy = async ( + hass: HomeAssistant, + provider: string +) => + hass.callApi( + "GET", + `hassio/${provider.includes("_") ? `addons/${provider}` : provider}/logs` + ); + export const fetchHassioLogs = async ( hass: HomeAssistant, provider: string, diff --git a/src/panels/config/logs/error-log-card.ts b/src/panels/config/logs/error-log-card.ts index 9bd729632bde..3c0239ea07b8 100644 --- a/src/panels/config/logs/error-log-card.ts +++ b/src/panels/config/logs/error-log-card.ts @@ -49,6 +49,7 @@ import { fetchHassioBoots, fetchHassioLogs, fetchHassioLogsFollow, + fetchHassioLogsLegacy, getHassioLogDownloadLinesUrl, getHassioLogDownloadUrl, } from "../../../data/hassio/supervisor"; @@ -545,8 +546,7 @@ class ErrorLogCard extends LitElement { this._streamSupported = false; let logs = ""; if (isComponentLoaded(this.hass, "hassio") && this.provider) { - const repsonse = await fetchHassioLogs(this.hass, this.provider); - logs = await repsonse.text(); + logs = await fetchHassioLogsLegacy(this.hass, this.provider); } else { logs = await fetchErrorLog(this.hass); } diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts index 2a9803d8e8a4..facaa4716fe5 100644 --- a/src/state/connection-mixin.ts +++ b/src/state/connection-mixin.ts @@ -158,6 +158,7 @@ export const connectionMixin = >( }, callApi: async (method, path, parameters, headers) => hassCallApi(auth, method, path, parameters, headers), + // callApiRaw introduced in 2024.11 callApiRaw: async (method, path, parameters, headers, signal) => hassCallApiRaw(auth, method, path, parameters, headers, signal), fetchWithAuth: ( diff --git a/src/types.ts b/src/types.ts index 923258c644f4..0a9a32d036bb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -259,7 +259,7 @@ export interface HomeAssistant { parameters?: Record, headers?: Record ): Promise; - callApiRaw( + callApiRaw( // introduced in 2024.11 method: "GET" | "POST" | "PUT" | "DELETE", path: string, parameters?: Record, From ae33b10cb2f6776249c951b307f54f1fc0a22400 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 7 Nov 2024 10:09:24 +0100 Subject: [PATCH 04/12] Add support for helper text in form boolean (#22711) --- gallery/src/pages/components/ha-form.ts | 1 + src/components/ha-form/ha-form-boolean.ts | 34 +++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/gallery/src/pages/components/ha-form.ts b/gallery/src/pages/components/ha-form.ts index 61495e4f785d..fe877ad1d8c5 100644 --- a/gallery/src/pages/components/ha-form.ts +++ b/gallery/src/pages/components/ha-form.ts @@ -510,6 +510,7 @@ class DemoHaForm extends LitElement { .computeError=${(error) => translations[error] || error} .computeLabel=${(schema) => translations[schema.name] || schema.name} + .computeHelper=${() => "Helper text"} @value-changed=${(e) => { this.data[idx] = e.detail.value; this.requestUpdate(); diff --git a/src/components/ha-form/ha-form-boolean.ts b/src/components/ha-form/ha-form-boolean.ts index b56ccd2d2481..11c7033e0a4d 100644 --- a/src/components/ha-form/ha-form-boolean.ts +++ b/src/components/ha-form/ha-form-boolean.ts @@ -1,6 +1,6 @@ import "@material/mwc-formfield"; -import type { TemplateResult } from "lit"; -import { html, LitElement } from "lit"; +import type { CSSResultGroup, TemplateResult } from "lit"; +import { css, html, LitElement, nothing } from "lit"; import { customElement, property, query } from "lit/decorators"; import { fireEvent } from "../../common/dom/fire_event"; import type { @@ -19,6 +19,8 @@ export class HaFormBoolean extends LitElement implements HaFormElement { @property() public label!: string; + @property() public helper?: string; + @property({ type: Boolean }) public disabled = false; @query("ha-checkbox", true) private _input?: HTMLElement; @@ -37,6 +39,12 @@ export class HaFormBoolean extends LitElement implements HaFormElement { .disabled=${this.disabled} @change=${this._valueChanged} > + +

${this.label}

+ ${this.helper + ? html`

${this.helper}

` + : nothing} +
`; } @@ -46,6 +54,28 @@ export class HaFormBoolean extends LitElement implements HaFormElement { value: (ev.target as HaCheckbox).checked, }); } + + static get styles(): CSSResultGroup { + return css` + ha-formfield { + display: flex; + min-height: 56px; + align-items: center; + --mdc-typography-body2-font-size: 1em; + } + p { + margin: 0; + } + .secondary { + direction: var(--direction); + padding-top: 4px; + box-sizing: border-box; + color: var(--secondary-text-color); + font-size: 0.875rem; + font-weight: var(--mdc-typography-body2-font-weight, 400); + } + `; + } } declare global { From 125ad9c79413d52e53855bf37ec0d99347b0b2e9 Mon Sep 17 00:00:00 2001 From: Wendelin <12148533+wendevlin@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:50:24 +0100 Subject: [PATCH 05/12] Fix logs live-indicator on older boots (#22719) --- src/panels/config/logs/error-log-card.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/panels/config/logs/error-log-card.ts b/src/panels/config/logs/error-log-card.ts index 3c0239ea07b8..e9e0f7dda9d6 100644 --- a/src/panels/config/logs/error-log-card.ts +++ b/src/panels/config/logs/error-log-card.ts @@ -307,6 +307,7 @@ class ErrorLogCard extends LitElement { ${this._streamSupported && this._loadingState !== "loading" && + this._boot === 0 && !this._error ? html`
From 387392713c9365cc34a20f40a4be95dd3f602936 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 7 Nov 2024 21:32:28 +0100 Subject: [PATCH 06/12] move download logs button, switch between raw and normal logs (#22721) --- .../addon-view/log/hassio-addon-log-tab.ts | 1 - src/panels/config/logs/error-log-card.ts | 231 +++++++++--------- src/panels/config/logs/ha-config-logs.ts | 35 +-- src/panels/config/logs/system-log-card.ts | 64 ++++- .../lovelace/cards/hui-recovery-mode-card.ts | 2 +- src/translations/en.json | 7 +- 6 files changed, 197 insertions(+), 143 deletions(-) diff --git a/hassio/src/addon-view/log/hassio-addon-log-tab.ts b/hassio/src/addon-view/log/hassio-addon-log-tab.ts index a40454fe8367..34ce4f462669 100644 --- a/hassio/src/addon-view/log/hassio-addon-log-tab.ts +++ b/hassio/src/addon-view/log/hassio-addon-log-tab.ts @@ -47,7 +47,6 @@ class HassioAddonLogDashboard extends LitElement { .localizeFunc=${this.supervisor.localize} .header=${this.addon.name} .provider=${this.addon.slug} - show .filter=${this._filter} > diff --git a/src/panels/config/logs/error-log-card.ts b/src/panels/config/logs/error-log-card.ts index e9e0f7dda9d6..f9fbe31410ae 100644 --- a/src/panels/config/logs/error-log-card.ts +++ b/src/panels/config/logs/error-log-card.ts @@ -11,6 +11,7 @@ import { mdiRefresh, mdiWrap, mdiWrapDisabled, + mdiFolderTextOutline, } from "@mdi/js"; import { css, @@ -58,7 +59,7 @@ import { downloadFileSupported, fileDownload, } from "../../../util/file_download"; -import type { HASSDomEvent } from "../../../common/dom/fire_event"; +import { fireEvent, type HASSDomEvent } from "../../../common/dom/fire_event"; import type { ConnectionStatus } from "../../../data/connection-status"; import { atLeastVersion } from "../../../common/config/version"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; @@ -79,9 +80,10 @@ class ErrorLogCard extends LitElement { @property() public header?: string; - @property() public provider!: string; + @property() public provider?: string; - @property({ type: Boolean, attribute: true }) public show = false; + @property({ attribute: "allow-switch", type: Boolean }) public allowSwitch = + false; @query(".error-log") private _logElement?: HTMLElement; @@ -130,26 +132,32 @@ class ErrorLogCard extends LitElement { @state() private _wrapLines = true; - @state() private _downloadSupported; + @state() private _downloadSupported?: boolean; - @state() private _logsFileLink; + @state() private _logsFileLink?: string; protected render(): TemplateResult { + const streaming = + this._streamSupported && + this.provider && + isComponentLoaded(this.hass, "hassio") && + this._loadingState !== "loading"; + + const hasBoots = this._streamSupported && Array.isArray(this._boots); + const localize = this.localizeFunc || this.hass.localize; return html`
${this._error ? html`${this._error}` : nothing} - +

${this.header || localize("ui.panel.config.logs.show_full_logs")}

- ${this._streamSupported && - Array.isArray(this._boots) && - this._showBootsSelect + ${hasBoots && this._showBootsSelect ? html` - ${this._boots.map( + ${this._boots!.map( (boot) => html` - ${!this._streamSupported || this._error + ${!streaming || this._error ? html`` : nothing} - ${this._streamSupported && Array.isArray(this._boots) + ${(this.allowSwitch && this.provider === "core") || hasBoots ? html` - - - ${localize( - `ui.panel.config.logs.${this._showBootsSelect ? "hide" : "show"}_haos_boots` - )} - + ${this.allowSwitch && this.provider === "core" + ? html` + + ${this.hass.localize( + "ui.panel.config.logs.show_condensed_logs" + )} + ` + : nothing} + ${hasBoots + ? html` + + ${localize( + `ui.panel.config.logs.${this._showBootsSelect ? "hide" : "show"}_haos_boots` + )} + ` + : nothing} ` : nothing} @@ -305,48 +326,34 @@ class ErrorLogCard extends LitElement { slot="trailingIcon" > - ${this._streamSupported && - this._loadingState !== "loading" && - this._boot === 0 && - !this._error + ${streaming && this._boot === 0 && !this._error ? html`
Live
` : nothing} - ${this.show === false - ? html` - ${this._downloadSupported - ? html` - - - ${localize("ui.panel.config.logs.download_logs")} - - ` - : nothing} - - ${localize("ui.panel.config.logs.load_logs")} - - ` - : nothing}
`; } - public connectedCallback() { - super.connectedCallback(); - - if (this._streamSupported === undefined) { - this._streamSupported = atLeastVersion( - this.hass.config.version, - 2024, - 11 - ); + protected willUpdate(changedProps: PropertyValues) { + super.willUpdate(changedProps); + if (changedProps.has("provider")) { + this._boot = 0; + this._loadLogs(); } - if (this._downloadSupported === undefined && this.hass) { - this._downloadSupported = downloadFileSupported(this.hass); + if (this.hasUpdated) { + return; } + this._streamSupported = atLeastVersion(this.hass.config.version, 2024, 11); + this._downloadSupported = downloadFileSupported(this.hass); + // just needs to be loaded once, because only the host endpoints provide boots information + this._loadBoots(); + + window.addEventListener("connection-status", this._handleConnectionStatus); + + this.hass.loadFragmentTranslation("config"); } protected firstUpdated(changedProps: PropertyValues) { @@ -356,28 +363,11 @@ class ErrorLogCard extends LitElement { this._scrolledToTopController.callback = this._handleTopScroll; this._scrolledToTopController.observe(this._scrollTopMarkerElement!); - - window.addEventListener("connection-status", this._handleConnectionStatus); - - if (this.hass?.config.recovery_mode || this.show) { - this.hass.loadFragmentTranslation("config"); - } - - // just needs to be loaded once, because only the host endpoints provide boots information - this._loadBoots(); } protected updated(changedProps) { super.updated(changedProps); - if ( - (changedProps.has("show") && this.show) || - (changedProps.has("provider") && this.show) - ) { - this._boot = 0; - this._loadLogs(); - } - if (this._newLogsIndicator && this._scrolledToBottomController.value) { this._newLogsIndicator = false; } @@ -411,7 +401,7 @@ class ErrorLogCard extends LitElement { } private async _downloadLogs(): Promise { - if (this._streamSupported) { + if (this._streamSupported && this.provider) { showDownloadLogsDialog(this, { header: this.header, provider: this.provider, @@ -433,10 +423,6 @@ class ErrorLogCard extends LitElement { } } - private _showLogs(): void { - this.show = true; - } - private async _loadLogs(): Promise { this._error = undefined; this._loadingState = "loading"; @@ -448,15 +434,16 @@ class ErrorLogCard extends LitElement { try { if (this._logStreamAborter) { this._logStreamAborter.abort(); + this._logStreamAborter = undefined; } - this._logStreamAborter = new AbortController(); - if ( this._streamSupported && isComponentLoaded(this.hass, "hassio") && this.provider ) { + this._logStreamAborter = new AbortController(); + // check if there are any logs at all const testResponse = await fetchHassioLogs( this.hass, @@ -599,60 +586,62 @@ class ErrorLogCard extends LitElement { if (ev.detail === "disconnected" && this._logStreamAborter) { this._logStreamAborter.abort(); } - if (ev.detail === "connected" && this.show) { + if (ev.detail === "connected") { this._loadLogs(); } }; private async _loadMoreLogs() { if ( - this._firstCursor && - this._loadingPrevState !== "loading" && - this._loadingState === "loaded" && - this._logElement + !this._firstCursor || + this._loadingPrevState === "loading" || + this._loadingState !== "loaded" || + !this._logElement || + !this.provider ) { - const scrolledToBottom = this._scrolledToBottomController.value; - const scrollPositionFromBottom = - this._logElement.scrollHeight - this._logElement.scrollTop; - this._loadingPrevState = "loading"; - const response = await fetchHassioLogs( - this.hass, - this.provider, - `entries=${this._firstCursor}:-100:100`, - this._boot - ); + return; + } + const scrolledToBottom = this._scrolledToBottomController.value; + const scrollPositionFromBottom = + this._logElement.scrollHeight - this._logElement.scrollTop; + this._loadingPrevState = "loading"; + const response = await fetchHassioLogs( + this.hass, + this.provider, + `entries=${this._firstCursor}:-100:100`, + this._boot + ); - if (response.headers.has("X-First-Cursor")) { - if (this._firstCursor === response.headers.get("X-First-Cursor")!) { - this._loadingPrevState = "end"; - return; - } - this._firstCursor = response.headers.get("X-First-Cursor")!; + if (response.headers.has("X-First-Cursor")) { + if (this._firstCursor === response.headers.get("X-First-Cursor")!) { + this._loadingPrevState = "end"; + return; } + this._firstCursor = response.headers.get("X-First-Cursor")!; + } - const body = await response.text(); + const body = await response.text(); - if (body) { - const lines = body - .split("\n") - .filter((line) => line.trim() !== "") - .reverse(); + if (body) { + const lines = body + .split("\n") + .filter((line) => line.trim() !== "") + .reverse(); - this._ansiToHtmlElement?.parseLinesToColoredPre(lines, true); - this._numberOfLines! += lines.length; - this._loadingPrevState = "loaded"; - } else { - this._loadingPrevState = "end"; - } + this._ansiToHtmlElement?.parseLinesToColoredPre(lines, true); + this._numberOfLines! += lines.length; + this._loadingPrevState = "loaded"; + } else { + this._loadingPrevState = "end"; + } - if (scrolledToBottom) { - this._scrollToBottom(); - } else if (this._loadingPrevState !== "end" && this._logElement) { - window.requestAnimationFrame(() => { - this._logElement!.scrollTop = - this._logElement!.scrollHeight - scrollPositionFromBottom; - }); - } + if (scrolledToBottom) { + this._scrollToBottom(); + } else if (this._loadingPrevState !== "end" && this._logElement) { + window.requestAnimationFrame(() => { + this._logElement!.scrollTop = + this._logElement!.scrollHeight - scrollPositionFromBottom; + }); } } @@ -694,7 +683,15 @@ class ErrorLogCard extends LitElement { } private _handleOverflowAction(ev: CustomEvent) { - switch (ev.detail.index) { + let index = ev.detail.index; + if (this.provider === "core") { + index--; + } + switch (index) { + case -1: + // @ts-ignore + fireEvent(this, "switch-log-view"); + break; case 0: this._showBootsSelect = !this._showBootsSelect; break; diff --git a/src/panels/config/logs/ha-config-logs.ts b/src/panels/config/logs/ha-config-logs.ts index 4b15706054c6..3d6ae423c72b 100644 --- a/src/panels/config/logs/ha-config-logs.ts +++ b/src/panels/config/logs/ha-config-logs.ts @@ -3,20 +3,20 @@ import type { CSSResultGroup, TemplateResult } from "lit"; import { css, html, LitElement } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; +import { navigate } from "../../../common/navigate"; import { extractSearchParam } from "../../../common/url/search-params"; -import "../../../components/ha-button-menu"; import "../../../components/ha-button"; +import "../../../components/ha-button-menu"; import "../../../components/search-input"; import type { LogProvider } from "../../../data/error_log"; import { fetchHassioAddonsInfo } from "../../../data/hassio/addon"; +import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-subpage"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, Route } from "../../../types"; import "./error-log-card"; import "./system-log-card"; import type { SystemLogCard } from "./system-log-card"; -import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box"; -import { navigate } from "../../../common/navigate"; const logProviders: LogProvider[] = [ { @@ -57,6 +57,8 @@ export class HaConfigLogs extends LitElement { @state() private _filter = extractSearchParam("filter") || ""; + @state() private _detail = false; + @query("system-log-card") private systemLog?: SystemLogCard; @state() private _selectedLogProvider = "core"; @@ -141,7 +143,7 @@ export class HaConfigLogs extends LitElement { : ""} ${search}
- ${this._selectedLogProvider === "core" + ${this._selectedLogProvider === "core" && !this._detail ? html` p.key === this._selectedLogProvider )!.name} .filter=${this._filter} + @switch-log-view=${this._showDetail} > ` - : ""} - p.key === this._selectedLogProvider - )!.name} - .filter=${this._filter} - .provider=${this._selectedLogProvider} - .show=${this._selectedLogProvider !== "core"} - > + : html` p.key === this._selectedLogProvider + )!.name} + .filter=${this._filter} + .provider=${this._selectedLogProvider} + @switch-log-view=${this._showDetail} + allow-switch + >`}
`; } + private _showDetail() { + this._detail = !this._detail; + } + private _selectProvider(ev) { this._selectedLogProvider = (ev.currentTarget as any).provider; this._filter = ""; diff --git a/src/panels/config/logs/system-log-card.ts b/src/panels/config/logs/system-log-card.ts index 1e1a9d12c120..60ef7284d00a 100644 --- a/src/panels/config/logs/system-log-card.ts +++ b/src/panels/config/logs/system-log-card.ts @@ -1,16 +1,20 @@ -import { mdiRefresh } from "@mdi/js"; import "@material/mwc-list/mwc-list"; +import { mdiDotsVertical, mdiDownload, mdiRefresh, mdiText } from "@mdi/js"; import type { CSSResultGroup } from "lit"; import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../common/dom/fire_event"; import type { LocalizeFunc } from "../../../common/translations/localize"; import "../../../components/buttons/ha-call-service-button"; import "../../../components/buttons/ha-progress-button"; +import "../../../components/ha-button-menu"; import "../../../components/ha-card"; import "../../../components/ha-circular-progress"; import "../../../components/ha-icon-button"; import "../../../components/ha-list-item"; +import { getSignedPath } from "../../../data/auth"; +import { getErrorLogDownloadUrl } from "../../../data/error_log"; import { domainToName } from "../../../data/integration"; import type { LoggedError } from "../../../data/system_log"; import { @@ -19,6 +23,7 @@ import { isCustomIntegrationError, } from "../../../data/system_log"; import type { HomeAssistant } from "../../../types"; +import { fileDownload } from "../../../util/file_download"; import { showSystemLogDetailDialog } from "./show-dialog-system-log-detail"; import { formatSystemLogTime } from "./util"; @@ -104,11 +109,34 @@ export class SystemLogCard extends LitElement { : html`

${this.header || "Logs"}

- +
+ + + + + + + + + ${this.hass.localize( + "ui.panel.config.logs.show_full_logs" + )} + + +
${this._items.length === 0 ? html` @@ -195,6 +223,19 @@ export class SystemLogCard extends LitElement { } } + private _handleOverflowAction() { + // @ts-ignore + fireEvent(this, "switch-log-view"); + } + + private async _downloadLogs() { + const timeString = new Date().toISOString().replace(/:/g, "-"); + const downloadUrl = getErrorLogDownloadUrl; + const logFileName = `home-assistant_${timeString}.log`; + const signedUrl = await getSignedPath(this.hass, downloadUrl); + fileDownload(signedUrl.path, logFileName); + } + private _openLog(ev: Event): void { const item = (ev.currentTarget as any).logItem; showSystemLogDetailDialog(this, { item }); @@ -203,7 +244,7 @@ export class SystemLogCard extends LitElement { static get styles(): CSSResultGroup { return css` ha-card { - padding-top: 16px; + padding-top: 8px; } .header { @@ -212,6 +253,11 @@ export class SystemLogCard extends LitElement { padding: 0 16px; } + .header-buttons { + display: flex; + align-items: center; + } + .card-header { color: var(--ha-card-header-color, var(--primary-text-color)); font-family: var(--ha-card-header-font-family, inherit); @@ -243,6 +289,10 @@ export class SystemLogCard extends LitElement { color: var(--warning-color); } + .card-content { + border-top: 1px solid var(--divider-color); + } + .card-actions, .empty-content { direction: var(--direction); diff --git a/src/panels/lovelace/cards/hui-recovery-mode-card.ts b/src/panels/lovelace/cards/hui-recovery-mode-card.ts index 10102b6dd728..37d979dc19e6 100644 --- a/src/panels/lovelace/cards/hui-recovery-mode-card.ts +++ b/src/panels/lovelace/cards/hui-recovery-mode-card.ts @@ -31,7 +31,7 @@ export class HuiRecoveryModeCard extends LitElement implements LovelaceCard { "ui.panel.lovelace.cards.recovery-mode.description" )}
- +
`; } diff --git a/src/translations/en.json b/src/translations/en.json index 2762e217884c..47865affb5cd 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2470,9 +2470,9 @@ "search": "Search logs", "failed_get_logs": "Failed to get {provider} logs, {error}", "no_issues_search": "No issues found for search term ''{term}''", - "load_logs": "Load full logs", + "load_logs": "Load logs", "nr_of_lines": "Number of lines", - "loading_log": "Loading full log…", + "loading_log": "Loading log…", "no_errors": "No errors have been reported", "no_issues": "There are no new issues!", "clear": "Clear", @@ -2489,7 +2489,8 @@ }, "custom_integration": "custom integration", "error_from_custom_integration": "This error originated from a custom integration.", - "show_full_logs": "Show full logs", + "show_full_logs": "Show raw logs", + "show_condensed_logs": "Show condensed logs", "select_number_of_lines": "Select number of lines to download", "lines": "Lines", "download_logs": "Download logs", From 17b6bf06733c0c94bb94f1d3ef8287c4f6ff5a2e Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 7 Nov 2024 17:33:18 +0100 Subject: [PATCH 07/12] Enable auto-scroll for drag and drop (#22725) --- src/components/ha-sortable.ts | 4 ++++ src/resources/sortable.ts | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/ha-sortable.ts b/src/components/ha-sortable.ts index 2dc997440020..88feb7dfbafe 100644 --- a/src/components/ha-sortable.ts +++ b/src/components/ha-sortable.ts @@ -135,6 +135,10 @@ export class HaSortable extends LitElement { const Sortable = (await import("../resources/sortable")).default; const options: SortableInstance.Options = { + scroll: true, + // Force the autoscroll fallback because it works better than the native one + forceAutoScrollFallback: true, + scrollSpeed: 20, animation: 150, ...this.options, onChoose: this._handleChoose, diff --git a/src/resources/sortable.ts b/src/resources/sortable.ts index 27b2f27953b7..6db53f011770 100644 --- a/src/resources/sortable.ts +++ b/src/resources/sortable.ts @@ -1,10 +1,11 @@ import type Sortable from "sortablejs"; import SortableCore, { - OnSpill, AutoScroll, + OnSpill, } from "sortablejs/modular/sortable.core.esm"; -SortableCore.mount(OnSpill, new AutoScroll()); +SortableCore.mount(OnSpill); +SortableCore.mount(new AutoScroll()); export default SortableCore as typeof Sortable; From 8a4b96f1ff9bc6e6a2869fceb572870aa1bcee17 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 7 Nov 2024 21:40:38 +0100 Subject: [PATCH 08/12] Bumped version to 20241106.1 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index eeaa6db0632c..2f96e9ee760a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20241106.0" +version = "20241106.1" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md" From 722ccc017f57235439f9aa0e66fa3b43cd405b9e Mon Sep 17 00:00:00 2001 From: tzagim <2285958+tzagim@users.noreply.github.com> Date: Fri, 8 Nov 2024 10:16:42 +0200 Subject: [PATCH 09/12] Fix for RTL languages in logs (#22727) Fix for RTL Languages (log) --- src/panels/config/logs/error-log-card.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/config/logs/error-log-card.ts b/src/panels/config/logs/error-log-card.ts index f9fbe31410ae..d804ae56d30e 100644 --- a/src/panels/config/logs/error-log-card.ts +++ b/src/panels/config/logs/error-log-card.ts @@ -768,8 +768,8 @@ class ErrorLogCard extends LitElement { overflow-y: scroll; min-height: var(--error-log-card-height, calc(100vh - 240px)); max-height: var(--error-log-card-height, calc(100vh - 240px)); - border-top: 1px solid var(--divider-color); + direction: ltr; } @media all and (max-width: 870px) { From e5e84acd07b97cfa0c68a90815f5b0bf97f2ae41 Mon Sep 17 00:00:00 2001 From: Wendelin <12148533+wendevlin@users.noreply.github.com> Date: Fri, 8 Nov 2024 11:00:54 +0100 Subject: [PATCH 10/12] Fix join-beta text (#22733) --- src/panels/config/core/updates/dialog-join-beta.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/config/core/updates/dialog-join-beta.ts b/src/panels/config/core/updates/dialog-join-beta.ts index 5a96530f36ca..7b4d7381c56c 100644 --- a/src/panels/config/core/updates/dialog-join-beta.ts +++ b/src/panels/config/core/updates/dialog-join-beta.ts @@ -48,7 +48,7 @@ export class DialogJoinBeta ${this.hass.localize("ui.dialogs.join_beta_channel.backup")}

- ${this.hass.localize("ui.dialogs.join_beta_channel.warning")} + ${this.hass.localize("ui.dialogs.join_beta_channel.warning")}.
${this.hass.localize("ui.dialogs.join_beta_channel.release_items")}

    From 25c02b1219732dc7e096c2f37c464cce2279b9e1 Mon Sep 17 00:00:00 2001 From: Wendelin <12148533+wendevlin@users.noreply.github.com> Date: Fri, 8 Nov 2024 12:39:21 +0100 Subject: [PATCH 11/12] Fix live-logs loading (#22737) --- src/panels/config/logs/error-log-card.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/panels/config/logs/error-log-card.ts b/src/panels/config/logs/error-log-card.ts index d804ae56d30e..961af26baadd 100644 --- a/src/panels/config/logs/error-log-card.ts +++ b/src/panels/config/logs/error-log-card.ts @@ -339,6 +339,18 @@ class ErrorLogCard extends LitElement { protected willUpdate(changedProps: PropertyValues) { super.willUpdate(changedProps); + if ( + this._downloadSupported === undefined || + this._streamSupported === undefined + ) { + this._downloadSupported = downloadFileSupported(this.hass); + this._streamSupported = atLeastVersion( + this.hass.config.version, + 2024, + 11 + ); + } + if (changedProps.has("provider")) { this._boot = 0; this._loadLogs(); @@ -346,8 +358,6 @@ class ErrorLogCard extends LitElement { if (this.hasUpdated) { return; } - this._streamSupported = atLeastVersion(this.hass.config.version, 2024, 11); - this._downloadSupported = downloadFileSupported(this.hass); // just needs to be loaded once, because only the host endpoints provide boots information this._loadBoots(); From 188fe44c2eeb63d0037d66f1581702181477b537 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 8 Nov 2024 13:01:19 +0100 Subject: [PATCH 12/12] Bumped version to 20241106.2 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2f96e9ee760a..e3ec31a2dfd3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "home-assistant-frontend" -version = "20241106.1" +version = "20241106.2" license = {text = "Apache-2.0"} description = "The Home Assistant frontend" readme = "README.md"