281 lines
8.4 KiB
TypeScript
281 lines
8.4 KiB
TypeScript
import { mdiPower } from "@mdi/js";
|
|
import type { CSSResultGroup, TemplateResult } from "lit";
|
|
import { css, html, LitElement } from "lit";
|
|
import { customElement, property, state } from "lit/decorators";
|
|
import { canShowPage } from "../../../common/config/can_show_page";
|
|
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
|
import { relativeTime } from "../../../common/datetime/relative_time";
|
|
import { blankBeforePercent } from "../../../common/translations/blank_before_percent";
|
|
import "../../../components/ha-card";
|
|
import "../../../components/ha-icon-button";
|
|
import "../../../components/ha-navigation-list";
|
|
import type { BackupContent } from "../../../data/backup";
|
|
import { fetchBackupInfo } from "../../../data/backup";
|
|
import type { CloudStatus } from "../../../data/cloud";
|
|
import { fetchCloudStatus } from "../../../data/cloud";
|
|
import type { HardwareInfo } from "../../../data/hardware";
|
|
import { BOARD_NAMES } from "../../../data/hardware";
|
|
import type {
|
|
HassioHassOSInfo,
|
|
HassioHostInfo,
|
|
} from "../../../data/hassio/host";
|
|
import {
|
|
fetchHassioHassOsInfo,
|
|
fetchHassioHostInfo,
|
|
} from "../../../data/hassio/host";
|
|
import { showRestartDialog } from "../../../dialogs/restart/show-dialog-restart";
|
|
import "../../../layouts/hass-subpage";
|
|
import { haStyle } from "../../../resources/styles";
|
|
import type { HomeAssistant } from "../../../types";
|
|
import "../ha-config-section";
|
|
import { configSections } from "../ha-panel-config";
|
|
|
|
@customElement("ha-config-system-navigation")
|
|
class HaConfigSystemNavigation extends LitElement {
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
|
|
@property({ type: Boolean, reflect: true }) public narrow = false;
|
|
|
|
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
|
|
|
|
@property({ attribute: false }) public cloudStatus?: CloudStatus;
|
|
|
|
@property({ attribute: false }) public showAdvanced = false;
|
|
|
|
@state() private _latestBackupDate?: Date;
|
|
|
|
@state() private _boardName?: string;
|
|
|
|
@state() private _storageInfo?: { used: number; free: number; total: number };
|
|
|
|
@state() private _externalAccess = false;
|
|
|
|
protected render(): TemplateResult {
|
|
const pages = configSections.general
|
|
.filter((page) => canShowPage(this.hass, page))
|
|
.map((page) => {
|
|
let description = "";
|
|
|
|
switch (page.translationKey) {
|
|
case "backup":
|
|
description = this._latestBackupDate
|
|
? this.hass.localize("ui.panel.config.backup.description", {
|
|
relative_time: relativeTime(
|
|
this._latestBackupDate,
|
|
this.hass.locale
|
|
),
|
|
})
|
|
: this.hass.localize(
|
|
"ui.panel.config.backup.description_no_backup"
|
|
);
|
|
break;
|
|
case "network":
|
|
description = this.hass.localize(
|
|
"ui.panel.config.network.description",
|
|
{
|
|
state: this._externalAccess
|
|
? this.hass.localize("ui.panel.config.network.enabled")
|
|
: this.hass.localize("ui.panel.config.network.disabled"),
|
|
}
|
|
);
|
|
break;
|
|
case "storage":
|
|
description = this._storageInfo
|
|
? this.hass.localize("ui.panel.config.storage.description", {
|
|
percent_used: `${Math.round(
|
|
(this._storageInfo.used / this._storageInfo.total) * 100
|
|
)}${blankBeforePercent(this.hass.locale)}%`,
|
|
free_space: `${this._storageInfo.free} GB`,
|
|
})
|
|
: "";
|
|
break;
|
|
case "hardware":
|
|
description =
|
|
this._boardName ||
|
|
this.hass.localize("ui.panel.config.hardware.description");
|
|
break;
|
|
|
|
default:
|
|
description = this.hass.localize(
|
|
`ui.panel.config.${page.translationKey}.description`
|
|
);
|
|
break;
|
|
}
|
|
|
|
return {
|
|
...page,
|
|
name: page.translationKey
|
|
? this.hass.localize(
|
|
`ui.panel.config.${page.translationKey}.caption`
|
|
)
|
|
: page.name,
|
|
description,
|
|
};
|
|
});
|
|
|
|
return html`
|
|
<hass-subpage
|
|
.hass=${this.hass}
|
|
back-path="/config"
|
|
.header=${this.hass.localize("ui.panel.config.dashboard.system.main")}
|
|
.narrow=${this.narrow}
|
|
>
|
|
<ha-icon-button
|
|
slot="toolbar-icon"
|
|
.path=${mdiPower}
|
|
.label=${this.hass.localize(
|
|
"ui.panel.config.system_dashboard.restart_homeassistant"
|
|
)}
|
|
@click=${this._showRestartDialog}
|
|
></ha-icon-button>
|
|
<ha-config-section
|
|
.narrow=${this.narrow}
|
|
.isWide=${this.isWide}
|
|
full-width
|
|
>
|
|
<ha-card outlined>
|
|
<ha-navigation-list
|
|
.hass=${this.hass}
|
|
.narrow=${this.narrow}
|
|
.pages=${pages}
|
|
has-secondary
|
|
.label=${this.hass.localize(
|
|
"ui.panel.config.dashboard.system.main"
|
|
)}
|
|
></ha-navigation-list>
|
|
</ha-card>
|
|
</ha-config-section>
|
|
</hass-subpage>
|
|
`;
|
|
}
|
|
|
|
protected firstUpdated(_changedProperties): void {
|
|
super.firstUpdated(_changedProperties);
|
|
|
|
this._fetchNetworkStatus();
|
|
const isHassioLoaded = isComponentLoaded(this.hass, "hassio");
|
|
this._fetchBackupInfo();
|
|
this._fetchHardwareInfo(isHassioLoaded);
|
|
if (isHassioLoaded) {
|
|
this._fetchStorageInfo();
|
|
}
|
|
}
|
|
|
|
private async _fetchBackupInfo() {
|
|
const backups: BackupContent[] = isComponentLoaded(this.hass, "backup")
|
|
? await fetchBackupInfo(this.hass).then(
|
|
(backupData) => backupData.backups
|
|
)
|
|
: [];
|
|
|
|
if (backups.length > 0) {
|
|
this._latestBackupDate = backups
|
|
.map((backup) => new Date(backup.date))
|
|
.reduce((a, b) => (a > b ? a : b));
|
|
}
|
|
}
|
|
|
|
private async _fetchHardwareInfo(isHassioLoaded: boolean) {
|
|
if (isComponentLoaded(this.hass, "hardware")) {
|
|
const hardwareInfo: HardwareInfo = await this.hass.callWS({
|
|
type: "hardware/info",
|
|
});
|
|
this._boardName = hardwareInfo?.hardware.find(
|
|
(hw) => hw.board !== null
|
|
)?.name;
|
|
} else if (isHassioLoaded) {
|
|
const osData: HassioHassOSInfo = await fetchHassioHassOsInfo(this.hass);
|
|
if (osData.board) {
|
|
this._boardName = BOARD_NAMES[osData.board];
|
|
}
|
|
}
|
|
}
|
|
|
|
private async _fetchStorageInfo() {
|
|
const hostInfo: HassioHostInfo = await fetchHassioHostInfo(this.hass);
|
|
this._storageInfo = {
|
|
used: hostInfo.disk_used,
|
|
free: hostInfo.disk_free,
|
|
total: hostInfo.disk_total,
|
|
};
|
|
}
|
|
|
|
private async _fetchNetworkStatus() {
|
|
if (isComponentLoaded(this.hass, "cloud")) {
|
|
const cloudStatus = await fetchCloudStatus(this.hass);
|
|
if (cloudStatus.logged_in) {
|
|
this._externalAccess = true;
|
|
return;
|
|
}
|
|
}
|
|
this._externalAccess = this.hass.config.external_url !== null;
|
|
}
|
|
|
|
private async _showRestartDialog() {
|
|
showRestartDialog(this);
|
|
}
|
|
|
|
static get styles(): CSSResultGroup {
|
|
return [
|
|
haStyle,
|
|
css`
|
|
:host(:not([narrow])) ha-card {
|
|
margin-bottom: max(24px, var(--safe-area-inset-bottom));
|
|
}
|
|
|
|
ha-config-section {
|
|
margin: auto;
|
|
margin-top: -32px;
|
|
max-width: 600px;
|
|
}
|
|
|
|
ha-card {
|
|
overflow: hidden;
|
|
margin-bottom: 24px;
|
|
margin-bottom: max(24px, var(--safe-area-inset-bottom));
|
|
}
|
|
|
|
ha-card a {
|
|
text-decoration: none;
|
|
color: var(--primary-text-color);
|
|
}
|
|
|
|
.title {
|
|
font-size: var(--ha-font-size-l);
|
|
padding: 16px;
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
.restart-section {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
@media all and (max-width: 600px) {
|
|
ha-card {
|
|
border-width: 1px 0;
|
|
border-radius: 0;
|
|
box-shadow: unset;
|
|
}
|
|
ha-config-section {
|
|
margin-top: -42px;
|
|
}
|
|
}
|
|
|
|
ha-navigation-list {
|
|
--navigation-list-item-title-font-size: var(--ha-font-size-l);
|
|
}
|
|
`,
|
|
];
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"ha-config-system-navigation": HaConfigSystemNavigation;
|
|
}
|
|
}
|