mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-08 09:56:36 +00:00
Add badge to configuration sidebar to indicate pending updates (#12146)
This commit is contained in:
parent
ca22ec6340
commit
85d3011625
@ -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,35 +397,37 @@ class HaSidebar extends LitElement {
|
|||||||
icon?: string | null,
|
icon?: string | null,
|
||||||
iconPath?: string | null
|
iconPath?: string | null
|
||||||
) {
|
) {
|
||||||
return html`
|
return urlPath === "config"
|
||||||
<a
|
? this._renderConfiguration(title)
|
||||||
role="option"
|
: html`
|
||||||
href=${`/${urlPath}`}
|
<a
|
||||||
data-panel=${urlPath}
|
role="option"
|
||||||
tabindex="-1"
|
href=${`/${urlPath}`}
|
||||||
@mouseenter=${this._itemMouseEnter}
|
data-panel=${urlPath}
|
||||||
@mouseleave=${this._itemMouseLeave}
|
tabindex="-1"
|
||||||
>
|
@mouseenter=${this._itemMouseEnter}
|
||||||
<paper-icon-item>
|
@mouseleave=${this._itemMouseLeave}
|
||||||
${iconPath
|
>
|
||||||
? html`<ha-svg-icon
|
<paper-icon-item>
|
||||||
slot="item-icon"
|
${iconPath
|
||||||
.path=${iconPath}
|
? html`<ha-svg-icon
|
||||||
></ha-svg-icon>`
|
slot="item-icon"
|
||||||
: html`<ha-icon slot="item-icon" .icon=${icon}></ha-icon>`}
|
.path=${iconPath}
|
||||||
<span class="item-text">${title}</span>
|
></ha-svg-icon>`
|
||||||
</paper-icon-item>
|
: html`<ha-icon slot="item-icon" .icon=${icon}></ha-icon>`}
|
||||||
${this.editMode
|
<span class="item-text">${title}</span>
|
||||||
? html`<ha-icon-button
|
</paper-icon-item>
|
||||||
.label=${this.hass.localize("ui.sidebar.hide_panel")}
|
${this.editMode
|
||||||
.path=${mdiClose}
|
? html`<ha-icon-button
|
||||||
class="hide-panel"
|
.label=${this.hass.localize("ui.sidebar.hide_panel")}
|
||||||
.panel=${urlPath}
|
.path=${mdiClose}
|
||||||
@click=${this._hidePanel}
|
class="hide-panel"
|
||||||
></ha-icon-button>`
|
.panel=${urlPath}
|
||||||
: ""}
|
@click=${this._hidePanel}
|
||||||
</a>
|
></ha-icon-button>`
|
||||||
`;
|
: ""}
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _renderPanelsEdit(beforeSpacer: PanelInfo[]) {
|
private _renderPanelsEdit(beforeSpacer: PanelInfo[]) {
|
||||||
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user