diff --git a/src/entrypoints/custom-panel.ts b/src/entrypoints/custom-panel.ts index 0f25084f37..de6df8758a 100644 --- a/src/entrypoints/custom-panel.ts +++ b/src/entrypoints/custom-panel.ts @@ -9,6 +9,7 @@ import "../resources/safari-14-attachshadow-patch"; import { createCustomPanelElement } from "../util/custom-panel/create-custom-panel-element"; import { loadCustomPanel } from "../util/custom-panel/load-custom-panel"; import { setCustomPanelProperties } from "../util/custom-panel/set-custom-panel-properties"; +import { baseEntrypointStyles } from "../resources/styles"; declare global { interface Window { @@ -41,6 +42,7 @@ function initialize( properties: Record ) { const style = document.createElement("style"); + style.innerHTML = "body{margin:0}"; document.head.appendChild(style); @@ -86,7 +88,24 @@ function initialize( (err) => { // eslint-disable-next-line console.error(err, panel); - alert(`Unable to load the panel source: ${err}.`); + let errorScreen; + if (panel.url_path === "hassio") { + import("../layouts/supervisor-error-screen"); + errorScreen = document.createElement( + "supervisor-error-screen" + ) as any; + } else { + import("../layouts/hass-error-screen"); + errorScreen = document.createElement("hass-error-screen") as any; + errorScreen.error = `Unable to load the panel source: ${err}.`; + } + + const errorStyle = document.createElement("style"); + errorStyle.innerHTML = baseEntrypointStyles.cssText; + document.body.appendChild(errorStyle); + + errorScreen.hass = properties.hass; + document.body.appendChild(errorScreen); } ); } diff --git a/src/layouts/hass-error-screen.ts b/src/layouts/hass-error-screen.ts index d7b9f5ea4c..cadf6c28ed 100644 --- a/src/layouts/hass-error-screen.ts +++ b/src/layouts/hass-error-screen.ts @@ -46,7 +46,9 @@ class HassErrorScreen extends LitElement {

${this.error}

- go back + + ${this.hass?.localize("ui.panel.error.go_back") || "go back"} +
`; diff --git a/src/layouts/supervisor-error-screen.ts b/src/layouts/supervisor-error-screen.ts new file mode 100644 index 0000000000..9f21d19044 --- /dev/null +++ b/src/layouts/supervisor-error-screen.ts @@ -0,0 +1,188 @@ +import "../components/ha-card"; +import "@material/mwc-button"; +import { + css, + CSSResultArray, + customElement, + html, + LitElement, + property, + PropertyValues, + TemplateResult, +} from "lit-element"; +import { HomeAssistant } from "../types"; +import "./hass-subpage"; +import "../resources/ha-style"; +import "../resources/roboto"; +import { haStyle } from "../resources/styles"; +import { applyThemesOnElement } from "../common/dom/apply_themes_on_element"; +import { atLeastVersion } from "../common/config/version"; + +@customElement("supervisor-error-screen") +class SupervisorErrorScreen extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + protected firstUpdated(changedProps: PropertyValues) { + super.firstUpdated(changedProps); + + this._applyTheme(); + } + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + const oldHass = changedProps.get("hass") as HomeAssistant | undefined; + if (!oldHass) { + return; + } + if (oldHass.themes !== this.hass.themes) { + this._applyTheme(); + } + } + + protected render(): TemplateResult { + return html` +
+ +
+
+
+ ${this.hass.localize("ui.panel.error.supervisor.title")} +
+ +
+
    +
  1. + ${this.hass.localize("ui.panel.error.supervisor.wait")} +
  2. +
  3. + + ${this.hass.localize("ui.panel.error.supervisor.observer")} + +
  4. +
  5. + ${this.hass.localize("ui.panel.error.supervisor.reboot")} +
  6. +
  7. + + ${this.hass.localize( + "ui.panel.error.supervisor.system_health" + )} + +
  8. +
  9. + + ${this.hass.localize("ui.panel.error.supervisor.ask")} + +
  10. +
+
+
+
+ `; + } + + private _applyTheme() { + let themeName: string; + let options: Partial | undefined; + + if (atLeastVersion(this.hass.config.version, 0, 114)) { + themeName = + this.hass.selectedTheme?.theme || + (this.hass.themes.darkMode && this.hass.themes.default_dark_theme + ? this.hass.themes.default_dark_theme! + : this.hass.themes.default_theme); + + options = this.hass.selectedTheme; + if (themeName === "default" && options?.dark === undefined) { + options = { + ...this.hass.selectedTheme, + dark: this.hass.themes.darkMode, + }; + } + } else { + themeName = + ((this.hass.selectedTheme as unknown) as string) || + this.hass.themes.default_theme; + } + + applyThemesOnElement( + this.parentElement, + this.hass.themes, + themeName, + options + ); + } + + private _handleBack(): void { + history.back(); + } + + static get styles(): CSSResultArray { + return [ + haStyle, + css` + .toolbar { + display: flex; + align-items: center; + font-size: 20px; + height: var(--header-height); + padding: 0 16px; + pointer-events: none; + background-color: var(--app-header-background-color); + font-weight: 400; + box-sizing: border-box; + } + ha-icon-button-arrow-prev { + pointer-events: auto; + } + .content { + color: var(--primary-text-color); + display: flex; + padding: 16px; + align-items: center; + justify-content: center; + flex-direction: column; + } + .title { + font-size: 24px; + font-weight: 400; + line-height: 32px; + padding-bottom: 16px; + } + + a { + color: var(--mdc-theme-primary); + } + + ha-card { + width: 600px; + margin: 16px; + padding: 8px; + } + @media all and (max-width: 500px) { + ha-card { + width: calc(100vw - 32px); + } + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "supervisor-error-screen": SupervisorErrorScreen; + } +} diff --git a/src/resources/styles.ts b/src/resources/styles.ts index c263427770..e6d70ac0e4 100644 --- a/src/resources/styles.ts +++ b/src/resources/styles.ts @@ -355,3 +355,12 @@ export const haStyleScrollbar = css` scrollbar-width: thin; } `; + +export const baseEntrypointStyles = css` + body { + background-color: var(--primary-background-color); + color: var(--primary-text-color); + height: calc(100vh - 32px); + width: 100vw; + } +`; diff --git a/src/translations/en.json b/src/translations/en.json index 4dacc57eae..a0f176f9a6 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3424,6 +3424,17 @@ "complete_access": "It will have access to all data in Home Assistant.", "hide_message": "Check docs for the panel_custom component to hide this message" } + }, + "error": { + "go_back": "Go back", + "supervisor": { + "title": "Could not load the Supervisor panel!", + "wait": "If you just started, make sure you have given the supervisor enough time to start.", + "ask": "Ask for help", + "reboot": "Try a reboot of the host", + "observer": "Check the Observer", + "system_health": "Check System Health" + } } } },