Add default dashboard selection to profile page (#5360)

* Add default dashboard selection to profile page

* Comments

* Console.bye
This commit is contained in:
Bram Kragten 2020-03-30 16:08:36 +02:00 committed by GitHub
parent 263138a388
commit 8a6bd04543
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 146 additions and 28 deletions

View File

@ -32,7 +32,7 @@ import { classMap } from "lit-html/directives/class-map";
import { PaperIconItemElement } from "@polymer/paper-item/paper-icon-item";
import { computeRTL } from "../common/util/compute_rtl";
import { compare } from "../common/string/compare";
import { getDefaultPanelUrlPath, getDefaultPanel } from "../data/panel";
import { getDefaultPanel } from "../data/panel";
const SHOW_AFTER_SPACER = ["config", "developer-tools", "hassio"];
@ -87,10 +87,8 @@ const computePanels = (hass: HomeAssistant): [PanelInfo[], PanelInfo[]] => {
const beforeSpacer: PanelInfo[] = [];
const afterSpacer: PanelInfo[] = [];
const defaultPage = getDefaultPanelUrlPath();
Object.values(panels).forEach((panel) => {
if (!panel.title || panel.url_path === defaultPage) {
if (!panel.title || panel.url_path === hass.defaultPanel) {
return;
}
(SHOW_AFTER_SPACER.includes(panel.url_path)
@ -143,7 +141,7 @@ class HaSidebar extends LitElement {
}
}
const defaultPanel = getDefaultPanel(hass.panels);
const defaultPanel = getDefaultPanel(hass);
return html`
<div class="menu">
@ -297,7 +295,8 @@ class HaSidebar extends LitElement {
hass.panelUrl !== oldHass.panelUrl ||
hass.user !== oldHass.user ||
hass.localize !== oldHass.localize ||
hass.states !== oldHass.states
hass.states !== oldHass.states ||
hass.defaultPanel !== oldHass.defaultPanel
);
}

View File

@ -1,13 +1,20 @@
import { HomeAssistant, PanelInfo } from "../types";
import { fireEvent } from "../common/dom/fire_event";
/** Panel to show when no panel is picked. */
const DEFAULT_PANEL = "lovelace";
export const DEFAULT_PANEL = "lovelace";
export const getDefaultPanelUrlPath = () =>
localStorage.defaultPage || DEFAULT_PANEL;
export const getStorageDefaultPanelUrlPath = () =>
localStorage.defaultPanel
? JSON.parse(localStorage.defaultPanel)
: DEFAULT_PANEL;
export const getDefaultPanel = (panels: HomeAssistant["panels"]) =>
panels[localStorage.defaultPage] || panels[DEFAULT_PANEL];
export const setDefaultPanel = (element: HTMLElement, urlPath: string) => {
fireEvent(element, "hass-default-panel", { defaultPanel: urlPath });
};
export const getDefaultPanel = (hass: HomeAssistant) =>
hass.panels[hass.defaultPanel];
export const getPanelTitle = (hass: HomeAssistant): string | undefined => {
if (!hass.panels) {

View File

@ -11,6 +11,7 @@ import { HomeAssistant } from "../types";
import { HassEntities } from "home-assistant-js-websocket";
import { getLocalLanguage } from "../util/hass-translation";
import { translationMetadata } from "../resources/translations-metadata";
import { DEFAULT_PANEL } from "../data/panel";
const ensureArray = <T>(val: T | T[]): T[] =>
Array.isArray(val) ? val : [val];
@ -172,6 +173,7 @@ export const provideHass = (
name: "Demo User",
},
panelUrl: "lovelace",
defaultPanel: DEFAULT_PANEL,
language: localLanguage,
selectedLanguage: localLanguage,

View File

@ -10,7 +10,7 @@ import { registerServiceWorker } from "../util/register-service-worker";
import { Route, HomeAssistant } from "../types";
import { navigate } from "../common/navigate";
import { HassElement } from "../state/hass-element";
import { getDefaultPanelUrlPath } from "../data/panel";
import { getStorageDefaultPanelUrlPath } from "../data/panel";
export class HomeAssistantAppEl extends HassElement {
@property() private _route?: Route;
@ -86,7 +86,7 @@ export class HomeAssistantAppEl extends HassElement {
this._route === undefined &&
(route.path === "" || route.path === "/")
) {
navigate(window, `/${getDefaultPanelUrlPath()}`, true);
navigate(window, getStorageDefaultPanelUrlPath(), true);
return;
}

View File

@ -19,6 +19,7 @@ import { PolymerChangedEvent } from "../../../../polymer-types";
import { HaSwitch } from "../../../../components/ha-switch";
import { createCloseHeading } from "../../../../components/ha-dialog";
import { haStyleDialog } from "../../../../resources/styles";
import { setDefaultPanel, DEFAULT_PANEL } from "../../../../data/panel";
@customElement("dialog-lovelace-dashboard-detail")
export class DialogLovelaceDashboardDetail extends LitElement {
@ -57,6 +58,7 @@ export class DialogLovelaceDashboardDetail extends LitElement {
if (!this._params) {
return html``;
}
const defaultPanelUrlPath = this.hass.defaultPanel;
const urlInvalid =
this._params.urlPath !== "lovelace" &&
!/^[a-zA-Z0-9_-]+-[a-zA-Z0-9_-]+$/.test(this._urlPath);
@ -169,12 +171,9 @@ export class DialogLovelaceDashboardDetail extends LitElement {
slot="secondaryAction"
@click=${this._toggleDefault}
.disabled=${this._params.urlPath === "lovelace" &&
(!localStorage.defaultPage ||
localStorage.defaultPage === "lovelace")}
defaultPanelUrlPath === "lovelace"}
>
${this._params.urlPath === localStorage.defaultPage ||
(this._params.urlPath === "lovelace" &&
!localStorage.defaultPage)
${this._params.urlPath === defaultPanelUrlPath
? this.hass.localize(
"ui.panel.config.lovelace.dashboards.detail.remove_default"
)
@ -244,12 +243,10 @@ export class DialogLovelaceDashboardDetail extends LitElement {
if (!urlPath) {
return;
}
if (urlPath === localStorage.defaultPage) {
delete localStorage.defaultPage;
} else {
localStorage.defaultPage = urlPath;
}
location.reload();
setDefaultPanel(
this,
urlPath === this.hass.defaultPanel ? DEFAULT_PANEL : urlPath
);
}
private async _updateDashboard() {

View File

@ -184,8 +184,8 @@ export class HaConfigLovelaceDashboards extends LitElement {
private _getItems = memoize((dashboards: LovelaceDashboard[]) => {
const defaultMode = (this.hass.panels?.lovelace
?.config as LovelacePanelConfig).mode;
const isDefault =
!localStorage.defaultPage || localStorage.defaultPage === "lovelace";
const defaultUrlPath = this.hass.defaultPanel;
const isDefault = defaultUrlPath === "lovelace";
return [
{
icon: "hass:view-dashboard",
@ -201,7 +201,7 @@ export class HaConfigLovelaceDashboards extends LitElement {
return {
filename: "",
...dashboard,
default: localStorage.defaultPage === dashboard.url_path,
default: defaultUrlPath === dashboard.url_path,
};
}),
];

View File

@ -20,6 +20,7 @@ import "./ha-long-lived-access-tokens-card";
import "./ha-advanced-mode-row";
import "./ha-pick-language-row";
import "./ha-pick-theme-row";
import "./ha-pick-dashboard-row";
import "./ha-push-notifications-row";
import "./ha-force-narrow-row";
import "./ha-set-vibrate-row";
@ -98,6 +99,10 @@ class HaPanelProfile extends LitElement {
.narrow=${this.narrow}
.hass=${this.hass}
></ha-pick-theme-row>
<ha-pick-dashboard-row
.narrow=${this.narrow}
.hass=${this.hass}
></ha-pick-dashboard-row>
${this.hass.dockedSidebar !== "auto" || !this.narrow
? html`
<ha-force-narrow-row

View File

@ -0,0 +1,86 @@
import {
LitElement,
TemplateResult,
html,
property,
customElement,
PropertyValues,
} from "lit-element";
import "./ha-settings-row";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-listbox/paper-listbox";
import "../../components/ha-paper-dropdown-menu";
import { HomeAssistant } from "../../types";
import { LovelaceDashboard, fetchDashboards } from "../../data/lovelace";
import { setDefaultPanel } from "../../data/panel";
@customElement("ha-pick-dashboard-row")
class HaPickDashboardRow extends LitElement {
@property() public hass!: HomeAssistant;
@property() public narrow!: boolean;
@property() private _dashboards: LovelaceDashboard[] = [];
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
this._getDashboards();
}
protected render(): TemplateResult {
return html`
<ha-settings-row .narrow=${this.narrow}>
<span slot="heading">
${this.hass.localize("ui.panel.profile.dashboard.header")}
</span>
<span slot="description">
${this.hass.localize("ui.panel.profile.dashboard.description")}
</span>
<ha-paper-dropdown-menu
.label=${this.hass.localize(
"ui.panel.profile.dashboard.dropdown_label"
)}
dynamic-align
.disabled=${!this._dashboards.length}
>
<paper-listbox
slot="dropdown-content"
.selected=${this.hass.defaultPanel}
@iron-select=${this._dashboardChanged}
attr-for-selected="url-path"
>
<paper-item url-path="lovelace">default</paper-item>
${this._dashboards.map((dashboard) => {
if (!this.hass.user!.is_admin && dashboard.require_admin) {
return "";
}
return html`
<paper-item url-path=${dashboard.url_path}
>${dashboard.title}</paper-item
>
`;
})}
</paper-listbox>
</ha-paper-dropdown-menu>
</ha-settings-row>
`;
}
private async _getDashboards() {
this._dashboards = await fetchDashboards(this.hass);
}
private _dashboardChanged(ev: CustomEvent) {
const urlPath = ev.detail.item.getAttribute("url-path");
if (!urlPath || urlPath === this.hass.defaultPanel) {
return;
}
setDefaultPanel(this, urlPath);
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-pick-dashboard-row": HaPickDashboardRow;
}
}

View File

@ -21,6 +21,7 @@ import { Constructor, ServiceCallResponse } from "../types";
import { HassBaseEl } from "./hass-base-mixin";
import { broadcastConnectionStatus } from "../data/connection-status";
import { subscribeFrontendUserData } from "../data/frontend";
import { DEFAULT_PANEL } from "../data/panel";
export const connectionMixin = <T extends Constructor<HassBaseEl>>(
superClass: T
@ -38,7 +39,7 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
services: null as any,
user: null as any,
panelUrl: (this as any)._panelUrl,
defaultPanel: DEFAULT_PANEL,
language: getLocalLanguage(),
selectedLanguage: null,
resources: null as any,

View File

@ -7,15 +7,25 @@ interface DockSidebarParams {
dock: HomeAssistant["dockedSidebar"];
}
interface DefaultPanelParams {
defaultPanel: HomeAssistant["defaultPanel"];
}
declare global {
// for fire event
interface HASSDomEvents {
"hass-dock-sidebar": DockSidebarParams;
}
interface HASSDomEvents {
"hass-default-panel": DefaultPanelParams;
}
// for add event listener
interface HTMLElementEventMap {
"hass-dock-sidebar": HASSDomEvent<DockSidebarParams>;
}
interface HTMLElementEventMap {
"hass-default-panel": HASSDomEvent<DefaultPanelParams>;
}
}
export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
@ -26,5 +36,9 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
this._updateHass({ dockedSidebar: ev.detail.dock });
storeState(this.hass!);
});
this.addEventListener("hass-default-panel", (ev) => {
this._updateHass({ defaultPanel: ev.detail.defaultPanel });
storeState(this.hass!);
});
}
};

View File

@ -2209,6 +2209,11 @@
"link_promo": "Learn about themes",
"dropdown_label": "Theme"
},
"dashboard": {
"header": "Dashboard",
"description": "Pick a default dashboard for this device.",
"dropdown_label": "Dashboard"
},
"change_password": {
"header": "Change Password",
"current_password": "Current Password",

View File

@ -154,6 +154,7 @@ export interface HomeAssistant {
vibrate: boolean;
dockedSidebar: "docked" | "always_hidden" | "auto";
defaultPanel: string;
moreInfoEntityId: string | null;
user?: CurrentUser;
userData?: CoreFrontendUserData | null;

View File

@ -5,6 +5,7 @@ const STORED_STATE = [
"selectedTheme",
"selectedLanguage",
"vibrate",
"defaultPanel",
];
const STORAGE = window.localStorage || {};