mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-16 05:46:35 +00:00
Add hassio supervisor and os update notice (#3798)
* Add hassio supervisor and os update notice * Cleanup * Update hassio-dashboard.ts * Fix styling * Check if system has HassOs * Remove unused import
This commit is contained in:
parent
f4bd42dfd4
commit
05a258c886
@ -8,26 +8,31 @@ import {
|
||||
customElement,
|
||||
} from "lit-element";
|
||||
import "./hassio-addons";
|
||||
import "./hassio-hass-update";
|
||||
import "./hassio-update";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import {
|
||||
HassioSupervisorInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
HassioHassOSInfo,
|
||||
} from "../../../src/data/hassio";
|
||||
|
||||
@customElement("hassio-dashboard")
|
||||
class HassioDashboard extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public supervisorInfo!: HassioSupervisorInfo;
|
||||
@property() public hassInfo!: HassioHomeAssistantInfo;
|
||||
@property() public hassOsInfo!: HassioHassOSInfo;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
return html`
|
||||
<div class="content">
|
||||
<hassio-hass-update
|
||||
<hassio-update
|
||||
.hass=${this.hass}
|
||||
.hassInfo=${this.hassInfo}
|
||||
></hassio-hass-update>
|
||||
.supervisorInfo=${this.supervisorInfo}
|
||||
.hassOsInfo=${this.hassOsInfo}
|
||||
></hassio-update>
|
||||
<hassio-addons
|
||||
.hass=${this.hass}
|
||||
.addons=${this.supervisorInfo.addons}
|
||||
|
@ -1,96 +0,0 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
|
||||
import "../../../src/components/buttons/ha-call-api-button";
|
||||
import "../components/hassio-card-content";
|
||||
import "../resources/hassio-style";
|
||||
|
||||
class HassioHassUpdate extends PolymerElement {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style hassio-style">
|
||||
paper-card {
|
||||
display: block;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
margin-top: 16px;
|
||||
}
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
<template is="dom-if" if="[[computeUpdateAvailable(hassInfo)]]">
|
||||
<div class="content">
|
||||
<div class="card-group">
|
||||
<paper-card heading="Update available! 🎉">
|
||||
<div class="card-content">
|
||||
Home Assistant [[hassInfo.last_version]] is available and you
|
||||
are currently running Home Assistant [[hassInfo.version]].
|
||||
<template is="dom-if" if="[[error]]">
|
||||
<div class="error">Error: [[error]]</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
hass="[[hass]]"
|
||||
path="hassio/homeassistant/update"
|
||||
>Update</ha-call-api-button
|
||||
>
|
||||
<a
|
||||
href="[[computeReleaseNotesUrl(hassInfo.version)]]"
|
||||
target="_blank"
|
||||
>
|
||||
<mwc-button>Release notes</mwc-button>
|
||||
</a>
|
||||
</div>
|
||||
</paper-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
hassInfo: Object,
|
||||
error: String,
|
||||
};
|
||||
}
|
||||
|
||||
ready() {
|
||||
super.ready();
|
||||
this.addEventListener("hass-api-called", (ev) => this.apiCalled(ev));
|
||||
}
|
||||
|
||||
apiCalled(ev) {
|
||||
if (ev.detail.success) {
|
||||
this.errors = null;
|
||||
return;
|
||||
}
|
||||
|
||||
const response = ev.detail.response;
|
||||
|
||||
if (typeof response.body === "object") {
|
||||
this.errors = response.body.message || "Unknown error";
|
||||
} else {
|
||||
this.errors = response.body;
|
||||
}
|
||||
}
|
||||
|
||||
computeUpdateAvailable(hassInfo) {
|
||||
return hassInfo.version !== hassInfo.last_version;
|
||||
}
|
||||
|
||||
computeReleaseNotesUrl(version) {
|
||||
return `https://${
|
||||
version.includes("b") ? "rc" : "www"
|
||||
}.home-assistant.io/latest-release-notes/`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("hassio-hass-update", HassioHassUpdate);
|
153
hassio/src/dashboard/hassio-update.ts
Normal file
153
hassio/src/dashboard/hassio-update.ts
Normal file
@ -0,0 +1,153 @@
|
||||
import {
|
||||
LitElement,
|
||||
TemplateResult,
|
||||
html,
|
||||
CSSResult,
|
||||
css,
|
||||
property,
|
||||
customElement,
|
||||
} from "lit-element";
|
||||
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import {
|
||||
HassioHomeAssistantInfo,
|
||||
HassioHassOSInfo,
|
||||
HassioSupervisorInfo,
|
||||
} from "../../../src/data/hassio";
|
||||
|
||||
import { hassioStyle } from "../resources/hassio-style";
|
||||
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-card/paper-card";
|
||||
import "../../../src/components/buttons/ha-call-api-button";
|
||||
import "../components/hassio-card-content";
|
||||
|
||||
@customElement("hassio-update")
|
||||
export class HassioUpdate extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public hassInfo: HassioHomeAssistantInfo;
|
||||
@property() public hassOsInfo?: HassioHassOSInfo;
|
||||
@property() public supervisorInfo: HassioSupervisorInfo;
|
||||
|
||||
@property() public error?: string;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (
|
||||
this.hassInfo.version === this.hassInfo.last_version &&
|
||||
this.supervisorInfo.version === this.supervisorInfo.last_version &&
|
||||
(!this.hassOsInfo ||
|
||||
this.hassOsInfo.version === this.hassOsInfo.version_latest)
|
||||
) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class="content">
|
||||
${this.error
|
||||
? html`
|
||||
<div class="error">Error: ${this.error}</div>
|
||||
`
|
||||
: ""}
|
||||
<div class="card-group">
|
||||
${this._renderUpdateCard(
|
||||
"Home Assistant",
|
||||
this.hassInfo.version,
|
||||
this.hassInfo.last_version,
|
||||
"hassio/homeassistant/update",
|
||||
`https://${
|
||||
this.hassInfo.last_version.includes("b") ? "rc" : "www"
|
||||
}.home-assistant.io/latest-release-notes/`
|
||||
)}
|
||||
${this._renderUpdateCard(
|
||||
"Hass.io Supervisor",
|
||||
this.supervisorInfo.version,
|
||||
this.supervisorInfo.last_version,
|
||||
"hassio/supervisor/update",
|
||||
`https://github.com//home-assistant/hassio/releases/tag/${
|
||||
this.supervisorInfo.last_version
|
||||
}`
|
||||
)}
|
||||
${this.hassOsInfo
|
||||
? this._renderUpdateCard(
|
||||
"HassOS",
|
||||
this.hassOsInfo.version,
|
||||
this.hassOsInfo.version_latest,
|
||||
"hassio/hassos/update",
|
||||
`https://github.com//home-assistant/hassos/releases/tag/${
|
||||
this.hassOsInfo.version_latest
|
||||
}`
|
||||
)
|
||||
: ""}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _renderUpdateCard(
|
||||
name: string,
|
||||
curVersion: string,
|
||||
lastVersion: string,
|
||||
apiPath: string,
|
||||
releaseNotesUrl: string
|
||||
): TemplateResult {
|
||||
if (lastVersion === curVersion) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<paper-card heading="${name} update available! 🎉">
|
||||
<div class="card-content">
|
||||
${name} ${lastVersion} is available and you are currently running
|
||||
${name} ${curVersion}.
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-call-api-button
|
||||
.hass=${this.hass}
|
||||
.path=${apiPath}
|
||||
@hass-api-called=${this._apiCalled}
|
||||
>
|
||||
Update
|
||||
</ha-call-api-button>
|
||||
<a href="${releaseNotesUrl}" target="_blank">
|
||||
<mwc-button>Release notes</mwc-button>
|
||||
</a>
|
||||
</div>
|
||||
</paper-card>
|
||||
`;
|
||||
}
|
||||
|
||||
private _apiCalled(ev) {
|
||||
if (ev.detail.success) {
|
||||
this.error = "";
|
||||
return;
|
||||
}
|
||||
|
||||
const response = ev.detail.response;
|
||||
|
||||
typeof response.body === "object"
|
||||
? (this.error = response.body.message || "Unknown error")
|
||||
: (this.error = response.body);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
hassioStyle,
|
||||
css`
|
||||
:host {
|
||||
width: 33%;
|
||||
}
|
||||
paper-card {
|
||||
display: inline-block;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.errors {
|
||||
color: var(--google-red-500);
|
||||
padding: 16px;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
@ -13,9 +13,11 @@ import { HomeAssistant } from "../../src/types";
|
||||
import {
|
||||
fetchHassioSupervisorInfo,
|
||||
fetchHassioHostInfo,
|
||||
fetchHassioHassOsInfo,
|
||||
fetchHassioHomeAssistantInfo,
|
||||
HassioSupervisorInfo,
|
||||
HassioHostInfo,
|
||||
HassioHassOSInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
fetchHassioAddonInfo,
|
||||
createHassioSession,
|
||||
@ -66,6 +68,7 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
||||
|
||||
@property() private _supervisorInfo: HassioSupervisorInfo;
|
||||
@property() private _hostInfo: HassioHostInfo;
|
||||
@property() private _hassOsInfo?: HassioHassOSInfo;
|
||||
@property() private _hassInfo: HassioHomeAssistantInfo;
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
@ -113,6 +116,7 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
||||
supervisorInfo: this._supervisorInfo,
|
||||
hostInfo: this._hostInfo,
|
||||
hassInfo: this._hassInfo,
|
||||
hassOsInfo: this._hassOsInfo,
|
||||
route,
|
||||
});
|
||||
} else {
|
||||
@ -121,6 +125,7 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
||||
el.supervisorInfo = this._supervisorInfo;
|
||||
el.hostInfo = this._hostInfo;
|
||||
el.hassInfo = this._hassInfo;
|
||||
el.hassOsInfo = this._hassOsInfo;
|
||||
el.route = route;
|
||||
}
|
||||
}
|
||||
@ -139,6 +144,10 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
|
||||
this._supervisorInfo = supervisorInfo;
|
||||
this._hostInfo = hostInfo;
|
||||
this._hassInfo = hassInfo;
|
||||
|
||||
if (this._hostInfo.features && this._hostInfo.features.includes("hassos")) {
|
||||
this._hassOsInfo = await fetchHassioHassOsInfo(this.hass);
|
||||
}
|
||||
}
|
||||
|
||||
private async _redirectIngress(addonSlug: string) {
|
||||
|
@ -27,6 +27,7 @@ import {
|
||||
HassioSupervisorInfo,
|
||||
HassioHostInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
HassioHassOSInfo,
|
||||
} from "../../src/data/hassio";
|
||||
|
||||
const HAS_REFRESH_BUTTON = ["store", "snapshots"];
|
||||
@ -39,6 +40,7 @@ class HassioPagesWithTabs extends LitElement {
|
||||
@property() public supervisorInfo!: HassioSupervisorInfo;
|
||||
@property() public hostInfo!: HassioHostInfo;
|
||||
@property() public hassInfo!: HassioHomeAssistantInfo;
|
||||
@property() public hassOsInfo!: HassioHassOSInfo;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
const page = this._page;
|
||||
@ -79,6 +81,7 @@ class HassioPagesWithTabs extends LitElement {
|
||||
.supervisorInfo=${this.supervisorInfo}
|
||||
.hostInfo=${this.hostInfo}
|
||||
.hassInfo=${this.hassInfo}
|
||||
.hassOsInfo=${this.hassOsInfo}
|
||||
></hassio-tabs-router>
|
||||
</app-header-layout>
|
||||
`;
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
HassioSupervisorInfo,
|
||||
HassioHostInfo,
|
||||
HassioHomeAssistantInfo,
|
||||
HassioHassOSInfo,
|
||||
} from "../../src/data/hassio";
|
||||
|
||||
@customElement("hassio-tabs-router")
|
||||
@ -23,6 +24,7 @@ class HassioTabsRouter extends HassRouterPage {
|
||||
@property() public supervisorInfo: HassioSupervisorInfo;
|
||||
@property() public hostInfo: HassioHostInfo;
|
||||
@property() public hassInfo: HassioHomeAssistantInfo;
|
||||
@property() public hassOsInfo!: HassioHassOSInfo;
|
||||
|
||||
protected routerOptions: RouterOptions = {
|
||||
routes: {
|
||||
@ -49,12 +51,14 @@ class HassioTabsRouter extends HassRouterPage {
|
||||
supervisorInfo: this.supervisorInfo,
|
||||
hostInfo: this.hostInfo,
|
||||
hassInfo: this.hassInfo,
|
||||
hassOsInfo: this.hassOsInfo,
|
||||
});
|
||||
} else {
|
||||
el.hass = this.hass;
|
||||
el.supervisorInfo = this.supervisorInfo;
|
||||
el.hostInfo = this.hostInfo;
|
||||
el.hassInfo = this.hassInfo;
|
||||
el.hassOsInfo = this.hassOsInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
|
||||
>Import from USB</ha-call-api-button
|
||||
>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_computeUpdateAvailable(_hassOs)]]">
|
||||
<template is="dom-if" if="[[_computeUpdateAvailable(hassOsInfo)]]">
|
||||
<ha-call-api-button hass="[[hass]]" path="hassio/hassos/update"
|
||||
>Update</ha-call-api-button
|
||||
>
|
||||
@ -120,12 +120,9 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
data: {
|
||||
type: Object,
|
||||
observer: "_dataChanged",
|
||||
},
|
||||
data: Object,
|
||||
hassOsInfo: Object,
|
||||
errors: String,
|
||||
_hassOs: Object,
|
||||
};
|
||||
}
|
||||
|
||||
@ -149,16 +146,6 @@ class HassioHostInfo extends EventsMixin(PolymerElement) {
|
||||
}
|
||||
}
|
||||
|
||||
_dataChanged(data) {
|
||||
if (data.features && data.features.includes("hassos")) {
|
||||
this.hass.callApi("get", "hassio/hassos/info").then((resp) => {
|
||||
this._hassOs = resp.data;
|
||||
});
|
||||
} else {
|
||||
this._hassOs = {};
|
||||
}
|
||||
}
|
||||
|
||||
_computeUpdateAvailable(data) {
|
||||
return data && data.version !== data.version_latest;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ class HassioSystem extends PolymerElement {
|
||||
<hassio-host-info
|
||||
hass="[[hass]]"
|
||||
data="[[hostInfo]]"
|
||||
hass-os-info="[[hassOsInfo]]"
|
||||
></hassio-host-info>
|
||||
<div class="title">System log</div>
|
||||
<hassio-supervisor-log hass="[[hass]]"></hassio-supervisor-log>
|
||||
@ -42,6 +43,7 @@ class HassioSystem extends PolymerElement {
|
||||
hass: Object,
|
||||
supervisorInfo: Object,
|
||||
hostInfo: Object,
|
||||
hassOsInfo: Object,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -183,6 +183,11 @@ export const fetchHassioHostInfo = (hass: HomeAssistant) =>
|
||||
.callApi<HassioResponse<HassioHostInfo>>("GET", "hassio/host/info")
|
||||
.then(hassioApiResultExtractor);
|
||||
|
||||
export const fetchHassioHassOsInfo = (hass: HomeAssistant) =>
|
||||
hass
|
||||
.callApi<HassioResponse<HassioHassOSInfo>>("GET", "hassio/hassos/info")
|
||||
.then(hassioApiResultExtractor);
|
||||
|
||||
export const fetchHassioHomeAssistantInfo = (hass: HomeAssistant) =>
|
||||
hass
|
||||
.callApi<HassioResponse<HassioHomeAssistantInfo>>(
|
||||
|
Loading…
x
Reference in New Issue
Block a user