mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-14 13:31:10 +00:00
Change logic for default panel
This commit is contained in:
@@ -14,12 +14,17 @@ declare global {
|
|||||||
interface FrontendUserData {
|
interface FrontendUserData {
|
||||||
core: CoreFrontendUserData;
|
core: CoreFrontendUserData;
|
||||||
sidebar: SidebarFrontendUserData;
|
sidebar: SidebarFrontendUserData;
|
||||||
default_panel: string;
|
default_panel?: string;
|
||||||
|
}
|
||||||
|
interface FrontendSystemData {
|
||||||
|
default_panel?: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ValidUserDataKey = keyof FrontendUserData;
|
export type ValidUserDataKey = keyof FrontendUserData;
|
||||||
|
|
||||||
|
export type ValidSystemDataKey = keyof FrontendSystemData;
|
||||||
|
|
||||||
export const fetchFrontendUserData = async <
|
export const fetchFrontendUserData = async <
|
||||||
UserDataKey extends ValidUserDataKey,
|
UserDataKey extends ValidUserDataKey,
|
||||||
>(
|
>(
|
||||||
@@ -60,3 +65,46 @@ export const subscribeFrontendUserData = <UserDataKey extends ValidUserDataKey>(
|
|||||||
key: userDataKey,
|
key: userDataKey,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const fetchFrontendSystemData = async <
|
||||||
|
SystemDataKey extends ValidSystemDataKey,
|
||||||
|
>(
|
||||||
|
conn: Connection,
|
||||||
|
key: SystemDataKey
|
||||||
|
): Promise<FrontendSystemData[SystemDataKey] | null> => {
|
||||||
|
const result = await conn.sendMessagePromise<{
|
||||||
|
value: FrontendSystemData[SystemDataKey] | null;
|
||||||
|
}>({
|
||||||
|
type: "frontend/get_system_data",
|
||||||
|
key,
|
||||||
|
});
|
||||||
|
return result.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const saveFrontendSystemData = async <
|
||||||
|
SystemDataKey extends ValidSystemDataKey,
|
||||||
|
>(
|
||||||
|
conn: Connection,
|
||||||
|
key: SystemDataKey,
|
||||||
|
value: FrontendSystemData[SystemDataKey]
|
||||||
|
): Promise<void> =>
|
||||||
|
conn.sendMessagePromise<undefined>({
|
||||||
|
type: "frontend/set_system_data",
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const subscribeFrontendSystemData = <
|
||||||
|
SystemDataKey extends ValidSystemDataKey,
|
||||||
|
>(
|
||||||
|
conn: Connection,
|
||||||
|
systemDataKey: SystemDataKey,
|
||||||
|
onChange: (data: { value: FrontendSystemData[SystemDataKey] | null }) => void
|
||||||
|
) =>
|
||||||
|
conn.subscribeMessage<{ value: FrontendSystemData[SystemDataKey] | null }>(
|
||||||
|
onChange,
|
||||||
|
{
|
||||||
|
type: "frontend/subscribe_system_data",
|
||||||
|
key: systemDataKey,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import type { HomeAssistant, PanelInfo } from "../types";
|
|||||||
/** Panel to show when no panel is picked. */
|
/** Panel to show when no panel is picked. */
|
||||||
export const DEFAULT_PANEL = "lovelace";
|
export const DEFAULT_PANEL = "lovelace";
|
||||||
|
|
||||||
export const getStorageDefaultPanelUrlPath = (): string => {
|
export const getStorageDefaultPanelUrlPath = (): string | undefined => {
|
||||||
const defaultPanel = window.localStorage.getItem("defaultPanel");
|
const defaultPanel = window.localStorage.getItem("defaultPanel");
|
||||||
|
|
||||||
return defaultPanel ? JSON.parse(defaultPanel) : DEFAULT_PANEL;
|
return defaultPanel ? JSON.parse(defaultPanel) : undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setDefaultPanel = (
|
export const setDefaultPanel = (
|
||||||
@@ -17,10 +17,15 @@ export const setDefaultPanel = (
|
|||||||
fireEvent(element, "hass-default-panel", { defaultPanel: urlPath });
|
fireEvent(element, "hass-default-panel", { defaultPanel: urlPath });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDefaultPanel = (hass: HomeAssistant): PanelInfo =>
|
export const getDefaultPanel = (hass: HomeAssistant): PanelInfo => {
|
||||||
hass.panels[hass.defaultPanel]
|
if (!hass.defaultPanel) {
|
||||||
|
return hass.panels[DEFAULT_PANEL];
|
||||||
|
}
|
||||||
|
|
||||||
|
return hass.panels[hass.defaultPanel]
|
||||||
? hass.panels[hass.defaultPanel]
|
? hass.panels[hass.defaultPanel]
|
||||||
: hass.panels[DEFAULT_PANEL];
|
: hass.panels[DEFAULT_PANEL];
|
||||||
|
};
|
||||||
|
|
||||||
export const getPanelNameTranslationKey = (panel: PanelInfo) => {
|
export const getPanelNameTranslationKey = (panel: PanelInfo) => {
|
||||||
if (panel.url_path === "lovelace") {
|
if (panel.url_path === "lovelace") {
|
||||||
|
|||||||
@@ -54,9 +54,10 @@ export class HomeAssistantAppEl extends QuickBarMixin(HassElement) {
|
|||||||
const path = curPath();
|
const path = curPath();
|
||||||
|
|
||||||
if (["", "/"].includes(path)) {
|
if (["", "/"].includes(path)) {
|
||||||
navigate(`/${getStorageDefaultPanelUrlPath()}${location.search}`, {
|
const defaultPanel = getStorageDefaultPanelUrlPath();
|
||||||
replace: true,
|
if (defaultPanel) {
|
||||||
});
|
navigate(`/${defaultPanel}${location.search}`, { replace: true });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._route = {
|
this._route = {
|
||||||
prefix: "",
|
prefix: "",
|
||||||
|
|||||||
@@ -188,6 +188,10 @@ class PartialPanelResolver extends HassRouterPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _updateRoutes(oldPanels?: HomeAssistant["panels"]) {
|
private async _updateRoutes(oldPanels?: HomeAssistant["panels"]) {
|
||||||
|
if (this.hass.defaultPanel) {
|
||||||
|
await this.hass.loadDefaultPanel();
|
||||||
|
}
|
||||||
|
|
||||||
this.routerOptions = this._getRoutes(this.hass.panels);
|
this.routerOptions = this._getRoutes(this.hass.panels);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -8,13 +8,18 @@ import {
|
|||||||
subscribeServices,
|
subscribeServices,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { computeStateName } from "../common/entity/compute_state_name";
|
||||||
import { promiseTimeout } from "../common/util/promise-timeout";
|
import { promiseTimeout } from "../common/util/promise-timeout";
|
||||||
import { subscribeAreaRegistry } from "../data/area_registry";
|
import { subscribeAreaRegistry } from "../data/area_registry";
|
||||||
import { broadcastConnectionStatus } from "../data/connection-status";
|
import { broadcastConnectionStatus } from "../data/connection-status";
|
||||||
import { subscribeDeviceRegistry } from "../data/device_registry";
|
import { subscribeDeviceRegistry } from "../data/device_registry";
|
||||||
import { subscribeFrontendUserData } from "../data/frontend";
|
import {
|
||||||
|
fetchFrontendSystemData,
|
||||||
|
fetchFrontendUserData,
|
||||||
|
subscribeFrontendSystemData,
|
||||||
|
subscribeFrontendUserData,
|
||||||
|
} from "../data/frontend";
|
||||||
import { forwardHaptic } from "../data/haptics";
|
import { forwardHaptic } from "../data/haptics";
|
||||||
import { DEFAULT_PANEL } from "../data/panel";
|
|
||||||
import { serviceCallWillDisconnect } from "../data/service";
|
import { serviceCallWillDisconnect } from "../data/service";
|
||||||
import {
|
import {
|
||||||
DateFormat,
|
DateFormat,
|
||||||
@@ -33,7 +38,7 @@ import { fetchWithAuth } from "../util/fetch-with-auth";
|
|||||||
import { getState, storeState } from "../util/ha-pref-storage";
|
import { getState, storeState } from "../util/ha-pref-storage";
|
||||||
import hassCallApi, { hassCallApiRaw } from "../util/hass-call-api";
|
import hassCallApi, { hassCallApiRaw } from "../util/hass-call-api";
|
||||||
import type { HassBaseEl } from "./hass-base-mixin";
|
import type { HassBaseEl } from "./hass-base-mixin";
|
||||||
import { computeStateName } from "../common/entity/compute_state_name";
|
import { DEFAULT_PANEL } from "../data/panel";
|
||||||
|
|
||||||
export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
||||||
superClass: T
|
superClass: T
|
||||||
@@ -73,7 +78,6 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
|||||||
},
|
},
|
||||||
resources: null as any,
|
resources: null as any,
|
||||||
localize: () => "",
|
localize: () => "",
|
||||||
|
|
||||||
translationMetadata,
|
translationMetadata,
|
||||||
dockedSidebar: "docked",
|
dockedSidebar: "docked",
|
||||||
vibrate: true,
|
vibrate: true,
|
||||||
@@ -204,14 +208,28 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
|||||||
loadFragmentTranslation: (fragment) =>
|
loadFragmentTranslation: (fragment) =>
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this._loadFragmentTranslations(this.hass?.language, fragment),
|
this._loadFragmentTranslations(this.hass?.language, fragment),
|
||||||
|
loadDefaultPanel: async () => {
|
||||||
|
const [user, system] = await Promise.all([
|
||||||
|
fetchFrontendUserData(conn, "default_panel"),
|
||||||
|
fetchFrontendSystemData(conn, "default_panel"),
|
||||||
|
]);
|
||||||
|
const defaultPanel = user || system;
|
||||||
|
this._updateHass({
|
||||||
|
userDefaultPanel: user,
|
||||||
|
systemDefaultPanel: system,
|
||||||
|
defaultPanel,
|
||||||
|
});
|
||||||
|
storeState(this.hass!);
|
||||||
|
return defaultPanel;
|
||||||
|
},
|
||||||
formatEntityState: (stateObj, state) =>
|
formatEntityState: (stateObj, state) =>
|
||||||
(state != null ? state : stateObj.state) ?? "",
|
(state != null ? state : stateObj.state) ?? "",
|
||||||
formatEntityAttributeName: (_stateObj, attribute) => attribute,
|
formatEntityAttributeName: (_stateObj, attribute) => attribute,
|
||||||
formatEntityAttributeValue: (stateObj, attribute, value) =>
|
formatEntityAttributeValue: (stateObj, attribute, value) =>
|
||||||
value != null ? value : (stateObj.attributes[attribute] ?? ""),
|
value != null ? value : (stateObj.attributes[attribute] ?? ""),
|
||||||
|
formatEntityName: (stateObj) => computeStateName(stateObj),
|
||||||
...getState(),
|
...getState(),
|
||||||
...this._pendingHass,
|
...this._pendingHass,
|
||||||
formatEntityName: (stateObj) => computeStateName(stateObj),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.hassConnected();
|
this.hassConnected();
|
||||||
@@ -289,11 +307,34 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
|
|||||||
conn,
|
conn,
|
||||||
"default_panel",
|
"default_panel",
|
||||||
({ value: defaultPanel }) => {
|
({ value: defaultPanel }) => {
|
||||||
this._updateHass({ defaultPanel: defaultPanel || DEFAULT_PANEL });
|
this._updateHass({
|
||||||
|
userDefaultPanel: defaultPanel,
|
||||||
|
});
|
||||||
|
// Update default panel taking into account user and system default panel
|
||||||
|
this._updateHass({
|
||||||
|
defaultPanel:
|
||||||
|
this.hass!.userDefaultPanel || this.hass!.systemDefaultPanel,
|
||||||
|
});
|
||||||
|
// Store updated default panel in local storage
|
||||||
|
storeState(this.hass!);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
subscribeFrontendSystemData(
|
||||||
|
conn,
|
||||||
|
"default_panel",
|
||||||
|
({ value: defaultPanel }) => {
|
||||||
|
this._updateHass({
|
||||||
|
systemDefaultPanel: defaultPanel,
|
||||||
|
});
|
||||||
|
// Update default panel taking into account user and system default panel
|
||||||
|
this._updateHass({
|
||||||
|
defaultPanel:
|
||||||
|
this.hass!.userDefaultPanel || this.hass!.systemDefaultPanel,
|
||||||
|
});
|
||||||
|
// Store updated default panel in local storage
|
||||||
storeState(this.hass!);
|
storeState(this.hass!);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
clearInterval(this.__backendPingInterval);
|
clearInterval(this.__backendPingInterval);
|
||||||
this.__backendPingInterval = setInterval(() => {
|
this.__backendPingInterval = setInterval(() => {
|
||||||
if (this.hass?.connected) {
|
if (this.hass?.connected) {
|
||||||
|
|||||||
@@ -248,7 +248,9 @@ export interface HomeAssistant {
|
|||||||
vibrate: boolean;
|
vibrate: boolean;
|
||||||
debugConnection: boolean;
|
debugConnection: boolean;
|
||||||
dockedSidebar: "docked" | "always_hidden" | "auto";
|
dockedSidebar: "docked" | "always_hidden" | "auto";
|
||||||
defaultPanel: string;
|
defaultPanel?: string | null;
|
||||||
|
userDefaultPanel?: string | null;
|
||||||
|
systemDefaultPanel?: string | null;
|
||||||
moreInfoEntityId: string | null;
|
moreInfoEntityId: string | null;
|
||||||
user?: CurrentUser;
|
user?: CurrentUser;
|
||||||
userData?: CoreFrontendUserData | null;
|
userData?: CoreFrontendUserData | null;
|
||||||
@@ -283,6 +285,7 @@ export interface HomeAssistant {
|
|||||||
configFlow?: Parameters<typeof getHassTranslations>[4]
|
configFlow?: Parameters<typeof getHassTranslations>[4]
|
||||||
): Promise<LocalizeFunc>;
|
): Promise<LocalizeFunc>;
|
||||||
loadFragmentTranslation(fragment: string): Promise<LocalizeFunc | undefined>;
|
loadFragmentTranslation(fragment: string): Promise<LocalizeFunc | undefined>;
|
||||||
|
loadDefaultPanel(): Promise<string | null | undefined>;
|
||||||
formatEntityState(stateObj: HassEntity, state?: string): string;
|
formatEntityState(stateObj: HassEntity, state?: string): string;
|
||||||
formatEntityAttributeValue(
|
formatEntityAttributeValue(
|
||||||
stateObj: HassEntity,
|
stateObj: HassEntity,
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ const STORED_STATE = [
|
|||||||
"suspendWhenHidden",
|
"suspendWhenHidden",
|
||||||
"enableShortcuts",
|
"enableShortcuts",
|
||||||
"defaultPanel",
|
"defaultPanel",
|
||||||
];
|
] as const;
|
||||||
|
|
||||||
|
type StoredHomeAssistant = Pick<HomeAssistant, (typeof STORED_STATE)[number]>;
|
||||||
|
|
||||||
export function storeState(hass: HomeAssistant) {
|
export function storeState(hass: HomeAssistant) {
|
||||||
try {
|
try {
|
||||||
@@ -31,8 +33,8 @@ export function storeState(hass: HomeAssistant) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getState() {
|
export function getState(): Partial<StoredHomeAssistant> {
|
||||||
const state = {};
|
const state = {} as Partial<StoredHomeAssistant>;
|
||||||
|
|
||||||
STORED_STATE.forEach((key) => {
|
STORED_STATE.forEach((key) => {
|
||||||
const storageItem = window.localStorage.getItem(key);
|
const storageItem = window.localStorage.getItem(key);
|
||||||
|
|||||||
Reference in New Issue
Block a user