Fix messaging when addon is not available (#8454)

This commit is contained in:
Joakim Sørensen 2021-02-26 14:15:36 +01:00 committed by GitHub
parent 64d390ad0f
commit af6e87ba31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 153 additions and 48 deletions

View File

@ -192,8 +192,10 @@ class HassioAddonStore extends LitElement {
} }
private async _loadData() { private async _loadData() {
fireEvent(this, "supervisor-store-refresh", { store: "addon" }); fireEvent(this, "supervisor-colllection-refresh", { colllection: "addon" });
fireEvent(this, "supervisor-store-refresh", { store: "supervisor" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "supervisor",
});
} }
private async _filterChanged(e) { private async _filterChanged(e) {

View File

@ -190,7 +190,9 @@ class HassioAddonDashboard extends LitElement {
const path: string = pathSplit[pathSplit.length - 1]; const path: string = pathSplit[pathSplit.length - 1];
if (["uninstall", "install", "update", "start", "stop"].includes(path)) { if (["uninstall", "install", "update", "start", "stop"].includes(path)) {
fireEvent(this, "supervisor-store-refresh", { store: "supervisor" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "supervisor",
});
} }
if (path === "uninstall") { if (path === "uninstall") {

View File

@ -25,6 +25,7 @@ import {
TemplateResult, TemplateResult,
} from "lit-element"; } from "lit-element";
import { classMap } from "lit-html/directives/class-map"; import { classMap } from "lit-html/directives/class-map";
import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../../src/common/config/version"; import { atLeastVersion } from "../../../../src/common/config/version";
import { fireEvent } from "../../../../src/common/dom/fire_event"; import { fireEvent } from "../../../../src/common/dom/fire_event";
import { navigate } from "../../../../src/common/navigate"; import { navigate } from "../../../../src/common/navigate";
@ -57,6 +58,7 @@ import {
fetchHassioStats, fetchHassioStats,
HassioStats, HassioStats,
} from "../../../../src/data/hassio/common"; } from "../../../../src/data/hassio/common";
import { StoreAddon } from "../../../../src/data/supervisor/store";
import { Supervisor } from "../../../../src/data/supervisor/supervisor"; import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import { import {
showAlertDialog, showAlertDialog,
@ -148,7 +150,16 @@ class HassioAddonInfo extends LitElement {
@internalProperty() private _error?: string; @internalProperty() private _error?: string;
private _addonStoreInfo = memoizeOne(
(slug: string, storeAddons: StoreAddon[]) =>
storeAddons.find((addon) => addon.slug === slug)
);
protected render(): TemplateResult { protected render(): TemplateResult {
const addonStoreInfo =
!this.addon.detached && !this.addon.available
? this._addonStoreInfo(this.addon.slug, this.supervisor.store.addons)
: undefined;
const metrics = [ const metrics = [
{ {
description: "Add-on CPU Usage", description: "Add-on CPU Usage",
@ -176,30 +187,33 @@ class HassioAddonInfo extends LitElement {
icon=${mdiArrowUpBoldCircle} icon=${mdiArrowUpBoldCircle}
iconClass="update" iconClass="update"
></hassio-card-content> ></hassio-card-content>
${!this.addon.available ${!this.addon.available && addonStoreInfo
? !addonArchIsSupported( ? !addonArchIsSupported(
this.supervisor.info.supported_arch, this.supervisor.info.supported_arch,
this.addon.arch this.addon.arch
) )
? html` ? html`
<p> <p class="warning">
This add-on is not compatible with the processor of This add-on is not compatible with the processor of
your device or the operating system you have installed your device or the operating system you have installed
on your device. on your device.
</p> </p>
` `
: html` : html`
<p> <p class="warning">
You are running Home Assistant You are running Home Assistant
${this.supervisor.core.version}, to update to this ${this.supervisor.core.version}, to update to this
version of the add-on you need at least version version of the add-on you need at least version
${this.addon.homeassistant} of Home Assistant ${addonStoreInfo.homeassistant} of Home Assistant
</p> </p>
` `
: ""} : ""}
</div> </div>
<div class="card-actions"> <div class="card-actions">
<ha-progress-button @click=${this._updateClicked}> <ha-progress-button
.disabled=${!this.addon.available}
@click=${this._updateClicked}
>
Update Update
</ha-progress-button> </ha-progress-button>
${this.addon.changelog ${this.addon.changelog
@ -551,7 +565,7 @@ class HassioAddonInfo extends LitElement {
</div> </div>
</div> </div>
${this._error ? html` <div class="errors">${this._error}</div> ` : ""} ${this._error ? html` <div class="errors">${this._error}</div> ` : ""}
${!this.addon.available ${!this.addon.version && addonStoreInfo && !this.addon.available
? !addonArchIsSupported( ? !addonArchIsSupported(
this.supervisor.info.supported_arch, this.supervisor.info.supported_arch,
this.addon.arch this.addon.arch
@ -567,8 +581,8 @@ class HassioAddonInfo extends LitElement {
<p class="warning"> <p class="warning">
You are running Home Assistant You are running Home Assistant
${this.supervisor.core.version}, to install this add-on you ${this.supervisor.core.version}, to install this add-on you
need at least version ${this.addon.homeassistant} of Home need at least version ${addonStoreInfo!.homeassistant} of
Assistant Home Assistant
</p> </p>
` `
: ""} : ""}

View File

@ -148,7 +148,9 @@ export class HassioUpdate extends LitElement {
} }
try { try {
await this.hass.callApi<HassioResponse<void>>("POST", item.apiPath); await this.hass.callApi<HassioResponse<void>>("POST", item.apiPath);
fireEvent(this, "supervisor-store-refresh", { store: item.key }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: item.key,
});
} catch (err) { } catch (err) {
// Only show an error if the status code was not expected (user behind proxy) // Only show an error if the status code was not expected (user behind proxy)
// or no status at all(connection terminated) // or no status at all(connection terminated)

View File

@ -3,7 +3,7 @@ import { atLeastVersion } from "../../src/common/config/version";
import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element"; import { applyThemesOnElement } from "../../src/common/dom/apply_themes_on_element";
import { fireEvent } from "../../src/common/dom/fire_event"; import { fireEvent } from "../../src/common/dom/fire_event";
import { HassioPanelInfo } from "../../src/data/hassio/supervisor"; import { HassioPanelInfo } from "../../src/data/hassio/supervisor";
import { supervisorStore } from "../../src/data/supervisor/supervisor"; import { supervisorCollection } from "../../src/data/supervisor/supervisor";
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager"; import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
import "../../src/layouts/hass-loading-screen"; import "../../src/layouts/hass-loading-screen";
import { HomeAssistant, Route } from "../../src/types"; import { HomeAssistant, Route } from "../../src/types";
@ -77,7 +77,9 @@ export class HassioMain extends SupervisorBaseElement {
} }
if ( if (
Object.keys(supervisorStore).some((store) => !this.supervisor![store]) Object.keys(supervisorCollection).some(
(colllection) => !this.supervisor![colllection]
)
) { ) {
return html`<hass-loading-screen></hass-loading-screen>`; return html`<hass-loading-screen></hass-loading-screen>`;
} }

View File

@ -19,12 +19,13 @@ import {
fetchHassioInfo, fetchHassioInfo,
fetchHassioSupervisorInfo, fetchHassioSupervisorInfo,
} from "../../src/data/hassio/supervisor"; } from "../../src/data/hassio/supervisor";
import { fetchSupervisorStore } from "../../src/data/supervisor/store";
import { import {
getSupervisorEventCollection, getSupervisorEventCollection,
subscribeSupervisorEvents, subscribeSupervisorEvents,
Supervisor, Supervisor,
SupervisorObject, SupervisorObject,
supervisorStore, supervisorCollection,
} from "../../src/data/supervisor/supervisor"; } from "../../src/data/supervisor/supervisor";
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin"; import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
import { urlSyncMixin } from "../../src/state/url-sync-mixin"; import { urlSyncMixin } from "../../src/state/url-sync-mixin";
@ -32,7 +33,7 @@ import { urlSyncMixin } from "../../src/state/url-sync-mixin";
declare global { declare global {
interface HASSDomEvents { interface HASSDomEvents {
"supervisor-update": Partial<Supervisor>; "supervisor-update": Partial<Supervisor>;
"supervisor-store-refresh": { store: SupervisorObject }; "supervisor-colllection-refresh": { colllection: SupervisorObject };
} }
} }
@ -65,40 +66,40 @@ export class SupervisorBaseElement extends urlSyncMixin(
} }
private async _handleSupervisorStoreRefreshEvent(ev) { private async _handleSupervisorStoreRefreshEvent(ev) {
const store = ev.detail.store; const colllection = ev.detail.colllection;
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) { if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
this._collections[store].refresh(); this._collections[colllection].refresh();
return; return;
} }
const response = await this.hass.callApi<HassioResponse<any>>( const response = await this.hass.callApi<HassioResponse<any>>(
"GET", "GET",
`hassio${supervisorStore[store]}` `hassio${supervisorCollection[colllection]}`
); );
this._updateSupervisor({ [store]: response.data }); this._updateSupervisor({ [colllection]: response.data });
} }
private async _initSupervisor(): Promise<void> { private async _initSupervisor(): Promise<void> {
this.addEventListener( this.addEventListener(
"supervisor-store-refresh", "supervisor-colllection-refresh",
this._handleSupervisorStoreRefreshEvent this._handleSupervisorStoreRefreshEvent
); );
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) { if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
Object.keys(supervisorStore).forEach((store) => { Object.keys(supervisorCollection).forEach((colllection) => {
this._unsubs[store] = subscribeSupervisorEvents( this._unsubs[colllection] = subscribeSupervisorEvents(
this.hass, this.hass,
(data) => this._updateSupervisor({ [store]: data }), (data) => this._updateSupervisor({ [colllection]: data }),
store, colllection,
supervisorStore[store] supervisorCollection[colllection]
); );
if (this._collections[store]) { if (this._collections[colllection]) {
this._collections[store].refresh(); this._collections[colllection].refresh();
} else { } else {
this._collections[store] = getSupervisorEventCollection( this._collections[colllection] = getSupervisorEventCollection(
this.hass.connection, this.hass.connection,
store, colllection,
supervisorStore[store] supervisorCollection[colllection]
); );
} }
}); });
@ -122,6 +123,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
os, os,
network, network,
resolution, resolution,
store,
] = await Promise.all([ ] = await Promise.all([
fetchHassioAddonsInfo(this.hass), fetchHassioAddonsInfo(this.hass),
fetchHassioSupervisorInfo(this.hass), fetchHassioSupervisorInfo(this.hass),
@ -131,6 +133,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
fetchHassioHassOsInfo(this.hass), fetchHassioHassOsInfo(this.hass),
fetchNetworkInfo(this.hass), fetchNetworkInfo(this.hass),
fetchHassioResolution(this.hass), fetchHassioResolution(this.hass),
fetchSupervisorStore(this.hass),
]); ]);
this.supervisor = { this.supervisor = {
@ -142,6 +145,7 @@ export class SupervisorBaseElement extends urlSyncMixin(
os, os,
network, network,
resolution, resolution,
store,
}; };
this.addEventListener("supervisor-update", (ev) => this.addEventListener("supervisor-update", (ev) =>

View File

@ -167,7 +167,9 @@ class HassioCoreInfo extends LitElement {
try { try {
await updateCore(this.hass); await updateCore(this.hass);
fireEvent(this, "supervisor-store-refresh", { store: "core" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "core",
});
} catch (err) { } catch (err) {
showAlertDialog(this, { showAlertDialog(this, {
title: "Failed to update Home Assistant Core", title: "Failed to update Home Assistant Core",

View File

@ -340,7 +340,7 @@ class HassioHostInfo extends LitElement {
try { try {
await updateOS(this.hass); await updateOS(this.hass);
fireEvent(this, "supervisor-store-refresh", { store: "os" }); fireEvent(this, "supervisor-colllection-refresh", { colllection: "os" });
} catch (err) { } catch (err) {
showAlertDialog(this, { showAlertDialog(this, {
title: "Failed to update", title: "Failed to update",
@ -369,7 +369,9 @@ class HassioHostInfo extends LitElement {
if (hostname && hostname !== curHostname) { if (hostname && hostname !== curHostname) {
try { try {
await changeHostOptions(this.hass, { hostname }); await changeHostOptions(this.hass, { hostname });
fireEvent(this, "supervisor-store-refresh", { store: "host" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "host",
});
} catch (err) { } catch (err) {
showAlertDialog(this, { showAlertDialog(this, {
title: "Setting hostname failed", title: "Setting hostname failed",
@ -382,7 +384,9 @@ class HassioHostInfo extends LitElement {
private async _importFromUSB(): Promise<void> { private async _importFromUSB(): Promise<void> {
try { try {
await configSyncOS(this.hass); await configSyncOS(this.hass);
fireEvent(this, "supervisor-store-refresh", { store: "host" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "host",
});
} catch (err) { } catch (err) {
showAlertDialog(this, { showAlertDialog(this, {
title: "Failed to import from USB", title: "Failed to import from USB",
@ -393,7 +397,9 @@ class HassioHostInfo extends LitElement {
private async _loadData(): Promise<void> { private async _loadData(): Promise<void> {
if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) { if (atLeastVersion(this.hass.config.version, 2021, 2, 4)) {
fireEvent(this, "supervisor-store-refresh", { store: "network" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "network",
});
} else { } else {
const network = await fetchNetworkInfo(this.hass); const network = await fetchNetworkInfo(this.hass);
fireEvent(this, "supervisor-update", { network }); fireEvent(this, "supervisor-update", { network });

View File

@ -317,7 +317,9 @@ class HassioSupervisorInfo extends LitElement {
private async _reloadSupervisor(): Promise<void> { private async _reloadSupervisor(): Promise<void> {
await reloadSupervisor(this.hass); await reloadSupervisor(this.hass);
fireEvent(this, "supervisor-store-refresh", { store: "supervisor" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "supervisor",
});
} }
private async _supervisorRestart(ev: CustomEvent): Promise<void> { private async _supervisorRestart(ev: CustomEvent): Promise<void> {
@ -366,7 +368,9 @@ class HassioSupervisorInfo extends LitElement {
try { try {
await updateSupervisor(this.hass); await updateSupervisor(this.hass);
fireEvent(this, "supervisor-store-refresh", { store: "supervisor" }); fireEvent(this, "supervisor-colllection-refresh", {
colllection: "supervisor",
});
} catch (err) { } catch (err) {
showAlertDialog(this, { showAlertDialog(this, {
title: "Failed to update the supervisor", title: "Failed to update the supervisor",

View File

@ -4,20 +4,33 @@ import { HomeAssistant } from "../../types";
import { SupervisorArch } from "../supervisor/supervisor"; import { SupervisorArch } from "../supervisor/supervisor";
import { hassioApiResultExtractor, HassioResponse } from "./common"; import { hassioApiResultExtractor, HassioResponse } from "./common";
export type AddonStage = "stable" | "experimental" | "deprecated";
export type AddonAppArmour = "disable" | "default" | "profile";
export type AddonRole = "default" | "homeassistant" | "manager" | "admin";
export type AddonStartup =
| "initialize"
| "system"
| "services"
| "application"
| "once";
export type AddonState = "started" | "stopped" | null;
export type AddonRepository = "core" | "local" | string;
export interface HassioAddonInfo { export interface HassioAddonInfo {
advanced: boolean; advanced: boolean;
available: boolean; available: boolean;
build: boolean; build: boolean;
description: string; description: string;
detached: boolean; detached: boolean;
homeassistant: string;
icon: boolean; icon: boolean;
installed: boolean; installed: boolean;
logo: boolean; logo: boolean;
name: string; name: string;
repository: "core" | "local" | string; repository: AddonRepository;
slug: string; slug: string;
stage: "stable" | "experimental" | "deprecated"; stage: AddonStage;
state: "started" | "stopped" | null; state: AddonState;
update_available: boolean; update_available: boolean;
url: string | null; url: string | null;
version_latest: string; version_latest: string;
@ -25,7 +38,7 @@ export interface HassioAddonInfo {
} }
export interface HassioAddonDetails extends HassioAddonInfo { export interface HassioAddonDetails extends HassioAddonInfo {
apparmor: "disable" | "default" | "profile"; apparmor: AddonAppArmour;
arch: SupervisorArch[]; arch: SupervisorArch[];
audio_input: null | string; audio_input: null | string;
audio_output: null | string; audio_output: null | string;
@ -43,10 +56,9 @@ export interface HassioAddonDetails extends HassioAddonInfo {
full_access: boolean; full_access: boolean;
gpio: boolean; gpio: boolean;
hassio_api: boolean; hassio_api: boolean;
hassio_role: "default" | "homeassistant" | "manager" | "admin"; hassio_role: AddonRole;
hostname: string; hostname: string;
homeassistant_api: boolean; homeassistant_api: boolean;
homeassistant: string;
host_dbus: boolean; host_dbus: boolean;
host_ipc: boolean; host_ipc: boolean;
host_network: boolean; host_network: boolean;
@ -68,7 +80,7 @@ export interface HassioAddonDetails extends HassioAddonInfo {
schema: HaFormSchema[] | null; schema: HaFormSchema[] | null;
services_role: string[]; services_role: string[];
slug: string; slug: string;
startup: "initialize" | "system" | "services" | "application" | "once"; startup: AddonStartup;
stdin: boolean; stdin: boolean;
watchdog: null | boolean; watchdog: null | boolean;
webui: null | string; webui: null | string;

View File

@ -0,0 +1,51 @@
import { atLeastVersion } from "../../common/config/version";
import { HomeAssistant } from "../../types";
import { AddonRepository, AddonStage } from "../hassio/addon";
import { hassioApiResultExtractor, HassioResponse } from "../hassio/common";
export interface StoreAddon {
advanced: boolean;
available: boolean;
build: boolean;
description: string;
homeassistant: string | null;
icon: boolean;
installed: boolean;
logo: boolean;
name: string;
repository: AddonRepository;
slug: string;
stage: AddonStage;
update_available: boolean;
url: string;
version: string | null;
version_latest: string;
}
interface StoreRepository {
maintainer: string;
name: string;
slug: string;
source: string;
url: string;
}
export interface SupervisorStore {
addons: StoreAddon[];
repositories: StoreRepository[];
}
export const fetchSupervisorStore = async (
hass: HomeAssistant
): Promise<SupervisorStore> => {
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
return await hass.callWS({
type: "supervisor/api",
endpoint: "/store",
method: "get",
});
}
return hassioApiResultExtractor(
await hass.callApi<HassioResponse<SupervisorStore>>("GET", `hassio/store`)
);
};

View File

@ -10,13 +10,14 @@ import {
HassioInfo, HassioInfo,
HassioSupervisorInfo, HassioSupervisorInfo,
} from "../hassio/supervisor"; } from "../hassio/supervisor";
import { SupervisorStore } from "./store";
export const supervisorWSbaseCommand = { export const supervisorWSbaseCommand = {
type: "supervisor/api", type: "supervisor/api",
method: "GET", method: "GET",
}; };
export const supervisorStore = { export const supervisorCollection = {
host: "/host/info", host: "/host/info",
supervisor: "/supervisor/info", supervisor: "/supervisor/info",
info: "/info", info: "/info",
@ -25,6 +26,7 @@ export const supervisorStore = {
resolution: "/resolution/info", resolution: "/resolution/info",
os: "/os/info", os: "/os/info",
addon: "/addons", addon: "/addons",
store: "/store",
}; };
export type SupervisorArch = "armhf" | "armv7" | "aarch64" | "i386" | "amd64"; export type SupervisorArch = "armhf" | "armv7" | "aarch64" | "i386" | "amd64";
@ -36,7 +38,8 @@ export type SupervisorObject =
| "network" | "network"
| "resolution" | "resolution"
| "os" | "os"
| "addon"; | "addon"
| "store";
interface supervisorApiRequest { interface supervisorApiRequest {
endpoint: string; endpoint: string;
@ -61,6 +64,7 @@ export interface Supervisor {
resolution: HassioResolution; resolution: HassioResolution;
os: HassioHassOSInfo; os: HassioHassOSInfo;
addon: HassioAddonsInfo; addon: HassioAddonsInfo;
store: SupervisorStore;
} }
export const supervisorApiWsRequest = <T>( export const supervisorApiWsRequest = <T>(
@ -81,7 +85,7 @@ async function processEvent(
if (Object.keys(event.data).length === 0) { if (Object.keys(event.data).length === 0) {
const data = await supervisorApiWsRequest<any>(conn, { const data = await supervisorApiWsRequest<any>(conn, {
endpoint: supervisorStore[key], endpoint: supervisorCollection[key],
}); });
store.setState(data); store.setState(data);
return; return;