mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 10:16:46 +00:00
Move to supervisor store API (#12911)
* Move to supervisor store API * Add supervisorApiCall helper to simplify functions * Do not consider ESPHome as custom repository * Home Assistant Community Add-ons is not custom
This commit is contained in:
parent
bc47ecaa57
commit
4ad49ef07f
@ -6,10 +6,8 @@ import { atLeastVersion } from "../../../src/common/config/version";
|
|||||||
import { navigate } from "../../../src/common/navigate";
|
import { navigate } from "../../../src/common/navigate";
|
||||||
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
import { caseInsensitiveStringCompare } from "../../../src/common/string/compare";
|
||||||
import "../../../src/components/ha-card";
|
import "../../../src/components/ha-card";
|
||||||
import {
|
import { HassioAddonRepository } from "../../../src/data/hassio/addon";
|
||||||
HassioAddonInfo,
|
import { StoreAddon } from "../../../src/data/supervisor/store";
|
||||||
HassioAddonRepository,
|
|
||||||
} from "../../../src/data/hassio/addon";
|
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import { HomeAssistant } from "../../../src/types";
|
import { HomeAssistant } from "../../../src/types";
|
||||||
import "../components/hassio-card-content";
|
import "../components/hassio-card-content";
|
||||||
@ -23,20 +21,16 @@ class HassioAddonRepositoryEl extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public repo!: HassioAddonRepository;
|
@property({ attribute: false }) public repo!: HassioAddonRepository;
|
||||||
|
|
||||||
@property({ attribute: false }) public addons!: HassioAddonInfo[];
|
@property({ attribute: false }) public addons!: StoreAddon[];
|
||||||
|
|
||||||
@property() public filter!: string;
|
@property() public filter!: string;
|
||||||
|
|
||||||
private _getAddons = memoizeOne(
|
private _getAddons = memoizeOne((addons: StoreAddon[], filter?: string) => {
|
||||||
(addons: HassioAddonInfo[], filter?: string) => {
|
if (filter) {
|
||||||
if (filter) {
|
return filterAndSort(addons, filter);
|
||||||
return filterAndSort(addons, filter);
|
|
||||||
}
|
|
||||||
return addons.sort((a, b) =>
|
|
||||||
caseInsensitiveStringCompare(a.name, b.name)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
return addons.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name));
|
||||||
|
});
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const repo = this.repo;
|
const repo = this.repo;
|
||||||
|
@ -14,15 +14,15 @@ 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";
|
||||||
import "../../../src/components/search-input";
|
|
||||||
import { extractSearchParam } from "../../../src/common/url/search-params";
|
import { extractSearchParam } from "../../../src/common/url/search-params";
|
||||||
import "../../../src/components/ha-button-menu";
|
import "../../../src/components/ha-button-menu";
|
||||||
import "../../../src/components/ha-icon-button";
|
import "../../../src/components/ha-icon-button";
|
||||||
|
import "../../../src/components/search-input";
|
||||||
import {
|
import {
|
||||||
HassioAddonInfo,
|
|
||||||
HassioAddonRepository,
|
HassioAddonRepository,
|
||||||
reloadHassioAddons,
|
reloadHassioAddons,
|
||||||
} from "../../../src/data/hassio/addon";
|
} from "../../../src/data/hassio/addon";
|
||||||
|
import { StoreAddon } from "../../../src/data/supervisor/store";
|
||||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||||
import "../../../src/layouts/hass-loading-screen";
|
import "../../../src/layouts/hass-loading-screen";
|
||||||
import "../../../src/layouts/hass-subpage";
|
import "../../../src/layouts/hass-subpage";
|
||||||
@ -66,10 +66,10 @@ class HassioAddonStore extends LitElement {
|
|||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
let repos: TemplateResult[] = [];
|
let repos: TemplateResult[] = [];
|
||||||
|
|
||||||
if (this.supervisor.addon.repositories) {
|
if (this.supervisor.store.repositories) {
|
||||||
repos = this.addonRepositories(
|
repos = this.addonRepositories(
|
||||||
this.supervisor.addon.repositories,
|
this.supervisor.store.repositories,
|
||||||
this.supervisor.addon.addons,
|
this.supervisor.store.addons,
|
||||||
this._filter
|
this._filter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ class HassioAddonStore extends LitElement {
|
|||||||
private addonRepositories = memoizeOne(
|
private addonRepositories = memoizeOne(
|
||||||
(
|
(
|
||||||
repositories: HassioAddonRepository[],
|
repositories: HassioAddonRepository[],
|
||||||
addons: HassioAddonInfo[],
|
addons: StoreAddon[],
|
||||||
filter?: string
|
filter?: string
|
||||||
) =>
|
) =>
|
||||||
repositories.sort(sortRepos).map((repo) => {
|
repositories.sort(sortRepos).map((repo) => {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
import { HassioAddonInfo } from "../../../src/data/hassio/addon";
|
import { StoreAddon } from "../../../src/data/supervisor/store";
|
||||||
|
|
||||||
export function filterAndSort(addons: HassioAddonInfo[], filter: string) {
|
export function filterAndSort(addons: StoreAddon[], filter: string) {
|
||||||
const options: Fuse.IFuseOptions<HassioAddonInfo> = {
|
const options: Fuse.IFuseOptions<StoreAddon> = {
|
||||||
keys: ["name", "description", "slug"],
|
keys: ["name", "description", "slug"],
|
||||||
isCaseSensitive: false,
|
isCaseSensitive: false,
|
||||||
minMatchCharLength: 2,
|
minMatchCharLength: 2,
|
||||||
|
@ -15,15 +15,18 @@ import "../../../../src/components/ha-circular-progress";
|
|||||||
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
import { createCloseHeading } from "../../../../src/components/ha-dialog";
|
||||||
import "../../../../src/components/ha-icon-button";
|
import "../../../../src/components/ha-icon-button";
|
||||||
import {
|
import {
|
||||||
fetchHassioAddonsInfo,
|
|
||||||
HassioAddonInfo,
|
HassioAddonInfo,
|
||||||
HassioAddonRepository,
|
HassioAddonRepository,
|
||||||
} from "../../../../src/data/hassio/addon";
|
} from "../../../../src/data/hassio/addon";
|
||||||
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
|
||||||
import { setSupervisorOption } from "../../../../src/data/hassio/supervisor";
|
|
||||||
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
import { HassioRepositoryDialogParams } from "./show-dialog-repositories";
|
||||||
|
import {
|
||||||
|
addStoreRepository,
|
||||||
|
fetchStoreRepositories,
|
||||||
|
removeStoreRepository,
|
||||||
|
} from "../../../../src/data/supervisor/store";
|
||||||
|
|
||||||
@customElement("dialog-hassio-repositories")
|
@customElement("dialog-hassio-repositories")
|
||||||
class HassioRepositoriesDialog extends LitElement {
|
class HassioRepositoriesDialog extends LitElement {
|
||||||
@ -58,7 +61,13 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
|
|
||||||
private _filteredRepositories = memoizeOne((repos: HassioAddonRepository[]) =>
|
private _filteredRepositories = memoizeOne((repos: HassioAddonRepository[]) =>
|
||||||
repos
|
repos
|
||||||
.filter((repo) => repo.slug !== "core" && repo.slug !== "local")
|
.filter(
|
||||||
|
(repo) =>
|
||||||
|
repo.slug !== "core" && // The core add-ons repository
|
||||||
|
repo.slug !== "local" && // Locally managed add-ons
|
||||||
|
repo.slug !== "a0d7b954" && // Home Assistant Community Add-ons
|
||||||
|
repo.slug !== "5c53de3b" // The ESPHome repository
|
||||||
|
)
|
||||||
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
|
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name))
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -215,9 +224,7 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
|
|
||||||
private async _loadData(): Promise<void> {
|
private async _loadData(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const addonsinfo = await fetchHassioAddonsInfo(this.hass);
|
this._repositories = await fetchStoreRepositories(this.hass);
|
||||||
|
|
||||||
this._repositories = addonsinfo.repositories;
|
|
||||||
|
|
||||||
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
fireEvent(this, "supervisor-collection-refresh", { collection: "addon" });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
@ -231,14 +238,9 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._processing = true;
|
this._processing = true;
|
||||||
const repositories = this._filteredRepositories(this._repositories!);
|
|
||||||
const newRepositories = repositories.map((repo) => repo.source);
|
|
||||||
newRepositories.push(input.value);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setSupervisorOption(this.hass, {
|
await addStoreRepository(this.hass, input.value);
|
||||||
addons_repositories: newRepositories,
|
|
||||||
});
|
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
|
|
||||||
input.value = "";
|
input.value = "";
|
||||||
@ -250,19 +252,8 @@ class HassioRepositoriesDialog extends LitElement {
|
|||||||
|
|
||||||
private async _removeRepository(ev: Event) {
|
private async _removeRepository(ev: Event) {
|
||||||
const slug = (ev.currentTarget as any).slug;
|
const slug = (ev.currentTarget as any).slug;
|
||||||
const repositories = this._filteredRepositories(this._repositories!);
|
|
||||||
const repository = repositories.find((repo) => repo.slug === slug);
|
|
||||||
if (!repository) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const newRepositories = repositories
|
|
||||||
.map((repo) => repo.source)
|
|
||||||
.filter((repo) => repo !== repository.source);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setSupervisorOption(this.hass, {
|
await removeStoreRepository(this.hass, slug);
|
||||||
addons_repositories: newRepositories,
|
|
||||||
});
|
|
||||||
await this._loadData();
|
await this._loadData();
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this._error = extractApiErrorMessage(err);
|
this._error = extractApiErrorMessage(err);
|
||||||
|
34
src/data/supervisor/common.ts
Normal file
34
src/data/supervisor/common.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { atLeastVersion } from "../../common/config/version";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
import { hassioApiResultExtractor, HassioResponse } from "../hassio/common";
|
||||||
|
|
||||||
|
export interface SupervisorApiCallOptions {
|
||||||
|
method?: "get" | "post" | "delete";
|
||||||
|
data?: Record<string, any>;
|
||||||
|
timeout?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const supervisorApiCall = async <T>(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
endpoint: string,
|
||||||
|
options?: SupervisorApiCallOptions
|
||||||
|
): Promise<T> => {
|
||||||
|
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
||||||
|
// Websockets was added in 2021.2.4
|
||||||
|
return hass.callWS<T>({
|
||||||
|
type: "supervisor/api",
|
||||||
|
endpoint,
|
||||||
|
method: options?.method || "get",
|
||||||
|
timeout: options?.timeout ?? null,
|
||||||
|
data: options?.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return hassioApiResultExtractor(
|
||||||
|
await hass.callApi<HassioResponse<T>>(
|
||||||
|
// @ts-ignore
|
||||||
|
(options.method || "get").toUpperCase(),
|
||||||
|
`hassio${endpoint}`,
|
||||||
|
options?.data
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
@ -1,7 +1,6 @@
|
|||||||
import { atLeastVersion } from "../../common/config/version";
|
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import { AddonRepository, AddonStage } from "../hassio/addon";
|
import { AddonRepository, AddonStage } from "../hassio/addon";
|
||||||
import { hassioApiResultExtractor, HassioResponse } from "../hassio/common";
|
import { supervisorApiCall } from "./common";
|
||||||
|
|
||||||
export interface StoreAddon {
|
export interface StoreAddon {
|
||||||
advanced: boolean;
|
advanced: boolean;
|
||||||
@ -36,16 +35,25 @@ export interface SupervisorStore {
|
|||||||
|
|
||||||
export const fetchSupervisorStore = async (
|
export const fetchSupervisorStore = async (
|
||||||
hass: HomeAssistant
|
hass: HomeAssistant
|
||||||
): Promise<SupervisorStore> => {
|
): Promise<SupervisorStore> => supervisorApiCall(hass, "/store");
|
||||||
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
|
|
||||||
return hass.callWS({
|
|
||||||
type: "supervisor/api",
|
|
||||||
endpoint: "/store",
|
|
||||||
method: "get",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return hassioApiResultExtractor(
|
export const fetchStoreRepositories = async (
|
||||||
await hass.callApi<HassioResponse<SupervisorStore>>("GET", `hassio/store`)
|
hass: HomeAssistant
|
||||||
);
|
): Promise<StoreRepository[]> => supervisorApiCall(hass, "/store/repositories");
|
||||||
};
|
|
||||||
|
export const addStoreRepository = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
repository: string
|
||||||
|
): Promise<void> =>
|
||||||
|
supervisorApiCall(hass, "/store/repositories", {
|
||||||
|
method: "post",
|
||||||
|
data: { repository },
|
||||||
|
});
|
||||||
|
|
||||||
|
export const removeStoreRepository = async (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
repository: string
|
||||||
|
): Promise<void> =>
|
||||||
|
supervisorApiCall(hass, `/store/repositories/${repository}`, {
|
||||||
|
method: "delete",
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user