diff --git a/src/components/ha-sidebar.ts b/src/components/ha-sidebar.ts index 70ee6ed471..b5e1ba55f5 100644 --- a/src/components/ha-sidebar.ts +++ b/src/components/ha-sidebar.ts @@ -37,6 +37,7 @@ import { LocalStorage } from "../common/decorators/local-storage"; import { fireEvent } from "../common/dom/fire_event"; import { toggleAttribute } from "../common/dom/toggle_attribute"; import { computeDomain } from "../common/entity/compute_domain"; +import { computeStateDomain } from "../common/entity/compute_state_domain"; import { stringCompare } from "../common/string/compare"; import { computeRTL } from "../common/util/compute_rtl"; import { ActionHandlerDetail } from "../data/lovelace"; @@ -44,6 +45,7 @@ import { PersistentNotification, subscribeNotifications, } from "../data/persistent_notification"; +import { updateCanInstall, UpdateEntity } from "../data/update"; import { actionHandler } from "../panels/lovelace/common/directives/action-handler-directive"; import { haStyleScrollbar } from "../resources/styles"; import type { HomeAssistant, PanelInfo, Route } from "../types"; @@ -68,7 +70,6 @@ const SORT_VALUE_URL_PATHS = { const PANEL_ICONS = { calendar: mdiCalendar, - config: mdiCog, "developer-tools": mdiHammer, energy: mdiLightningBolt, history: mdiChartBox, @@ -190,6 +191,8 @@ class HaSidebar extends LitElement { @state() private _notifications?: PersistentNotification[]; + @state() private _updatesCount = 0; + @state() private _renderEmptySortable = false; private _mouseLeaveTimeout?: number; @@ -235,6 +238,7 @@ class HaSidebar extends LitElement { changedProps.has("narrow") || changedProps.has("alwaysExpand") || changedProps.has("_externalConfig") || + changedProps.has("_updatesCount") || changedProps.has("_notifications") || changedProps.has("editMode") || changedProps.has("_renderEmptySortable") || @@ -290,6 +294,12 @@ class HaSidebar extends LitElement { toggleAttribute(this, "rtl", computeRTL(this.hass)); } + this._updatesCount = Object.values(this.hass.states).filter( + (entity) => + computeStateDomain(entity) === "update" && + updateCanInstall(entity as UpdateEntity) + ).length; + if (!SUPPORT_SCROLL_IF_NEEDED) { return; } @@ -387,35 +397,37 @@ class HaSidebar extends LitElement { icon?: string | null, iconPath?: string | null ) { - return html` - - - ${iconPath - ? html`` - : html``} - ${title} - - ${this.editMode - ? html`` - : ""} - - `; + return urlPath === "config" + ? this._renderConfiguration(title) + : html` + + + ${iconPath + ? html`` + : html``} + ${title} + + ${this.editMode + ? html`` + : ""} + + `; } private _renderPanelsEdit(beforeSpacer: PanelInfo[]) { @@ -477,6 +489,35 @@ class HaSidebar extends LitElement { return html`
`; } + private _renderConfiguration(title: string | null) { + return html` + + + ${!this.alwaysExpand && this._updatesCount > 0 + ? html` + + ${this._updatesCount} + + ` + : ""} + ${title} + ${this.alwaysExpand && this._updatesCount > 0 + ? html` + ${this._updatesCount} + ` + : ""} + + `; + } + private _renderNotifications() { let notificationCount = this._notifications ? this._notifications.length @@ -953,18 +994,21 @@ class HaSidebar extends LitElement { height: 1px; background-color: var(--divider-color); } - .notifications-container { + .notifications-container, + .configuration-container { display: flex; margin-left: env(safe-area-inset-left); } - :host([rtl]) .notifications-container { + :host([rtl]) .notifications-container, + :host([rtl]) .configuration-container { margin-left: initial; margin-right: env(safe-area-inset-right); } .notifications { cursor: pointer; } - .notifications .item-text { + .notifications .item-text, + .configuration .item-text { flex: 1; } .profile { @@ -988,7 +1032,8 @@ class HaSidebar extends LitElement { margin-right: 8px; } - .notification-badge { + .notification-badge, + .configuration-badge { min-width: 20px; box-sizing: border-box; border-radius: 50%; @@ -999,7 +1044,11 @@ class HaSidebar extends LitElement { padding: 0px 6px; color: var(--text-accent-color, var(--text-primary-color)); } - ha-svg-icon + .notification-badge { + .configuration-badge { + background-color: var(--primary-color); + } + ha-svg-icon + .notification-badge, + ha-svg-icon + .configuration-badge { position: absolute; bottom: 14px; left: 26px;