diff --git a/hassio/src/addon-store/hassio-addon-repository.ts b/hassio/src/addon-store/hassio-addon-repository.ts index c188e516b7..67c4c50849 100644 --- a/hassio/src/addon-store/hassio-addon-repository.ts +++ b/hassio/src/addon-store/hassio-addon-repository.ts @@ -23,9 +23,9 @@ import { hassioStyle } from "../resources/hassio-style"; class HassioAddonRepositoryEl extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property() public repo!: HassioAddonRepository; + @property({ attribute: false }) public repo!: HassioAddonRepository; - @property() public addons!: HassioAddonInfo[]; + @property({ attribute: false }) public addons!: HassioAddonInfo[]; @property() public filter!: string; @@ -78,18 +78,18 @@ class HassioAddonRepositoryEl extends LitElement { .title=${addon.name} .description=${addon.description} .available=${addon.available} - .icon=${addon.installed && addon.installed !== addon.version + .icon=${addon.installed && addon.update_available ? mdiArrowUpBoldCircle : mdiPuzzle} .iconTitle=${addon.installed - ? addon.installed !== addon.version + ? addon.update_available ? "New version available" : "Add-on is installed" : addon.available ? "Add-on is not installed" : "Add-on is not available on your system"} .iconClass=${addon.installed - ? addon.installed !== addon.version + ? addon.update_available ? "update" : "installed" : !addon.available @@ -104,7 +104,7 @@ class HassioAddonRepositoryEl extends LitElement { : undefined} .showTopbar=${addon.installed || !addon.available} .topbarClass=${addon.installed - ? addon.installed !== addon.version + ? addon.update_available ? "update" : "installed" : !addon.available diff --git a/hassio/src/addon-view/info/hassio-addon-info.ts b/hassio/src/addon-view/info/hassio-addon-info.ts index 27bd3ed6ca..91b3410d67 100644 --- a/hassio/src/addon-view/info/hassio-addon-info.ts +++ b/hassio/src/addon-view/info/hassio-addon-info.ts @@ -135,7 +135,7 @@ class HassioAddonInfo extends LitElement { protected render(): TemplateResult { return html` - ${this._computeUpdateAvailable + ${this.addon.update_available ? html`
@@ -609,15 +609,6 @@ class HassioAddonInfo extends LitElement { return this.addon?.state === "started"; } - private get _computeUpdateAvailable(): boolean | "" { - return ( - this.addon && - !this.addon.detached && - this.addon.version && - this.addon.version !== this.addon.version_latest - ); - } - private get _pathWebui(): string | null { return ( this.addon.webui && diff --git a/hassio/src/components/hassio-card-content.ts b/hassio/src/components/hassio-card-content.ts index ee57a98ab8..1123aa9f5a 100644 --- a/hassio/src/components/hassio-card-content.ts +++ b/hassio/src/components/hassio-card-content.ts @@ -50,7 +50,7 @@ class HassioCardContent extends LitElement { ` : html` diff --git a/hassio/src/dashboard/hassio-addons.ts b/hassio/src/dashboard/hassio-addons.ts index 8c6963cac9..717a6397a3 100644 --- a/hassio/src/dashboard/hassio-addons.ts +++ b/hassio/src/dashboard/hassio-addons.ts @@ -52,22 +52,21 @@ class HassioAddons extends LitElement { .title=${addon.name} .description=${addon.description} available - .showTopbar=${addon.installed !== addon.version} + .showTopbar=${addon.update_available} topbarClass="update" - .icon=${addon.installed !== addon.version + .icon=${addon.update_available! ? mdiArrowUpBoldCircle : mdiPuzzle} .iconTitle=${addon.state !== "started" ? "Add-on is stopped" - : addon.installed !== addon.version + : addon.update_available! ? "New version available" : "Add-on is running"} - .iconClass=${addon.installed && - addon.installed !== addon.version + .iconClass=${addon.update_available ? addon.state === "started" ? "update" : "update stopped" - : addon.installed && addon.state === "started" + : addon.state === "started" ? "running" : "stopped"} .iconImage=${atLeastVersion( diff --git a/hassio/src/dashboard/hassio-update.ts b/hassio/src/dashboard/hassio-update.ts index a95eafbd76..9f8fa97d37 100644 --- a/hassio/src/dashboard/hassio-update.ts +++ b/hassio/src/dashboard/hassio-update.ts @@ -5,11 +5,11 @@ import { CSSResult, customElement, html, - internalProperty, LitElement, property, TemplateResult, } from "lit-element"; +import memoizeOne from "memoize-one"; import "../../../src/components/buttons/ha-progress-button"; import "../../../src/components/ha-card"; import "../../../src/components/ha-svg-icon"; @@ -35,29 +35,30 @@ import { hassioStyle } from "../resources/hassio-style"; export class HassioUpdate extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property({ attribute: false }) public hassInfo: HassioHomeAssistantInfo; + @property({ attribute: false }) public hassInfo?: HassioHomeAssistantInfo; @property({ attribute: false }) public hassOsInfo?: HassioHassOSInfo; - @property() public supervisorInfo: HassioSupervisorInfo; + @property({ attribute: false }) public supervisorInfo?: HassioSupervisorInfo; - @internalProperty() private _error?: string; + private _pendingUpdates = memoizeOne( + ( + core?: HassioHomeAssistantInfo, + supervisor?: HassioSupervisorInfo, + os?: HassioHassOSInfo + ): number => { + return [core, supervisor, os].filter( + (value) => !!value && value?.update_available + ).length; + } + ); protected render(): TemplateResult { - const updatesAvailable: number = [ + const updatesAvailable = this._pendingUpdates( this.hassInfo, this.supervisorInfo, - this.hassOsInfo, - ].filter((value) => { - return ( - !!value && - (value.version_latest - ? value.version !== value.version_latest - : value.version_latest - ? value.version !== value.version_latest - : false) - ); - }).length; + this.hassOsInfo + ); if (!updatesAvailable) { return html``; @@ -65,9 +66,6 @@ export class HassioUpdate extends LitElement { return html`
- ${this._error - ? html`
Error: ${this._error}
` - : ""}

${updatesAvailable > 1 ? "Updates Available 🎉" @@ -76,26 +74,24 @@ export class HassioUpdate extends LitElement {
${this._renderUpdateCard( "Home Assistant Core", - this.hassInfo.version, - this.hassInfo.version_latest, + this.hassInfo!, "hassio/homeassistant/update", `https://${ - this.hassInfo.version_latest.includes("b") ? "rc" : "www" - }.home-assistant.io/latest-release-notes/`, - mdiHomeAssistant + this.hassInfo?.version_latest.includes("b") ? "rc" : "www" + }.home-assistant.io/latest-release-notes/` )} ${this._renderUpdateCard( "Supervisor", - this.supervisorInfo.version, - this.supervisorInfo.version_latest, + this.supervisorInfo!, "hassio/supervisor/update", - `https://github.com//home-assistant/hassio/releases/tag/${this.supervisorInfo.version_latest}` + `https://github.com//home-assistant/hassio/releases/tag/${ + this.supervisorInfo!.version_latest + }` )} ${this.hassOsInfo ? this._renderUpdateCard( "Operating System", - this.hassOsInfo.version, - this.hassOsInfo.version_latest, + this.hassOsInfo, "hassio/os/update", `https://github.com//home-assistant/hassos/releases/tag/${this.hassOsInfo.version_latest}` ) @@ -107,28 +103,22 @@ export class HassioUpdate extends LitElement { private _renderUpdateCard( name: string, - curVersion: string, - lastVersion: string, + object: HassioHomeAssistantInfo | HassioSupervisorInfo | HassioHassOSInfo, apiPath: string, - releaseNotesUrl: string, - icon?: string + releaseNotesUrl: string ): TemplateResult { - if (!lastVersion || lastVersion === curVersion) { + if (!object.update_available) { return html``; } return html`
- ${icon - ? html` -
- -
- ` - : ""} -
${name} ${lastVersion}
+
+ +
+
${name} ${object.version_latest}
- You are currently running version ${curVersion} + You are currently running version ${object.version}
@@ -138,7 +128,7 @@ export class HassioUpdate extends LitElement { Update diff --git a/hassio/src/hassio-panel-router.ts b/hassio/src/hassio-panel-router.ts index 00830423b0..054f5fef34 100644 --- a/hassio/src/hassio-panel-router.ts +++ b/hassio/src/hassio-panel-router.ts @@ -25,13 +25,13 @@ class HassioPanelRouter extends HassRouterPage { @property({ type: Boolean }) public narrow!: boolean; - @property({ attribute: false }) public supervisorInfo: HassioSupervisorInfo; + @property({ attribute: false }) public supervisorInfo?: HassioSupervisorInfo; @property({ attribute: false }) public hassioInfo!: HassioInfo; @property({ attribute: false }) public hostInfo: HassioHostInfo; - @property({ attribute: false }) public hassInfo: HassioHomeAssistantInfo; + @property({ attribute: false }) public hassInfo?: HassioHomeAssistantInfo; @property({ attribute: false }) public hassOsInfo!: HassioHassOSInfo; diff --git a/hassio/src/hassio-router.ts b/hassio/src/hassio-router.ts index a3ecdaf784..36620f368e 100644 --- a/hassio/src/hassio-router.ts +++ b/hassio/src/hassio-router.ts @@ -66,7 +66,7 @@ class HassioRouter extends HassRouterPage { }, }; - @internalProperty() private _supervisorInfo: HassioSupervisorInfo; + @internalProperty() private _supervisorInfo?: HassioSupervisorInfo; @internalProperty() private _hostInfo: HassioHostInfo; @@ -74,7 +74,7 @@ class HassioRouter extends HassRouterPage { @internalProperty() private _hassOsInfo?: HassioHassOSInfo; - @internalProperty() private _hassInfo: HassioHomeAssistantInfo; + @internalProperty() private _hassInfo?: HassioHomeAssistantInfo; protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); diff --git a/hassio/src/system/hassio-host-info.ts b/hassio/src/system/hassio-host-info.ts index f0f34aec2f..bc25836f3c 100644 --- a/hassio/src/system/hassio-host-info.ts +++ b/hassio/src/system/hassio-host-info.ts @@ -108,8 +108,8 @@ class HassioHostInfo extends LitElement { ${this.hostInfo.operating_system} - ${this.hostInfo.version !== this.hostInfo.version_latest && - this.hostInfo.features.includes("hassos") + ${this.hostInfo.features.includes("hassos") && + this.hostInfo.update_available ? html` ${this.supervisorInfo.version_latest} - ${this.supervisorInfo.version !== this.supervisorInfo.version_latest + ${this.supervisorInfo.update_available ? html` ; - network: null | Record; - network_description: null | Record; - host_network: boolean; - host_pid: boolean; - host_ipc: boolean; - host_dbus: boolean; - privileged: any; apparmor: "disable" | "default" | "profile"; - devices: string[]; - auto_uart: boolean; - icon: boolean; - logo: boolean; - stage: "stable" | "experimental" | "deprecated"; - changelog: boolean; - hassio_api: boolean; - hassio_role: "default" | "homeassistant" | "manager" | "admin"; - startup: "initialize" | "system" | "services" | "application" | "once"; - homeassistant_api: boolean; - auth_api: boolean; - full_access: boolean; - protected: boolean; - rating: "1-6"; - stdin: boolean; - webui: null | string; - gpio: boolean; - kernel_modules: boolean; - devicetree: boolean; - docker_api: boolean; - audio: boolean; + arch: "armhf" | "aarch64" | "i386" | "amd64"; audio_input: null | string; audio_output: null | string; - services_role: string[]; + audio: boolean; + auth_api: boolean; + auto_uart: boolean; + auto_update: boolean; + boot: "auto" | "manual"; + changelog: boolean; + devices: string[]; + devicetree: boolean; discovery: string[]; - ip_address: string; - ingress: boolean; - ingress_panel: boolean; + docker_api: boolean; + documentation: boolean; + full_access: boolean; + gpio: boolean; + hassio_api: boolean; + hassio_role: "default" | "homeassistant" | "manager" | "admin"; + homeassistant_api: boolean; + homeassistant: string; + host_dbus: boolean; + host_ipc: boolean; + host_network: boolean; + host_pid: boolean; ingress_entry: null | string; + ingress_panel: boolean; ingress_url: null | string; + ingress: boolean; + ip_address: string; + kernel_modules: boolean; + long_description: null | string; + machine: any; + network_description: null | Record; + network: null | Record; + options: Record; + privileged: any; + protected: boolean; + rating: "1-6"; + services_role: string[]; + slug: string; + startup: "initialize" | "system" | "services" | "application" | "once"; + stdin: boolean; watchdog: null | boolean; + webui: null | string; } export interface HassioAddonsInfo { diff --git a/src/data/hassio/host.ts b/src/data/hassio/host.ts index a8db6dbc71..bbe2e4d852 100644 --- a/src/data/hassio/host.ts +++ b/src/data/hassio/host.ts @@ -4,11 +4,12 @@ import { hassioApiResultExtractor, HassioResponse } from "./common"; export type HassioHostInfo = any; export interface HassioHassOSInfo { - version: string; + board: "ova" | "rpi"; + update_available: boolean; + version_cli_latest: string; version_cli: string; version_latest: string; - version_cli_latest: string; - board: "ova" | "rpi"; + version: string; } export const fetchHassioHostInfo = async (hass: HomeAssistant) => { diff --git a/src/data/hassio/supervisor.ts b/src/data/hassio/supervisor.ts index 992425b8bc..9d2845f776 100644 --- a/src/data/hassio/supervisor.ts +++ b/src/data/hassio/supervisor.ts @@ -1,19 +1,56 @@ import { HomeAssistant, PanelInfo } from "../../types"; +import { HassioAddonInfo, HassioAddonRepository } from "./addon"; import { hassioApiResultExtractor, HassioResponse } from "./common"; -export type HassioHomeAssistantInfo = any; -export type HassioSupervisorInfo = any; +export type HassioHomeAssistantInfo = { + arch: string; + audio_input: string | null; + audio_output: string | null; + boot: boolean; + image: string; + ip_address: string; + machine: string; + port: number; + ssl: boolean; + update_available: boolean; + version_latest: string; + version: string; + wait_boot: number; + watchdog: boolean; +}; + +export type HassioSupervisorInfo = { + addons: HassioAddonInfo[]; + addons_repositories: HassioAddonRepository[]; + arch: string; + channel: string; + debug: boolean; + debug_block: boolean; + diagnostics: boolean | null; + healthy: boolean; + ip_address: string; + logging: string; + supported: boolean; + timezone: string; + update_available: boolean; + version: string; + version_latest: string; + wait_boot: number; +}; export type HassioInfo = { arch: string; channel: string; docker: string; - hassos?: string; + features: string[]; + hassos: null; homeassistant: string; hostname: string; logging: string; - maching: string; + machine: string; + operating_system: string; supervisor: string; + supported: boolean; supported_arch: string[]; timezone: string; };