Add badge to configuration sidebar to indicate pending updates (#12146)

This commit is contained in:
Joakim Sørensen 2022-03-29 14:35:05 +02:00 committed by GitHub
parent ca22ec6340
commit 85d3011625
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

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