Merge pull request #12582 from home-assistant/dev

This commit is contained in:
Bram Kragten 2022-05-04 13:28:04 +02:00 committed by GitHub
commit a39af9c307
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 98 additions and 24 deletions

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = home-assistant-frontend name = home-assistant-frontend
version = 20220503.0 version = 20220504.0
author = The Home Assistant Authors author = The Home Assistant Authors
author_email = hello@home-assistant.io author_email = hello@home-assistant.io
license = Apache-2.0 license = Apache-2.0

View File

@ -1,10 +1,11 @@
import "@lit-labs/virtualizer";
import type { LitVirtualizer } from "@lit-labs/virtualizer";
import { grid } from "@lit-labs/virtualizer/layouts/grid";
import "@material/mwc-button/mwc-button"; import "@material/mwc-button/mwc-button";
import "@material/mwc-list/mwc-list"; import "@material/mwc-list/mwc-list";
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import { mdiArrowUpRight, mdiPlay, mdiPlus } from "@mdi/js"; import { mdiArrowUpRight, mdiPlay, mdiPlus } from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip"; import "@polymer/paper-tooltip/paper-tooltip";
import { grid } from "@lit-labs/virtualizer/layouts/grid";
import "@lit-labs/virtualizer";
import { import {
css, css,
CSSResultGroup, CSSResultGroup,
@ -21,10 +22,12 @@ import {
state, state,
} from "lit/decorators"; } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map";
import { until } from "lit/directives/until"; import { until } from "lit/directives/until";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { computeRTLDirection } from "../../common/util/compute_rtl"; import { computeRTLDirection } from "../../common/util/compute_rtl";
import { debounce } from "../../common/util/debounce"; import { debounce } from "../../common/util/debounce";
import { getSignedPath } from "../../data/auth";
import type { MediaPlayerItem } from "../../data/media-player"; import type { MediaPlayerItem } from "../../data/media-player";
import { import {
browseMediaPlayer, browseMediaPlayer,
@ -39,6 +42,7 @@ import { showAlertDialog } from "../../dialogs/generic/show-dialog-box";
import { installResizeObserver } from "../../panels/lovelace/common/install-resize-observer"; import { installResizeObserver } from "../../panels/lovelace/common/install-resize-observer";
import { haStyle } from "../../resources/styles"; import { haStyle } from "../../resources/styles";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import { brandsUrl, extractDomainFromBrandUrl } from "../../util/brands-url";
import { documentationUrl } from "../../util/documentation-url"; import { documentationUrl } from "../../util/documentation-url";
import "../entity/ha-entity-picker"; import "../entity/ha-entity-picker";
import "../ha-button-menu"; import "../ha-button-menu";
@ -49,8 +53,6 @@ import "../ha-icon-button";
import "../ha-svg-icon"; import "../ha-svg-icon";
import "./ha-browse-media-tts"; import "./ha-browse-media-tts";
import type { TtsMediaPickedEvent } from "./ha-browse-media-tts"; import type { TtsMediaPickedEvent } from "./ha-browse-media-tts";
import { getSignedPath } from "../../data/auth";
import { brandsUrl, extractDomainFromBrandUrl } from "../../util/brands-url";
declare global { declare global {
interface HASSDomEvents { interface HASSDomEvents {
@ -100,6 +102,10 @@ export class HaMediaPlayerBrowse extends LitElement {
@query(".content") private _content?: HTMLDivElement; @query(".content") private _content?: HTMLDivElement;
@query("lit-virtualizer") private _virtualizer?: LitVirtualizer;
private _observed = false;
private _headerOffsetHeight = 0; private _headerOffsetHeight = 0;
private _resizeObserver?: ResizeObserver; private _resizeObserver?: ResizeObserver;
@ -280,6 +286,19 @@ export class HaMediaPlayerBrowse extends LitElement {
this._animateHeaderHeight(); this._animateHeaderHeight();
} else if (changedProps.has("_currentItem")) { } else if (changedProps.has("_currentItem")) {
this._setHeaderHeight(); this._setHeaderHeight();
// This fixes a race condition for resizing of the cards using the grid layout
if (this._observed) {
return;
}
// @ts-ignore
const virtualizer = this._virtualizer?._virtualizer;
if (virtualizer) {
this._observed = true;
setTimeout(() => virtualizer._observeMutations(), 0);
}
} }
} }
@ -477,6 +496,9 @@ export class HaMediaPlayerBrowse extends LitElement {
<lit-virtualizer <lit-virtualizer
scroller scroller
.items=${children} .items=${children}
style=${styleMap({
height: `${children.length * 72 + 26}px`,
})}
.renderItem=${this._renderListItem} .renderItem=${this._renderListItem}
></lit-virtualizer> ></lit-virtualizer>
${currentItem.not_shown ${currentItem.not_shown
@ -606,7 +628,6 @@ export class HaMediaPlayerBrowse extends LitElement {
</div> </div>
<span class="title">${child.title}</span> <span class="title">${child.title}</span>
</mwc-list-item> </mwc-list-item>
<li divider role="separator"></li>
`; `;
}; };

View File

@ -2,8 +2,10 @@ import type {
HassEntities, HassEntities,
HassEntityAttributeBase, HassEntityAttributeBase,
HassEntityBase, HassEntityBase,
HassEvent,
} from "home-assistant-js-websocket"; } from "home-assistant-js-websocket";
import { BINARY_STATE_ON } from "../common/const"; import { BINARY_STATE_ON } from "../common/const";
import { computeDomain } from "../common/entity/compute_domain";
import { computeStateDomain } from "../common/entity/compute_state_domain"; import { computeStateDomain } from "../common/entity/compute_state_domain";
import { supportsFeature } from "../common/entity/supports-feature"; import { supportsFeature } from "../common/entity/supports-feature";
import { caseInsensitiveStringCompare } from "../common/string/compare"; import { caseInsensitiveStringCompare } from "../common/string/compare";
@ -110,15 +112,32 @@ export const checkForEntityUpdates = async (
return; return;
} }
let updated = 0;
const unsubscribeEvents = await hass.connection.subscribeEvents<HassEvent>(
(event) => {
if (computeDomain(event.data.entity_id) === "update") {
updated++;
showToast(element, {
message: hass.localize("ui.panel.config.updates.updates_refreshed", {
count: updated,
}),
});
}
},
"state_changed"
);
await hass.callService("homeassistant", "update_entity", { await hass.callService("homeassistant", "update_entity", {
entity_id: entities, entity_id: entities,
}); });
if (filterUpdateEntitiesWithInstall(hass.states).length) { // there is no reliable way to know if all the updates are done updating, so we just wait a bit for now...
showToast(element, { await new Promise((r) => setTimeout(r, 10000));
message: hass.localize("ui.panel.config.updates.updates_refreshed"),
}); unsubscribeEvents();
} else {
if (updated === 0) {
showToast(element, { showToast(element, {
message: hass.localize("ui.panel.config.updates.no_new_updates"), message: hass.localize("ui.panel.config.updates.no_new_updates"),
}); });

View File

@ -1,3 +1,4 @@
import deepClone from "deep-clone-simple";
import "@material/mwc-button"; import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement } from "lit"; import { css, CSSResultGroup, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
@ -83,7 +84,7 @@ export default class HaAutomationAction extends LitElement {
ev.stopPropagation(); ev.stopPropagation();
const index = (ev.target as any).index; const index = (ev.target as any).index;
fireEvent(this, "value-changed", { fireEvent(this, "value-changed", {
value: this.actions.concat(this.actions[index]), value: this.actions.concat(deepClone(this.actions[index])),
}); });
} }

View File

@ -1,3 +1,4 @@
import deepClone from "deep-clone-simple";
import "@material/mwc-button"; import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit"; import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
@ -96,7 +97,7 @@ export default class HaAutomationCondition extends LitElement {
ev.stopPropagation(); ev.stopPropagation();
const index = (ev.target as any).index; const index = (ev.target as any).index;
fireEvent(this, "value-changed", { fireEvent(this, "value-changed", {
value: this.conditions.concat(this.conditions[index]), value: this.conditions.concat(deepClone(this.conditions[index])),
}); });
} }

View File

@ -1,3 +1,4 @@
import deepClone from "deep-clone-simple";
import "@material/mwc-button"; import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement } from "lit"; import { css, CSSResultGroup, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
@ -67,7 +68,7 @@ export default class HaAutomationTrigger extends LitElement {
ev.stopPropagation(); ev.stopPropagation();
const index = (ev.target as any).index; const index = (ev.target as any).index;
fireEvent(this, "value-changed", { fireEvent(this, "value-changed", {
value: this.triggers.concat(this.triggers[index]), value: this.triggers.concat(deepClone(this.triggers[index])),
}); });
} }

View File

@ -109,7 +109,11 @@ class HaConfigSectionUpdates extends LitElement {
></ha-config-updates> ></ha-config-updates>
` `
: html` : html`
${this.hass.localize("ui.panel.config.updates.no_updates")} <div class="no-updates">
${this.hass.localize(
"ui.panel.config.updates.no_updates"
)}
</div>
`} `}
</div> </div>
</ha-card> </ha-card>
@ -198,6 +202,10 @@ class HaConfigSectionUpdates extends LitElement {
flex-direction: column; flex-direction: column;
padding: 0; padding: 0;
} }
.no-updates {
padding: 16px;
}
`; `;
} }

View File

@ -9,6 +9,7 @@ import "../../../components/ha-alert";
import "../../../components/ha-icon-next"; import "../../../components/ha-icon-next";
import type { UpdateEntity } from "../../../data/update"; import type { UpdateEntity } from "../../../data/update";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "../../../components/ha-circular-progress";
@customElement("ha-config-updates") @customElement("ha-config-updates")
class HaConfigUpdates extends LitElement { class HaConfigUpdates extends LitElement {
@ -51,7 +52,18 @@ class HaConfigUpdates extends LitElement {
.title=${entity.attributes.title || .title=${entity.attributes.title ||
entity.attributes.friendly_name} entity.attributes.friendly_name}
.stateObj=${entity} .stateObj=${entity}
class=${this.narrow && entity.attributes.in_progress
? "updating"
: ""}
></state-badge> ></state-badge>
${this.narrow && entity.attributes.in_progress
? html`<ha-circular-progress
active
size="small"
slot="graphic"
class="absolute"
></ha-circular-progress>`
: ""}
<span <span
>${entity.attributes.title || >${entity.attributes.title ||
entity.attributes.friendly_name}</span entity.attributes.friendly_name}</span
@ -67,7 +79,13 @@ class HaConfigUpdates extends LitElement {
: ""} : ""}
</span> </span>
${!this.narrow ${!this.narrow
? html`<ha-icon-next slot="meta"></ha-icon-next>` ? entity.attributes.in_progress
? html`<ha-circular-progress
active
size="small"
slot="meta"
></ha-circular-progress>`
: html`<ha-icon-next slot="meta"></ha-icon-next>`
: ""} : ""}
</mwc-list-item> </mwc-list-item>
` `
@ -121,6 +139,12 @@ class HaConfigUpdates extends LitElement {
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
} }
ha-circular-progress.absolute {
position: absolute;
}
state-badge.updating {
opacity: 0.5;
}
`, `,
]; ];
} }

View File

@ -52,7 +52,6 @@ import type { ConfigEntryExtended } from "./ha-config-integrations";
import "./ha-integration-header"; import "./ha-integration-header";
const integrationsWithPanel = { const integrationsWithPanel = {
hassio: "/hassio/dashboard",
mqtt: "/config/mqtt", mqtt: "/config/mqtt",
zha: "/config/zha/dashboard", zha: "/config/zha/dashboard",
zwave_js: "/config/zwave_js/dashboard", zwave_js: "/config/zwave_js/dashboard",

View File

@ -1175,7 +1175,7 @@
}, },
"updates": { "updates": {
"caption": "Updates", "caption": "Updates",
"description": "Manage updates of Home Assistant, Add-ons and devices", "description": "Manage updates of Home Assistant, add-ons and devices",
"no_updates": "No updates available", "no_updates": "No updates available",
"no_update_entities": { "no_update_entities": {
"title": "Unable to check for updates", "title": "Unable to check for updates",
@ -1183,7 +1183,7 @@
}, },
"check_updates": "Check for updates", "check_updates": "Check for updates",
"no_new_updates": "No new updates found", "no_new_updates": "No new updates found",
"updates_refreshed": "Updates refreshed", "updates_refreshed": "{count} {count, plural,\n one {update}\n other {updates}\n} refreshed",
"title": "{count} {count, plural,\n one {update}\n other {updates}\n}", "title": "{count} {count, plural,\n one {update}\n other {updates}\n}",
"unable_to_fetch": "Unable to load updates", "unable_to_fetch": "Unable to load updates",
"version_available": "Version {version_available} is available", "version_available": "Version {version_available} is available",
@ -1490,7 +1490,7 @@
}, },
"core": { "core": {
"caption": "General", "caption": "General",
"description": "Name, Timezone and locale settings", "description": "Name, time zone and locale settings",
"section": { "section": {
"core": { "core": {
"header": "General Configuration", "header": "General Configuration",
@ -3139,7 +3139,7 @@
}, },
"analytics": { "analytics": {
"caption": "Analytics", "caption": "Analytics",
"description": "Learn how to share data to better the Open Home" "description": "Learn how to share data to improve Home Assistant"
}, },
"network": { "network": {
"caption": "Network", "caption": "Network",
@ -3184,11 +3184,11 @@
}, },
"system_health": { "system_health": {
"caption": "System Health", "caption": "System Health",
"description": "Status, Stats and Integration startup time", "description": "Status, metrics and integration startup time",
"cpu_usage": "Processor Usage", "cpu_usage": "Processor Usage",
"ram_usage": "Memory Usage", "ram_usage": "Memory Usage",
"core_stats": "Core Stats", "core_stats": "Core Metrics",
"supervisor_stats": "Supervisor Stats", "supervisor_stats": "Supervisor Metrics",
"integration_start_time": "Integration Startup Time" "integration_start_time": "Integration Startup Time"
}, },
"system_dashboard": { "system_dashboard": {