mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-12 20:06:33 +00:00
Check for empty logs (#22675)
* Fix download logs default lines + translations + iOS, add live logs indicator * Fix rtl in error-log-card * Fix downloadFileSupported
This commit is contained in:
parent
38da01abfa
commit
e908fbb48e
@ -264,6 +264,7 @@ export interface ExternalConfig {
|
||||
hasAssist: boolean;
|
||||
hasBarCodeScanner: number;
|
||||
canSetupImprov: boolean;
|
||||
downloadFileSupported: boolean;
|
||||
}
|
||||
|
||||
export class ExternalMessaging {
|
||||
|
@ -17,19 +17,21 @@ import type { HomeAssistant } from "../../../types";
|
||||
import { fileDownload } from "../../../util/file_download";
|
||||
import type { DownloadLogsDialogParams } from "./show-dialog-download-logs";
|
||||
|
||||
const DEFAULT_LINE_COUNT = 500;
|
||||
|
||||
@customElement("dialog-download-logs")
|
||||
class DownloadLogsDialog extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _dialogParams?: DownloadLogsDialogParams;
|
||||
|
||||
@state() private _lineCount = 100;
|
||||
@state() private _lineCount = DEFAULT_LINE_COUNT;
|
||||
|
||||
@query("ha-md-dialog") private _dialogElement!: HaMdDialog;
|
||||
|
||||
public showDialog(dialogParams: DownloadLogsDialogParams) {
|
||||
this._dialogParams = dialogParams;
|
||||
this._lineCount = this._dialogParams?.defaultLineCount ?? 100;
|
||||
this._lineCount = this._dialogParams?.defaultLineCount || 500;
|
||||
}
|
||||
|
||||
public closeDialog() {
|
||||
@ -38,7 +40,7 @@ class DownloadLogsDialog extends LitElement {
|
||||
|
||||
private _dialogClosed() {
|
||||
this._dialogParams = undefined;
|
||||
this._lineCount = 100;
|
||||
this._lineCount = DEFAULT_LINE_COUNT;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
@ -48,7 +50,7 @@ class DownloadLogsDialog extends LitElement {
|
||||
}
|
||||
|
||||
const numberOfLinesOptions = [100, 500, 1000, 5000, 10000];
|
||||
if (!numberOfLinesOptions.includes(this._lineCount)) {
|
||||
if (!numberOfLinesOptions.includes(this._lineCount) && this._lineCount) {
|
||||
numberOfLinesOptions.push(this._lineCount);
|
||||
numberOfLinesOptions.sort((a, b) => a - b);
|
||||
}
|
||||
@ -63,7 +65,7 @@ class DownloadLogsDialog extends LitElement {
|
||||
.path=${mdiClose}
|
||||
></ha-icon-button>
|
||||
<span slot="title" id="dialog-light-color-favorite-title">
|
||||
${this.hass.localize("ui.panel.config.logs.download_full_log")}
|
||||
${this.hass.localize("ui.panel.config.logs.download_logs")}
|
||||
</span>
|
||||
<span slot="subtitle">
|
||||
${this._dialogParams.header}${this._dialogParams.boot === 0
|
||||
@ -95,7 +97,7 @@ class DownloadLogsDialog extends LitElement {
|
||||
<ha-button @click=${this.closeDialog}>
|
||||
${this.hass.localize("ui.common.cancel")}
|
||||
</ha-button>
|
||||
<ha-button @click=${this._dowloadLogs}>
|
||||
<ha-button @click=${this._downloadLogs}>
|
||||
${this.hass.localize("ui.common.download")}
|
||||
</ha-button>
|
||||
</div>
|
||||
@ -103,7 +105,7 @@ class DownloadLogsDialog extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private async _dowloadLogs() {
|
||||
private async _downloadLogs() {
|
||||
const provider = this._dialogParams!.provider;
|
||||
const boot = this._dialogParams!.boot;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import {
|
||||
mdiArrowCollapseDown,
|
||||
mdiCircle,
|
||||
mdiDownload,
|
||||
mdiMenuDown,
|
||||
mdiRefresh,
|
||||
@ -40,10 +41,14 @@ import {
|
||||
fetchHassioBoots,
|
||||
fetchHassioLogs,
|
||||
fetchHassioLogsFollow,
|
||||
getHassioLogDownloadLinesUrl,
|
||||
getHassioLogDownloadUrl,
|
||||
} from "../../../data/hassio/supervisor";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { fileDownload } from "../../../util/file_download";
|
||||
import {
|
||||
downloadFileSupported,
|
||||
fileDownload,
|
||||
} from "../../../util/file_download";
|
||||
import type { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||
import type { ConnectionStatus } from "../../../data/connection-status";
|
||||
import { atLeastVersion } from "../../../common/config/version";
|
||||
@ -109,6 +114,10 @@ class ErrorLogCard extends LitElement {
|
||||
|
||||
@state() private _boots?: number[];
|
||||
|
||||
@state() private _downloadSupported;
|
||||
|
||||
@state() private _logsFileLink;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div class="error-log-intro">
|
||||
@ -176,13 +185,32 @@ class ErrorLogCard extends LitElement {
|
||||
</ha-menu>
|
||||
`
|
||||
: nothing}
|
||||
<ha-icon-button
|
||||
.path=${mdiDownload}
|
||||
@click=${this._downloadFullLog}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.logs.download_full_log"
|
||||
)}
|
||||
></ha-icon-button>
|
||||
${this._downloadSupported
|
||||
? html`
|
||||
<ha-icon-button
|
||||
.path=${mdiDownload}
|
||||
@click=${this._downloadLogs}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.logs.download_logs"
|
||||
)}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: this._logsFileLink
|
||||
? html`
|
||||
<a
|
||||
href=${this._logsFileLink}
|
||||
target="_blank"
|
||||
class="download-link"
|
||||
>
|
||||
<ha-icon-button
|
||||
.path=${mdiDownload}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.logs.download_logs"
|
||||
)}
|
||||
></ha-icon-button>
|
||||
</a>
|
||||
`
|
||||
: nothing}
|
||||
${!this._streamSupported || this._error
|
||||
? html`<ha-icon-button
|
||||
.path=${mdiRefresh}
|
||||
@ -242,13 +270,27 @@ class ErrorLogCard extends LitElement {
|
||||
slot="trailingIcon"
|
||||
></ha-svg-icon>
|
||||
</ha-button>
|
||||
${this._streamSupported &&
|
||||
this._loadingState !== "loading" &&
|
||||
!this._error
|
||||
? html`<div class="live-indicator">
|
||||
<ha-svg-icon path=${mdiCircle}></ha-svg-icon>
|
||||
Live
|
||||
</div>`
|
||||
: nothing}
|
||||
</ha-card>
|
||||
${this.show === false
|
||||
? html`
|
||||
<ha-button outlined @click=${this._downloadFullLog}>
|
||||
<ha-svg-icon .path=${mdiDownload}></ha-svg-icon>
|
||||
${this.hass.localize("ui.panel.config.logs.download_full_log")}
|
||||
</ha-button>
|
||||
${this._downloadSupported
|
||||
? html`
|
||||
<ha-button outlined @click=${this._downloadLogs}>
|
||||
<ha-svg-icon .path=${mdiDownload}></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.logs.download_logs"
|
||||
)}
|
||||
</ha-button>
|
||||
`
|
||||
: nothing}
|
||||
<mwc-button raised @click=${this._showLogs}>
|
||||
${this.hass.localize("ui.panel.config.logs.load_logs")}
|
||||
</mwc-button>
|
||||
@ -268,6 +310,9 @@ class ErrorLogCard extends LitElement {
|
||||
11
|
||||
);
|
||||
}
|
||||
if (this._downloadSupported === undefined && this.hass) {
|
||||
this._downloadSupported = downloadFileSupported(this.hass);
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
@ -331,7 +376,7 @@ class ErrorLogCard extends LitElement {
|
||||
);
|
||||
}
|
||||
|
||||
private async _downloadFullLog(): Promise<void> {
|
||||
private async _downloadLogs(): Promise<void> {
|
||||
if (this._streamSupported) {
|
||||
showDownloadLogsDialog(this, {
|
||||
header: this.header,
|
||||
@ -378,6 +423,18 @@ class ErrorLogCard extends LitElement {
|
||||
isComponentLoaded(this.hass, "hassio") &&
|
||||
this.provider
|
||||
) {
|
||||
// check if there are any logs at all
|
||||
const testResponse = await fetchHassioLogs(
|
||||
this.hass,
|
||||
this.provider,
|
||||
`entries=:-1:`,
|
||||
this._boot
|
||||
);
|
||||
const testLogs = await testResponse.text();
|
||||
if (!testLogs.trim()) {
|
||||
this._loadingState = "empty";
|
||||
}
|
||||
|
||||
const response = await fetchHassioLogsFollow(
|
||||
this.hass,
|
||||
this.provider,
|
||||
@ -438,6 +495,17 @@ class ErrorLogCard extends LitElement {
|
||||
} else {
|
||||
this._newLogsIndicator = true;
|
||||
}
|
||||
|
||||
if (!this._downloadSupported) {
|
||||
const downloadUrl = getHassioLogDownloadLinesUrl(
|
||||
this.provider,
|
||||
this._numberOfLines,
|
||||
this._boot
|
||||
);
|
||||
getSignedPath(this.hass, downloadUrl).then((signedUrl) => {
|
||||
this._logsFileLink = signedUrl.path;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -597,6 +665,9 @@ class ErrorLogCard extends LitElement {
|
||||
}
|
||||
|
||||
static styles: CSSResultGroup = css`
|
||||
:host {
|
||||
direction: var(--direction);
|
||||
}
|
||||
.error-log-intro {
|
||||
text-align: center;
|
||||
margin: 16px;
|
||||
@ -646,7 +717,7 @@ class ErrorLogCard extends LitElement {
|
||||
position: relative;
|
||||
font-family: var(--code-font-family, monospace);
|
||||
clear: both;
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
overflow-y: scroll;
|
||||
@ -713,6 +784,36 @@ class ErrorLogCard extends LitElement {
|
||||
--ha-assist-chip-container-shape: 10px;
|
||||
--md-assist-chip-trailing-space: 8px;
|
||||
}
|
||||
|
||||
@keyframes breathe {
|
||||
from {
|
||||
opacity: 0.8;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.live-indicator {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
inset-inline-end: 16px;
|
||||
border-top-right-radius: 8px;
|
||||
border-top-left-radius: 8px;
|
||||
background-color: var(--primary-color);
|
||||
color: var(--text-primary-color);
|
||||
padding: 4px 8px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.live-indicator ha-svg-icon {
|
||||
animation: breathe 1s cubic-bezier(0.5, 0, 1, 1) infinite alternate;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.download-link {
|
||||
color: var(--text-color);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@ -2492,7 +2492,7 @@
|
||||
"show_full_logs": "Show full logs",
|
||||
"select_number_of_lines": "Select number of lines to download",
|
||||
"lines": "Lines",
|
||||
"download_full_log": "Download full log",
|
||||
"download_logs": "Download logs",
|
||||
"scroll_down_button": "New logs - Click to scroll",
|
||||
"provider_not_found": "Log provider not found",
|
||||
"provider_not_available": "Logs for ''{provider}'' are not available on your system.",
|
||||
|
@ -1,3 +1,6 @@
|
||||
import type { HomeAssistant } from "../types";
|
||||
import { isIosApp } from "./is_ios";
|
||||
|
||||
export const fileDownload = (href: string, filename = ""): void => {
|
||||
const a = document.createElement("a");
|
||||
a.target = "_blank";
|
||||
@ -8,3 +11,6 @@ export const fileDownload = (href: string, filename = ""): void => {
|
||||
a.dispatchEvent(new MouseEvent("click"));
|
||||
document.body.removeChild(a);
|
||||
};
|
||||
|
||||
export const downloadFileSupported = (hass: HomeAssistant): boolean =>
|
||||
!isIosApp(hass) || !!hass.auth.external?.config.downloadFileSupported;
|
||||
|
5
src/util/is_ios.ts
Normal file
5
src/util/is_ios.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import type { HomeAssistant } from "../types";
|
||||
import { isSafari } from "./is_safari";
|
||||
|
||||
export const isIosApp = (hass: HomeAssistant): boolean =>
|
||||
isSafari && !!hass.auth.external;
|
Loading…
x
Reference in New Issue
Block a user