diff --git a/hassio/src/addon-view/hassio-addon-network.js b/hassio/src/addon-view/hassio-addon-network.js
index b516c5e576..3c5b768188 100644
--- a/hassio/src/addon-view/hassio-addon-network.js
+++ b/hassio/src/addon-view/hassio-addon-network.js
@@ -44,6 +44,7 @@ class HassioAddonNetwork extends EventsMixin(PolymerElement) {
[[item.container]] |
diff --git a/hassio/src/hassio-main.ts b/hassio/src/hassio-main.ts
index cc4123630c..fb0766c77e 100644
--- a/hassio/src/hassio-main.ts
+++ b/hassio/src/hassio-main.ts
@@ -17,6 +17,9 @@ import {
HassioSupervisorInfo,
HassioHostInfo,
HassioHomeAssistantInfo,
+ fetchHassioAddonInfo,
+ createHassioSession,
+ HassioPanelInfo,
} from "../../src/data/hassio";
import { makeDialogManager } from "../../src/dialogs/make-dialog-manager";
import { ProvideHassLitMixin } from "../../src/mixins/provide-hass-lit-mixin";
@@ -32,6 +35,7 @@ customElements.get("paper-icon-button").prototype._keyBindings = {};
@customElement("hassio-main")
class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
@property() public hass!: HomeAssistant;
+ @property() public panel!: HassioPanelInfo;
protected routerOptions: RouterOptions = {
// Hass.io has a page with tabs, so we route all non-matching routes to it.
@@ -117,6 +121,11 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
}
private async _fetchData() {
+ if (this.panel.config && this.panel.config.ingress) {
+ await this._redirectIngress(this.panel.config.ingress);
+ return;
+ }
+
const [supervisorInfo, hostInfo, hassInfo] = await Promise.all([
fetchHassioSupervisorInfo(this.hass),
fetchHassioHostInfo(this.hass),
@@ -127,6 +136,28 @@ class HassioMain extends ProvideHassLitMixin(HassRouterPage) {
this._hassInfo = hassInfo;
}
+ private async _redirectIngress(addonSlug: string) {
+ try {
+ const [addon] = await Promise.all([
+ fetchHassioAddonInfo(this.hass, addonSlug).catch(() => {
+ throw new Error("Failed to fetch add-on info");
+ }),
+ createHassioSession(this.hass).catch(() => {
+ throw new Error("Failed to create an ingress session");
+ }),
+ ]);
+ if (!addon.ingress_url) {
+ throw new Error("Add-on does not support Ingress");
+ }
+ location.assign(addon.ingress_url);
+ // await a promise that doesn't resolve, so we show the loading screen
+ // while we load the next page.
+ await new Promise(() => undefined);
+ } catch (err) {
+ alert(`Unable to open ingress connection `);
+ }
+ }
+
private _apiCalled(ev) {
if (!ev.detail.success) {
return;
diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts
index 98d0a5e097..50428786ad 100644
--- a/src/components/ha-sidebar.ts
+++ b/src/components/ha-sidebar.ts
@@ -15,7 +15,7 @@ import "./ha-icon";
import "../components/user/ha-user-badge";
import isComponentLoaded from "../common/config/is_component_loaded";
-import { HomeAssistant, Panel } from "../types";
+import { HomeAssistant, PanelInfo } from "../types";
import { fireEvent } from "../common/dom/fire_event";
import { DEFAULT_PANEL } from "../common/const";
@@ -32,7 +32,9 @@ const computePanels = (hass: HomeAssistant) => {
logbook: 2,
history: 3,
};
- const result: Panel[] = Object.values(panels).filter((panel) => panel.title);
+ const result: PanelInfo[] = Object.values(panels).filter(
+ (panel) => panel.title
+ );
result.sort((a, b) => {
const aBuiltIn = a.component_name in sortValue;
diff --git a/src/data/hassio.ts b/src/data/hassio.ts
index ab3b840df3..5790a90e40 100644
--- a/src/data/hassio.ts
+++ b/src/data/hassio.ts
@@ -1,4 +1,11 @@
-import { HomeAssistant } from "../types";
+import { HomeAssistant, PanelInfo } from "../types";
+
+export type HassioPanelInfo = PanelInfo<
+ | undefined
+ | {
+ ingress?: string;
+ }
+>;
interface HassioResponse {
data: T;
diff --git a/src/data/panel_custom.ts b/src/data/panel_custom.ts
index 7f8ad4a29e..ce09a24408 100644
--- a/src/data/panel_custom.ts
+++ b/src/data/panel_custom.ts
@@ -1,3 +1,5 @@
+import { PanelInfo } from "../types";
+
export interface CustomPanelConfig {
name: string;
embed_iframe: boolean;
@@ -6,3 +8,7 @@ export interface CustomPanelConfig {
module_url?: string;
html_url?: string;
}
+
+export type CustomPanelInfo = PanelInfo<
+ T & { _panel_custom: CustomPanelConfig }
+>;
diff --git a/src/entrypoints/custom-panel.ts b/src/entrypoints/custom-panel.ts
index 7f0bc53dd0..46e3eb2527 100644
--- a/src/entrypoints/custom-panel.ts
+++ b/src/entrypoints/custom-panel.ts
@@ -4,8 +4,7 @@ import { createCustomPanelElement } from "../util/custom-panel/create-custom-pan
import { setCustomPanelProperties } from "../util/custom-panel/set-custom-panel-properties";
import { fireEvent } from "../common/dom/fire_event";
import { PolymerElement } from "@polymer/polymer";
-import { Panel } from "../types";
-import { CustomPanelConfig } from "../data/panel_custom";
+import { CustomPanelInfo } from "../data/panel_custom";
declare global {
interface Window {
@@ -39,12 +38,12 @@ function setProperties(properties) {
setCustomPanelProperties(panelEl, properties);
}
-function initialize(panel: Panel, properties: {}) {
+function initialize(panel: CustomPanelInfo, properties: {}) {
const style = document.createElement("style");
style.innerHTML = "body{margin:0}";
document.head.appendChild(style);
- const config = panel.config!._panel_custom as CustomPanelConfig;
+ const config = panel.config._panel_custom;
let start: Promise = Promise.resolve();
if (!webComponentsSupported) {
diff --git a/src/panels/custom/ha-panel-custom.ts b/src/panels/custom/ha-panel-custom.ts
index b7de1b6b30..563ccb6a18 100644
--- a/src/panels/custom/ha-panel-custom.ts
+++ b/src/panels/custom/ha-panel-custom.ts
@@ -2,8 +2,8 @@ import { property, PropertyValues, UpdatingElement } from "lit-element";
import { loadCustomPanel } from "../../util/custom-panel/load-custom-panel";
import { createCustomPanelElement } from "../../util/custom-panel/create-custom-panel-element";
import { setCustomPanelProperties } from "../../util/custom-panel/set-custom-panel-properties";
-import { HomeAssistant, Route, Panel } from "../../types";
-import { CustomPanelConfig } from "../../data/panel_custom";
+import { HomeAssistant, Route } from "../../types";
+import { CustomPanelInfo } from "../../data/panel_custom";
import { navigate } from "../../common/navigate";
declare global {
@@ -16,7 +16,7 @@ export class HaPanelCustom extends UpdatingElement {
@property() public hass!: HomeAssistant;
@property() public narrow!: boolean;
@property() public route!: Route;
- @property() public panel!: Panel;
+ @property() public panel!: CustomPanelInfo;
private _setProperties?: (props: {}) => void | undefined;
// Since navigate fires events on `window`, we need to expose this as a function
@@ -66,8 +66,8 @@ export class HaPanelCustom extends UpdatingElement {
}
}
- private _createPanel(panel: Panel) {
- const config = panel.config!._panel_custom as CustomPanelConfig;
+ private _createPanel(panel: CustomPanelInfo) {
+ const config = panel.config!._panel_custom;
const tempA = document.createElement("a");
tempA.href = config.html_url || config.js_url || config.module_url || "";
diff --git a/src/types.ts b/src/types.ts
index 33665a4594..d5ffd71605 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -78,16 +78,16 @@ export interface Themes {
themes: { [key: string]: Theme };
}
-export interface Panel {
+export interface PanelInfo {
component_name: string;
- config: { [key: string]: any } | null;
+ config: T;
icon: string | null;
title: string | null;
url_path: string;
}
export interface Panels {
- [name: string]: Panel;
+ [name: string]: PanelInfo;
}
export interface Translation {
@@ -212,14 +212,6 @@ export type CameraEntity = HassEntityBase & {
};
};
-export interface PanelInfo {
- component_name: string;
- icon?: string;
- title?: string;
- url_path: string;
- config: T;
-}
-
export interface Route {
prefix: string;
path: string;
@@ -229,7 +221,7 @@ export interface PanelElement extends HTMLElement {
hass?: HomeAssistant;
narrow?: boolean;
route?: Route | null;
- panel?: Panel;
+ panel?: PanelInfo;
}
export interface LocalizeMixin {
|