Split store and installed calls (#12921)

* Split store and installed calls

* Fix issue when installing

* Remove supervisor.addons usage

* one more

* Update core

* Comments
This commit is contained in:
Joakim Sørensen 2022-06-11 11:04:54 +02:00 committed by GitHub
parent 0926202eca
commit e7848262ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 107 additions and 60 deletions

View File

@ -12,15 +12,17 @@ import { navigate } from "../../../src/common/navigate";
import { extractSearchParam } from "../../../src/common/url/search-params";
import "../../../src/components/ha-circular-progress";
import {
fetchAddonInfo,
fetchHassioAddonInfo,
fetchHassioAddonsInfo,
HassioAddonDetails,
} from "../../../src/data/hassio/addon";
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
import {
fetchHassioSupervisorInfo,
setSupervisorOption,
} from "../../../src/data/hassio/supervisor";
addStoreRepository,
fetchSupervisorStore,
StoreAddonDetails,
} from "../../../src/data/supervisor/store";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import { showConfirmationDialog } from "../../../src/dialogs/generic/show-dialog-box";
import "../../../src/layouts/hass-error-screen";
@ -45,7 +47,9 @@ class HassioAddonDashboard extends LitElement {
@property({ attribute: false }) public route!: Route;
@property({ attribute: false }) public addon?: HassioAddonDetails;
@property({ attribute: false }) public addon?:
| HassioAddonDetails
| StoreAddonDetails;
@property({ type: Boolean }) public narrow!: boolean;
@ -173,10 +177,10 @@ class HassioAddonDashboard extends LitElement {
const requestedAddon = extractSearchParam("addon");
const requestedAddonRepository = extractSearchParam("repository_url");
if (requestedAddonRepository) {
const supervisorInfo = await fetchHassioSupervisorInfo(this.hass);
const storeInfo = await fetchSupervisorStore(this.hass);
if (
!supervisorInfo.addons_repositories.find(
(repo) => repo === requestedAddonRepository
!storeInfo.repositories.find(
(repo) => repo.source === requestedAddonRepository
)
) {
if (
@ -197,12 +201,7 @@ class HassioAddonDashboard extends LitElement {
}
try {
await setSupervisorOption(this.hass, {
addons_repositories: [
...supervisorInfo.addons_repositories,
requestedAddonRepository,
],
});
await addStoreRepository(this.hass, requestedAddonRepository);
} catch (err: any) {
this._error = extractApiErrorMessage(err);
}
@ -245,6 +244,8 @@ class HassioAddonDashboard extends LitElement {
if (path === "uninstall") {
window.history.back();
} else if (path === "install") {
this.addon = await fetchHassioAddonInfo(this.hass, this.addon!.slug);
} else {
await this._routeDataChanged();
}
@ -262,8 +263,7 @@ class HassioAddonDashboard extends LitElement {
return;
}
try {
const addoninfo = await fetchHassioAddonInfo(this.hass, addon);
this.addon = addoninfo;
this.addon = await fetchAddonInfo(this.hass, this.supervisor, addon);
} catch (err: any) {
this._error = `Error fetching addon info: ${extractApiErrorMessage(err)}`;
this.addon = undefined;

View File

@ -1,5 +1,6 @@
import { customElement, property } from "lit/decorators";
import { HassioAddonDetails } from "../../../src/data/hassio/addon";
import { StoreAddonDetails } from "../../../src/data/supervisor/store";
import { Supervisor } from "../../../src/data/supervisor/supervisor";
import {
HassRouterPage,
@ -20,7 +21,9 @@ class HassioAddonRouter extends HassRouterPage {
@property({ attribute: false }) public supervisor!: Supervisor;
@property({ attribute: false }) public addon!: HassioAddonDetails;
@property({ attribute: false }) public addon!:
| HassioAddonDetails
| StoreAddonDetails;
protected routerOptions: RouterOptions = {
defaultPage: "info",

View File

@ -59,7 +59,10 @@ import {
fetchHassioStats,
HassioStats,
} from "../../../../src/data/hassio/common";
import { StoreAddon } from "../../../../src/data/supervisor/store";
import {
StoreAddon,
StoreAddonDetails,
} from "../../../../src/data/supervisor/store";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import {
showAlertDialog,
@ -100,7 +103,9 @@ class HassioAddonInfo extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public addon!: HassioAddonDetails;
@property({ attribute: false }) public addon!:
| HassioAddonDetails
| StoreAddonDetails;
@property({ attribute: false }) public supervisor!: Supervisor;
@ -143,7 +148,7 @@ class HassioAddonInfo extends LitElement {
></update-available-card>
`
: ""}
${!this.addon.protected
${"protected" in this.addon && !this.addon.protected
? html`
<ha-alert
alert-type="error"
@ -518,7 +523,7 @@ class HassioAddonInfo extends LitElement {
: ""}
</div>
<div>
${this.addon.state === "started"
${this.addon.version && this.addon.state === "started"
? html`<ha-settings-row ?three-line=${this.narrow}>
<span slot="heading">
${this.supervisor.localize("addon.dashboard.hostname")}
@ -669,7 +674,7 @@ class HassioAddonInfo extends LitElement {
}
private async _loadData(): Promise<void> {
if (this.addon.state === "started") {
if ("state" in this.addon && this.addon.state === "started") {
this._metrics = await fetchHassioStats(
this.hass,
`addons/${this.addon.slug}`
@ -717,18 +722,22 @@ class HassioAddonInfo extends LitElement {
}
private get _computeIsRunning(): boolean {
return this.addon?.state === "started";
return (this.addon as HassioAddonDetails)?.state === "started";
}
private get _pathWebui(): string | null {
return (
this.addon.webui &&
this.addon.webui.replace("[HOST]", document.location.hostname)
return (this.addon as HassioAddonDetails).webui!.replace(
"[HOST]",
document.location.hostname
);
}
private get _computeShowWebUI(): boolean | "" | null {
return !this.addon.ingress && this.addon.webui && this._computeIsRunning;
return (
!this.addon.ingress &&
(this.addon as HassioAddonDetails).webui &&
this._computeIsRunning
);
}
private _openIngress(): void {
@ -754,7 +763,8 @@ class HassioAddonInfo extends LitElement {
private async _startOnBootToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
boot: this.addon.boot === "auto" ? "manual" : "auto",
boot:
(this.addon as HassioAddonDetails).boot === "auto" ? "manual" : "auto",
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@ -776,7 +786,7 @@ class HassioAddonInfo extends LitElement {
private async _watchdogToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
watchdog: !this.addon.watchdog,
watchdog: !(this.addon as HassioAddonDetails).watchdog,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@ -798,7 +808,7 @@ class HassioAddonInfo extends LitElement {
private async _autoUpdateToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
auto_update: !this.addon.auto_update,
auto_update: !(this.addon as HassioAddonDetails).auto_update,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@ -820,7 +830,7 @@ class HassioAddonInfo extends LitElement {
private async _protectionToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetSecurityParams = {
protected: !this.addon.protected,
protected: !(this.addon as HassioAddonDetails).protected,
};
try {
await setHassioAddonSecurity(this.hass, this.addon.slug, data);
@ -842,7 +852,7 @@ class HassioAddonInfo extends LitElement {
private async _panelToggled(): Promise<void> {
this._error = undefined;
const data: HassioAddonSetOptionParams = {
ingress_panel: !this.addon.ingress_panel,
ingress_panel: !(this.addon as HassioAddonDetails).ingress_panel,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
@ -870,7 +880,7 @@ class HassioAddonInfo extends LitElement {
showHassioMarkdownDialog(this, {
title: this.supervisor.localize("addon.dashboard.changelog"),
content: extractChangelog(this.addon, content),
content: extractChangelog(this.addon as HassioAddonDetails, content),
});
} catch (err: any) {
showAlertDialog(this, {

View File

@ -98,9 +98,8 @@ export class HassioBackups extends LitElement {
if (backup.content.addons.length !== 0) {
for (const addon of backup.content.addons) {
content.push(
this.supervisor.supervisor.addons.find(
(entry) => entry.slug === addon
)?.name || addon
this.supervisor.addon.addons.find((entry) => entry.slug === addon)
?.name || addon
);
}
}

View File

@ -96,7 +96,7 @@ export class SupervisorBackupContent extends LitElement {
: ["ssl", "share", "media", "addons/local"]
);
this.addons = _computeAddons(
this.backup ? this.backup.addons : this.supervisor?.supervisor.addons
this.backup ? this.backup.addons : this.supervisor?.addon.addons
);
this.backupType = this.backup?.type || "full";
this.backupName = this.backup?.name || "";

View File

@ -24,7 +24,7 @@ class HassioAddons extends LitElement {
? html` <h1>${this.supervisor.localize("dashboard.addons")}</h1> `
: ""}
<div class="card-group">
${!this.supervisor.supervisor.addons?.length
${!this.supervisor.addon.addons.length
? html`
<ha-card outlined>
<div class="card-content">
@ -34,7 +34,7 @@ class HassioAddons extends LitElement {
</div>
</ha-card>
`
: this.supervisor.supervisor.addons
: this.supervisor.addon.addons
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
.map(
(addon) => html`

View File

@ -87,7 +87,7 @@ class HassioRepositoriesDialog extends LitElement {
const repositories = this._filteredRepositories(this._repositories);
const usedRepositories = this._filteredUsedRepositories(
repositories,
this._dialogParams.supervisor.supervisor.addons
this._dialogParams.supervisor.addon.addons
);
return html`
<ha-dialog

View File

@ -4,8 +4,7 @@ import { customElement, property, query, state } from "lit/decorators";
import { isComponentLoaded } from "../common/config/is_component_loaded";
import { fireEvent } from "../common/dom/fire_event";
import { stringCompare } from "../common/string/compare";
import { HassioAddonInfo } from "../data/hassio/addon";
import { fetchHassioSupervisorInfo } from "../data/hassio/supervisor";
import { fetchHassioAddonsInfo, HassioAddonInfo } from "../data/hassio/addon";
import { showAlertDialog } from "../dialogs/generic/show-dialog-box";
import { PolymerChangedEvent } from "../polymer-types";
import { HomeAssistant } from "../types";
@ -78,10 +77,10 @@ class HaAddonPicker extends LitElement {
private async _getAddons() {
try {
if (isComponentLoaded(this.hass, "hassio")) {
const supervisorInfo = await fetchHassioSupervisorInfo(this.hass);
this._addons = supervisorInfo.addons.sort((a, b) =>
stringCompare(a.name, b.name)
);
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
this._addons = addonsInfo.addons
.filter((addon) => addon.version)
.sort((a, b) => stringCompare(a.name, b.name));
} else {
showAlertDialog(this, {
title: this.hass.localize(

View File

@ -1,7 +1,9 @@
import { atLeastVersion } from "../../common/config/version";
import type { HaFormSchema } from "../../components/ha-form/types";
import { HomeAssistant } from "../../types";
import { SupervisorArch } from "../supervisor/supervisor";
import { supervisorApiCall } from "../supervisor/common";
import { StoreAddonDetails } from "../supervisor/store";
import { Supervisor, SupervisorArch } from "../supervisor/supervisor";
import {
extractApiErrorMessage,
hassioApiResultExtractor,
@ -363,3 +365,15 @@ export const uninstallHassioAddon = async (
`hassio/addons/${slug}/uninstall`
);
};
export const fetchAddonInfo = (
hass: HomeAssistant,
supervisor: Supervisor,
addonSlug: string
): Promise<HassioAddonDetails | StoreAddonDetails> =>
supervisorApiCall(
hass,
!supervisor.addon?.addons.find((addon) => addon.slug === addonSlug)
? `/store/addons/${addonSlug}` // Use /store/addons when add-on is not installed
: `/addons/${addonSlug}/info` // Use /addons when add-on is installed
);

View File

@ -1,7 +1,6 @@
import { atLeastVersion } from "../../common/config/version";
import { HomeAssistant, PanelInfo } from "../../types";
import { SupervisorArch } from "../supervisor/supervisor";
import { HassioAddonInfo } from "./addon";
import { hassioApiResultExtractor, HassioResponse } from "./common";
export type HassioHomeAssistantInfo = {
@ -22,7 +21,7 @@ export type HassioHomeAssistantInfo = {
};
export type HassioSupervisorInfo = {
addons: HassioAddonInfo[];
addons: string[];
addons_repositories: string[];
arch: SupervisorArch;
channel: string;

View File

@ -1,6 +1,7 @@
import { HomeAssistant } from "../../types";
import { AddonRepository, AddonStage } from "../hassio/addon";
import { AddonStage } from "../hassio/addon";
import { supervisorApiCall } from "./common";
import { SupervisorArch } from "./supervisor";
export interface StoreAddon {
advanced: boolean;
@ -12,14 +13,34 @@ export interface StoreAddon {
installed: boolean;
logo: boolean;
name: string;
repository: AddonRepository;
repository: string;
slug: string;
stage: AddonStage;
update_available: boolean;
url: string;
version: string | null;
version_latest: string;
version: null;
}
export interface StoreAddonDetails extends StoreAddon {
apparmor: boolean;
arch: SupervisorArch[];
auth_api: boolean;
detached: boolean;
docker_api: boolean;
documentation: boolean;
full_access: boolean;
hassio_api: boolean;
hassio_role: string;
homeassistant_api: boolean;
host_network: boolean;
host_pid: boolean;
ingress: boolean;
long_description: string;
rating: number;
signed: boolean;
}
interface StoreRepository {
maintainer: string;
name: string;

View File

@ -34,7 +34,7 @@ import "../../components/ha-circular-progress";
import "../../components/ha-header-bar";
import "../../components/ha-icon-button";
import "../../components/ha-textfield";
import { fetchHassioSupervisorInfo } from "../../data/hassio/supervisor";
import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
import { domainToName } from "../../data/integration";
import { getPanelNameTranslationKey } from "../../data/panel";
import { PageNavigation } from "../../layouts/hass-tabs-subpage";
@ -586,7 +586,7 @@ export class QuickBar extends LitElement {
const sectionItems = this._generateNavigationConfigSectionCommands();
const supervisorItems: BaseNavigationCommand[] = [];
if (isComponentLoaded(this.hass, "hassio")) {
const supervisorInfo = await fetchHassioSupervisorInfo(this.hass);
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
supervisorItems.push({
path: "/hassio/store",
primaryText: this.hass.localize(
@ -599,7 +599,7 @@ export class QuickBar extends LitElement {
"ui.dialogs.quick-bar.commands.navigation.addon_dashboard"
),
});
for (const addon of supervisorInfo.addons) {
for (const addon of addonsInfo.addons.filter((a) => a.version)) {
supervisorItems.push({
path: `/hassio/addon/${addon.slug}`,
primaryText: this.hass.localize(

View File

@ -6,7 +6,7 @@ import { extractSearchParam } from "../../../common/url/search-params";
import "../../../components/ha-button-menu";
import "../../../components/search-input";
import { LogProvider } from "../../../data/error_log";
import { fetchHassioSupervisorInfo } from "../../../data/hassio/supervisor";
import { fetchHassioAddonsInfo } from "../../../data/hassio/addon";
import "../../../layouts/hass-subpage";
import "../../../layouts/hass-tabs-subpage";
import { haStyle } from "../../../resources/styles";
@ -167,13 +167,15 @@ export class HaConfigLogs extends LitElement {
private async _getInstalledAddons() {
try {
const supervisorInfo = await fetchHassioSupervisorInfo(this.hass);
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
this._logProviders = [
...this._logProviders,
...supervisorInfo.addons.map((addon) => ({
key: addon.slug,
name: addon.name,
})),
...addonsInfo.addons
.filter((addon) => addon.version)
.map((addon) => ({
key: addon.slug,
name: addon.name,
})),
];
} catch (err) {
// Ignore, nothing the user can do anyway