mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Add my support to supervisor (#8405)
* Add my support to supervisor * Remove localize * Comments * Update ha-panel-my.ts
This commit is contained in:
parent
e8daf88729
commit
0ec58007c9
@ -9,16 +9,21 @@ import {
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { navigate } from "../../../src/common/navigate";
|
||||
import { extractSearchParam } from "../../../src/common/url/search-params";
|
||||
import "../../../src/components/ha-circular-progress";
|
||||
import {
|
||||
fetchHassioAddonInfo,
|
||||
HassioAddonDetails,
|
||||
} from "../../../src/data/hassio/addon";
|
||||
import "../../../src/layouts/hass-loading-screen";
|
||||
import "../../../src/layouts/hass-error-screen";
|
||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||
import "../../../src/layouts/hass-tabs-subpage";
|
||||
import type { PageNavigation } from "../../../src/layouts/hass-tabs-subpage";
|
||||
@ -31,6 +36,7 @@ import "./config/hassio-addon-network";
|
||||
import "./hassio-addon-router";
|
||||
import "./info/hassio-addon-info";
|
||||
import "./log/hassio-addon-logs";
|
||||
import { extractApiErrorMessage } from "../../../src/data/hassio/common";
|
||||
|
||||
@customElement("hassio-addon-dashboard")
|
||||
class HassioAddonDashboard extends LitElement {
|
||||
@ -44,6 +50,8 @@ class HassioAddonDashboard extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public narrow!: boolean;
|
||||
|
||||
@internalProperty() _error?: string;
|
||||
|
||||
private _computeTail = memoizeOne((route: Route) => {
|
||||
const dividerPos = route.path.indexOf("/", 1);
|
||||
return dividerPos === -1
|
||||
@ -58,8 +66,14 @@ class HassioAddonDashboard extends LitElement {
|
||||
});
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (this._error) {
|
||||
return html`<hass-error-screen
|
||||
.error=${this._error}
|
||||
></hass-error-screen>`;
|
||||
}
|
||||
|
||||
if (!this.addon) {
|
||||
return html`<ha-circular-progress active></ha-circular-progress>`;
|
||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
||||
}
|
||||
|
||||
const addonTabs: PageNavigation[] = [
|
||||
@ -156,7 +170,12 @@ class HassioAddonDashboard extends LitElement {
|
||||
}
|
||||
|
||||
protected async firstUpdated(): Promise<void> {
|
||||
await this._routeDataChanged(this.route);
|
||||
if (this.route.path === "") {
|
||||
const addon = extractSearchParam("addon");
|
||||
if (addon) {
|
||||
navigate(this, `/hassio/addon/${addon}`, true);
|
||||
}
|
||||
}
|
||||
this.addEventListener("hass-api-called", (ev) => this._apiCalled(ev));
|
||||
}
|
||||
|
||||
@ -170,16 +189,26 @@ class HassioAddonDashboard extends LitElement {
|
||||
if (path === "uninstall") {
|
||||
history.back();
|
||||
} else {
|
||||
await this._routeDataChanged(this.route);
|
||||
await this._routeDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async _routeDataChanged(routeData: Route): Promise<void> {
|
||||
const addon = routeData.path.split("/")[1];
|
||||
protected updated(changedProperties) {
|
||||
if (changedProperties.has("route") && !this.addon) {
|
||||
this._routeDataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async _routeDataChanged(): Promise<void> {
|
||||
const addon = this.route.path.split("/")[1];
|
||||
if (!addon) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const addoninfo = await fetchHassioAddonInfo(this.hass, addon);
|
||||
this.addon = addoninfo;
|
||||
} catch {
|
||||
} catch (err) {
|
||||
this._error = `Error fetching addon info: ${extractApiErrorMessage(err)}`;
|
||||
this.addon = undefined;
|
||||
}
|
||||
}
|
||||
|
125
hassio/src/hassio-my-redirect.ts
Normal file
125
hassio/src/hassio-my-redirect.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { sanitizeUrl } from "@braintree/sanitize-url";
|
||||
import {
|
||||
createSearchParam,
|
||||
extractSearchParamsObject,
|
||||
} from "../../src/common/url/search-params";
|
||||
import "../../src/layouts/hass-error-screen";
|
||||
import {
|
||||
ParamType,
|
||||
Redirect,
|
||||
Redirects,
|
||||
} from "../../src/panels/my/ha-panel-my";
|
||||
import { navigate } from "../../src/common/navigate";
|
||||
import { HomeAssistant, Route } from "../../src/types";
|
||||
|
||||
const REDIRECTS: Redirects = {
|
||||
supervisor_system: {
|
||||
redirect: "/hassio/system",
|
||||
},
|
||||
supervisor_snapshots: {
|
||||
redirect: "/hassio/snapshots",
|
||||
},
|
||||
supervisor_store: {
|
||||
redirect: "/hassio/store",
|
||||
},
|
||||
supervisor: {
|
||||
redirect: "/hassio/dashboard",
|
||||
},
|
||||
supervisor_addon: {
|
||||
redirect: "/hassio/addon",
|
||||
params: {
|
||||
addon: "string",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@customElement("hassio-my-redirect")
|
||||
class HassioMyRedirect extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public route!: Route;
|
||||
|
||||
@internalProperty() public _error?: TemplateResult | string;
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
const path = this.route.path.substr(1);
|
||||
const redirect = REDIRECTS[path];
|
||||
|
||||
if (!redirect) {
|
||||
this._error = html`This redirect is not supported by your Home Assistant
|
||||
instance. Check the
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
href="https://my.home-assistant.io/faq.html#supported-pages"
|
||||
>My Home Assistant FAQ</a
|
||||
>
|
||||
for the supported redirects and the version they where introduced.`;
|
||||
return;
|
||||
}
|
||||
|
||||
let url: string;
|
||||
try {
|
||||
url = this._createRedirectUrl(redirect);
|
||||
} catch (err) {
|
||||
this._error = "An unknown error occured";
|
||||
return;
|
||||
}
|
||||
|
||||
navigate(this, url, true);
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (this._error) {
|
||||
return html`<hass-error-screen
|
||||
.error=${this._error}
|
||||
></hass-error-screen>`;
|
||||
}
|
||||
return html``;
|
||||
}
|
||||
|
||||
private _createRedirectUrl(redirect: Redirect): string {
|
||||
const params = this._createRedirectParams(redirect);
|
||||
return `${redirect.redirect}${params}`;
|
||||
}
|
||||
|
||||
private _createRedirectParams(redirect: Redirect): string {
|
||||
const params = extractSearchParamsObject();
|
||||
if (!redirect.params && !Object.keys(params).length) {
|
||||
return "";
|
||||
}
|
||||
const resultParams = {};
|
||||
Object.entries(redirect.params || {}).forEach(([key, type]) => {
|
||||
if (!params[key] || !this._checkParamType(type, params[key])) {
|
||||
throw Error();
|
||||
}
|
||||
resultParams[key] = params[key];
|
||||
});
|
||||
return `?${createSearchParam(resultParams)}`;
|
||||
}
|
||||
|
||||
private _checkParamType(type: ParamType, value: string) {
|
||||
if (type === "string") {
|
||||
return true;
|
||||
}
|
||||
if (type === "url") {
|
||||
return value && value === sanitizeUrl(value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hassio-my-redirect": HassioMyRedirect;
|
||||
}
|
||||
}
|
@ -41,6 +41,10 @@ class HassioRouter extends HassRouterPage {
|
||||
tag: "hassio-ingress-view",
|
||||
load: () => import("./ingress-view/hassio-ingress-view"),
|
||||
},
|
||||
_my_redirect: {
|
||||
tag: "hassio-my-redirect",
|
||||
load: () => import("./hassio-my-redirect"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -380,22 +380,24 @@ export class QuickBar extends LitElement {
|
||||
QuickBarNavigationItem,
|
||||
"action"
|
||||
>[] {
|
||||
return Object.keys(this.hass.panels).map((panelKey) => {
|
||||
const panel = this.hass.panels[panelKey];
|
||||
const translationKey = getPanelNameTranslationKey(panel);
|
||||
return Object.keys(this.hass.panels)
|
||||
.filter((panelKey) => panelKey !== "_my_redirect")
|
||||
.map((panelKey) => {
|
||||
const panel = this.hass.panels[panelKey];
|
||||
const translationKey = getPanelNameTranslationKey(panel);
|
||||
|
||||
const text = this.hass.localize(
|
||||
"ui.dialogs.quick-bar.commands.navigation.navigate_to",
|
||||
"panel",
|
||||
this.hass.localize(translationKey) || panel.title || panel.url_path
|
||||
);
|
||||
const text = this.hass.localize(
|
||||
"ui.dialogs.quick-bar.commands.navigation.navigate_to",
|
||||
"panel",
|
||||
this.hass.localize(translationKey) || panel.title || panel.url_path
|
||||
);
|
||||
|
||||
return {
|
||||
text,
|
||||
icon: getPanelIcon(panel) || DEFAULT_NAVIGATION_ICON,
|
||||
path: `/${panel.url_path}`,
|
||||
};
|
||||
});
|
||||
return {
|
||||
text,
|
||||
icon: getPanelIcon(panel) || DEFAULT_NAVIGATION_ICON,
|
||||
path: `/${panel.url_path}`,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private _generateNavigationConfigSectionCommands(): Partial<
|
||||
|
@ -13,8 +13,10 @@ import {
|
||||
extractSearchParamsObject,
|
||||
} from "../../common/url/search-params";
|
||||
import "../../layouts/hass-error-screen";
|
||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { domainToName } from "../../data/integration";
|
||||
|
||||
const REDIRECTS = {
|
||||
const REDIRECTS: Redirects = {
|
||||
info: {
|
||||
redirect: "/config/info",
|
||||
},
|
||||
@ -38,10 +40,12 @@ const REDIRECTS = {
|
||||
},
|
||||
};
|
||||
|
||||
type ParamType = "url" | "string";
|
||||
export type ParamType = "url" | "string";
|
||||
|
||||
interface Redirect {
|
||||
export type Redirects = { [key: string]: Redirect };
|
||||
export interface Redirect {
|
||||
redirect: string;
|
||||
component?: string;
|
||||
params?: {
|
||||
[key: string]: ParamType;
|
||||
};
|
||||
@ -58,7 +62,25 @@ class HaPanelMy extends LitElement {
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
const path = this.route.path.substr(1);
|
||||
const redirect: Redirect | undefined = REDIRECTS[path];
|
||||
|
||||
if (path.startsWith("supervisor")) {
|
||||
if (!isComponentLoaded(this.hass, "hassio")) {
|
||||
this._error = this.hass.localize(
|
||||
"ui.panel.my.component_not_loaded",
|
||||
"integration",
|
||||
domainToName(this.hass.localize, "hassio")
|
||||
);
|
||||
return;
|
||||
}
|
||||
navigate(
|
||||
this,
|
||||
`/hassio/_my_redirect/${path}${window.location.search}`,
|
||||
true
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const redirect = REDIRECTS[path];
|
||||
|
||||
if (!redirect) {
|
||||
this._error = this.hass.localize(
|
||||
@ -74,6 +96,18 @@ class HaPanelMy extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
redirect.component &&
|
||||
!isComponentLoaded(this.hass, redirect.component)
|
||||
) {
|
||||
this._error = this.hass.localize(
|
||||
"ui.panel.my.component_not_loaded",
|
||||
"integration",
|
||||
domainToName(this.hass.localize, redirect.component)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let url: string;
|
||||
try {
|
||||
url = this._createRedirectUrl(redirect);
|
||||
|
@ -806,6 +806,7 @@
|
||||
"panel": {
|
||||
"my": {
|
||||
"not_supported": "This redirect is not supported by your Home Assistant instance. Check the {link} for the supported redirects and the version they where introduced.",
|
||||
"component_not_loaded": "This redirect is not supported by your Home Assistant instance. You need the integration {integration} to use this redirect.",
|
||||
"faq_link": "My Home Assistant FAQ",
|
||||
"error": "An unknown error occured"
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user