mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Use update entities for showing updates on configuration panel (#12100)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
c7e9ee785d
commit
7b6d3c0e36
@ -45,7 +45,6 @@ import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box";
|
|||||||
import "../../../src/layouts/hass-loading-screen";
|
import "../../../src/layouts/hass-loading-screen";
|
||||||
import "../../../src/layouts/hass-subpage";
|
import "../../../src/layouts/hass-subpage";
|
||||||
import "../../../src/layouts/hass-tabs-subpage";
|
import "../../../src/layouts/hass-tabs-subpage";
|
||||||
import { SUPERVISOR_UPDATE_NAMES } from "../../../src/panels/config/dashboard/ha-config-updates";
|
|
||||||
import { HomeAssistant, Route } from "../../../src/types";
|
import { HomeAssistant, Route } from "../../../src/types";
|
||||||
import { addonArchIsSupported, extractChangelog } from "../util/addon";
|
import { addonArchIsSupported, extractChangelog } from "../util/addon";
|
||||||
|
|
||||||
@ -55,6 +54,12 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SUPERVISOR_UPDATE_NAMES = {
|
||||||
|
core: "Home Assistant Core",
|
||||||
|
os: "Home Assistant Operating System",
|
||||||
|
supervisor: "Home Assistant Supervisor",
|
||||||
|
};
|
||||||
|
|
||||||
type updateType = "os" | "supervisor" | "core" | "addon";
|
type updateType = "os" | "supervisor" | "core" | "addon";
|
||||||
|
|
||||||
const changelogUrl = (
|
const changelogUrl = (
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
import { HomeAssistant } from "../../types";
|
|
||||||
|
|
||||||
interface SupervisorBaseAvailableUpdates {
|
|
||||||
panel_path?: string;
|
|
||||||
update_type?: string;
|
|
||||||
version_latest?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SupervisorAddonAvailableUpdates
|
|
||||||
extends SupervisorBaseAvailableUpdates {
|
|
||||||
update_type?: "addon";
|
|
||||||
icon?: string;
|
|
||||||
name?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SupervisorCoreAvailableUpdates
|
|
||||||
extends SupervisorBaseAvailableUpdates {
|
|
||||||
update_type?: "core";
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SupervisorOsAvailableUpdates extends SupervisorBaseAvailableUpdates {
|
|
||||||
update_type?: "os";
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SupervisorSupervisorAvailableUpdates
|
|
||||||
extends SupervisorBaseAvailableUpdates {
|
|
||||||
update_type?: "supervisor";
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SupervisorAvailableUpdates =
|
|
||||||
| SupervisorAddonAvailableUpdates
|
|
||||||
| SupervisorCoreAvailableUpdates
|
|
||||||
| SupervisorOsAvailableUpdates
|
|
||||||
| SupervisorSupervisorAvailableUpdates;
|
|
||||||
|
|
||||||
export interface SupervisorAvailableUpdatesResponse {
|
|
||||||
available_updates: SupervisorAvailableUpdates[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchSupervisorAvailableUpdates = async (
|
|
||||||
hass: HomeAssistant
|
|
||||||
): Promise<SupervisorAvailableUpdates[]> =>
|
|
||||||
(
|
|
||||||
await hass.callWS<SupervisorAvailableUpdatesResponse>({
|
|
||||||
type: "supervisor/api",
|
|
||||||
endpoint: "/available_updates",
|
|
||||||
method: "get",
|
|
||||||
})
|
|
||||||
).available_updates;
|
|
||||||
|
|
||||||
export const refreshSupervisorAvailableUpdates = async (
|
|
||||||
hass: HomeAssistant
|
|
||||||
): Promise<void> =>
|
|
||||||
hass.callWS<void>({
|
|
||||||
type: "supervisor/api",
|
|
||||||
endpoint: "/refresh_updates",
|
|
||||||
method: "post",
|
|
||||||
});
|
|
@ -1,3 +1,5 @@
|
|||||||
|
import type { ActionDetail } from "@material/mwc-list";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import {
|
import {
|
||||||
mdiCloudLock,
|
mdiCloudLock,
|
||||||
mdiDotsVertical,
|
mdiDotsVertical,
|
||||||
@ -5,10 +7,9 @@ import {
|
|||||||
mdiMagnify,
|
mdiMagnify,
|
||||||
mdiNewBox,
|
mdiNewBox,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import "@material/mwc-list/mwc-list-item";
|
|
||||||
import type { ActionDetail } from "@material/mwc-list";
|
|
||||||
import "@polymer/app-layout/app-header/app-header";
|
import "@polymer/app-layout/app-header/app-header";
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
|
import type { HassEntities } from "home-assistant-js-websocket";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
@ -18,30 +19,29 @@ import {
|
|||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||||
import "../../../components/ha-card";
|
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
|
||||||
import "../../../components/ha-icon-next";
|
import { caseInsensitiveStringCompare } from "../../../common/string/compare";
|
||||||
import "../../../components/ha-icon-button";
|
|
||||||
import "../../../components/ha-menu-button";
|
|
||||||
import "../../../components/ha-button-menu";
|
import "../../../components/ha-button-menu";
|
||||||
|
import "../../../components/ha-card";
|
||||||
|
import "../../../components/ha-icon-button";
|
||||||
|
import "../../../components/ha-icon-next";
|
||||||
|
import "../../../components/ha-menu-button";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import { CloudStatus } from "../../../data/cloud";
|
import { CloudStatus } from "../../../data/cloud";
|
||||||
import {
|
import { updateCanInstall, UpdateEntity } from "../../../data/update";
|
||||||
refreshSupervisorAvailableUpdates,
|
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||||
SupervisorAvailableUpdates,
|
|
||||||
} from "../../../data/supervisor/root";
|
|
||||||
import { showQuickBar } from "../../../dialogs/quick-bar/show-dialog-quick-bar";
|
import { showQuickBar } from "../../../dialogs/quick-bar/show-dialog-quick-bar";
|
||||||
import "../../../layouts/ha-app-layout";
|
import "../../../layouts/ha-app-layout";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { documentationUrl } from "../../../util/documentation-url";
|
||||||
|
import { showToast } from "../../../util/toast";
|
||||||
import "../ha-config-section";
|
import "../ha-config-section";
|
||||||
import { configSections } from "../ha-panel-config";
|
import { configSections } from "../ha-panel-config";
|
||||||
import "./ha-config-navigation";
|
import "./ha-config-navigation";
|
||||||
import "./ha-config-updates";
|
import "./ha-config-updates";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
|
||||||
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
|
|
||||||
import { showToast } from "../../../util/toast";
|
|
||||||
import { documentationUrl } from "../../../util/documentation-url";
|
|
||||||
|
|
||||||
const randomTip = (hass: HomeAssistant) => {
|
const randomTip = (hass: HomeAssistant) => {
|
||||||
const weighted: string[] = [];
|
const weighted: string[] = [];
|
||||||
@ -113,9 +113,6 @@ class HaConfigDashboard extends LitElement {
|
|||||||
|
|
||||||
@property() public cloudStatus?: CloudStatus;
|
@property() public cloudStatus?: CloudStatus;
|
||||||
|
|
||||||
// null means not available
|
|
||||||
@property() public supervisorUpdates?: SupervisorAvailableUpdates[] | null;
|
|
||||||
|
|
||||||
@property() public showAdvanced!: boolean;
|
@property() public showAdvanced!: boolean;
|
||||||
|
|
||||||
@state() private _tip?: string;
|
@state() private _tip?: string;
|
||||||
@ -123,6 +120,9 @@ class HaConfigDashboard extends LitElement {
|
|||||||
private _notifyUpdates = false;
|
private _notifyUpdates = false;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
|
const canInstallUpdates = this._filterUpdateEntitiesWithInstall(
|
||||||
|
this.hass.states
|
||||||
|
);
|
||||||
return html`
|
return html`
|
||||||
<ha-app-layout>
|
<ha-app-layout>
|
||||||
<app-header fixed slot="header">
|
<app-header fixed slot="header">
|
||||||
@ -160,50 +160,47 @@ class HaConfigDashboard extends LitElement {
|
|||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
full-width
|
full-width
|
||||||
>
|
>
|
||||||
${this.supervisorUpdates === undefined
|
${canInstallUpdates.length
|
||||||
? // Hide everything until updates loaded
|
? html`<ha-card>
|
||||||
html``
|
<ha-config-updates
|
||||||
: html`${this.supervisorUpdates?.length
|
.hass=${this.hass}
|
||||||
? html`<ha-card>
|
.narrow=${this.narrow}
|
||||||
<ha-config-updates
|
.updateEntities=${canInstallUpdates}
|
||||||
.hass=${this.hass}
|
></ha-config-updates>
|
||||||
.narrow=${this.narrow}
|
</ha-card>`
|
||||||
.supervisorUpdates=${this.supervisorUpdates}
|
: ""}
|
||||||
></ha-config-updates>
|
<ha-card>
|
||||||
</ha-card>`
|
${this.narrow && canInstallUpdates.length
|
||||||
: ""}
|
? html`<div class="title">
|
||||||
<ha-card>
|
${this.hass.localize("panel.config")}
|
||||||
${this.narrow && this.supervisorUpdates?.length
|
</div>`
|
||||||
? html`<div class="title">
|
: ""}
|
||||||
${this.hass.localize("panel.config")}
|
${this.cloudStatus && isComponentLoaded(this.hass, "cloud")
|
||||||
</div>`
|
? html`
|
||||||
: ""}
|
|
||||||
${this.cloudStatus && isComponentLoaded(this.hass, "cloud")
|
|
||||||
? html`
|
|
||||||
<ha-config-navigation
|
|
||||||
.hass=${this.hass}
|
|
||||||
.narrow=${this.narrow}
|
|
||||||
.showAdvanced=${this.showAdvanced}
|
|
||||||
.pages=${[
|
|
||||||
{
|
|
||||||
component: "cloud",
|
|
||||||
path: "/config/cloud",
|
|
||||||
name: "Home Assistant Cloud",
|
|
||||||
info: this.cloudStatus,
|
|
||||||
iconPath: mdiCloudLock,
|
|
||||||
iconColor: "#3B808E",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
></ha-config-navigation>
|
|
||||||
`
|
|
||||||
: ""}
|
|
||||||
<ha-config-navigation
|
<ha-config-navigation
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
.showAdvanced=${this.showAdvanced}
|
.showAdvanced=${this.showAdvanced}
|
||||||
.pages=${configSections.dashboard}
|
.pages=${[
|
||||||
|
{
|
||||||
|
component: "cloud",
|
||||||
|
path: "/config/cloud",
|
||||||
|
name: "Home Assistant Cloud",
|
||||||
|
info: this.cloudStatus,
|
||||||
|
iconPath: mdiCloudLock,
|
||||||
|
iconColor: "#3B808E",
|
||||||
|
},
|
||||||
|
]}
|
||||||
></ha-config-navigation>
|
></ha-config-navigation>
|
||||||
</ha-card>`}
|
`
|
||||||
|
: ""}
|
||||||
|
<ha-config-navigation
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
.showAdvanced=${this.showAdvanced}
|
||||||
|
.pages=${configSections.dashboard}
|
||||||
|
></ha-config-navigation>
|
||||||
|
</ha-card>
|
||||||
<div class="tips">
|
<div class="tips">
|
||||||
<ha-svg-icon .path=${mdiLightbulbOutline}></ha-svg-icon>
|
<ha-svg-icon .path=${mdiLightbulbOutline}></ha-svg-icon>
|
||||||
<span class="tip-word">Tip!</span>
|
<span class="tip-word">Tip!</span>
|
||||||
@ -221,11 +218,11 @@ class HaConfigDashboard extends LitElement {
|
|||||||
this._tip = randomTip(this.hass);
|
this._tip = randomTip(this.hass);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!changedProps.has("supervisorUpdates") || !this._notifyUpdates) {
|
if (!changedProps.has("hass") || !this._notifyUpdates) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._notifyUpdates = false;
|
this._notifyUpdates = false;
|
||||||
if (this.supervisorUpdates?.length) {
|
if (this._filterUpdateEntitiesWithInstall(this.hass.states).length) {
|
||||||
showToast(this, {
|
showToast(this, {
|
||||||
message: this.hass.localize(
|
message: this.hass.localize(
|
||||||
"ui.panel.config.updates.updates_refreshed"
|
"ui.panel.config.updates.updates_refreshed"
|
||||||
@ -238,6 +235,44 @@ class HaConfigDashboard extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _filterUpdateEntities = memoizeOne((entities: HassEntities) =>
|
||||||
|
(
|
||||||
|
Object.values(entities).filter(
|
||||||
|
(entity) => computeStateDomain(entity) === "update"
|
||||||
|
) as UpdateEntity[]
|
||||||
|
).sort((a, b) => {
|
||||||
|
if (a.attributes.title === "Home Assistant Core") {
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
if (b.attributes.title === "Home Assistant Core") {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (a.attributes.title === "Home Assistant Operating System") {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (b.attributes.title === "Home Assistant Operating System") {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (a.attributes.title === "Home Assistant Supervisor") {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b.attributes.title === "Home Assistant Supervisor") {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return caseInsensitiveStringCompare(
|
||||||
|
a.attributes.title || a.attributes.friendly_name || "",
|
||||||
|
b.attributes.title || b.attributes.friendly_name || ""
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
private _filterUpdateEntitiesWithInstall = memoizeOne(
|
||||||
|
(entities: HassEntities) =>
|
||||||
|
this._filterUpdateEntities(entities).filter((entity) =>
|
||||||
|
updateCanInstall(entity)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
private _showQuickBar(): void {
|
private _showQuickBar(): void {
|
||||||
showQuickBar(this, {
|
showQuickBar(this, {
|
||||||
commandMode: true,
|
commandMode: true,
|
||||||
@ -246,20 +281,24 @@ class HaConfigDashboard extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
|
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
|
||||||
|
const _entities = this._filterUpdateEntities(this.hass.states).map(
|
||||||
|
(entity) => entity.entity_id
|
||||||
|
);
|
||||||
switch (ev.detail.index) {
|
switch (ev.detail.index) {
|
||||||
case 0:
|
case 0:
|
||||||
if (isComponentLoaded(this.hass, "hassio")) {
|
if (_entities.length) {
|
||||||
this._notifyUpdates = true;
|
this._notifyUpdates = true;
|
||||||
await refreshSupervisorAvailableUpdates(this.hass);
|
await this.hass.callService("homeassistant", "update_entity", {
|
||||||
fireEvent(this, "ha-refresh-supervisor");
|
entity_id: _entities,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
showAlertDialog(this, {
|
showAlertDialog(this, {
|
||||||
title: this.hass.localize(
|
title: this.hass.localize(
|
||||||
"ui.panel.config.updates.check_unavailable.title"
|
"ui.panel.config.updates.no_update_entities.title"
|
||||||
),
|
),
|
||||||
text: this.hass.localize(
|
text: this.hass.localize(
|
||||||
"ui.panel.config.updates.check_unavailable.description"
|
"ui.panel.config.updates.no_update_entities.description"
|
||||||
),
|
),
|
||||||
warning: true,
|
warning: true,
|
||||||
});
|
});
|
||||||
|
@ -1,21 +1,14 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import { mdiPackageVariant } from "@mdi/js";
|
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import "../../../components/entity/state-badge";
|
||||||
import "../../../components/ha-alert";
|
import "../../../components/ha-alert";
|
||||||
import "../../../components/ha-logo-svg";
|
|
||||||
import "../../../components/ha-svg-icon";
|
|
||||||
import { SupervisorAvailableUpdates } from "../../../data/supervisor/root";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import "../../../components/ha-icon-next";
|
import "../../../components/ha-icon-next";
|
||||||
|
import type { UpdateEntity } from "../../../data/update";
|
||||||
export const SUPERVISOR_UPDATE_NAMES = {
|
import { HomeAssistant } from "../../../types";
|
||||||
core: "Home Assistant Core",
|
|
||||||
os: "Home Assistant Operating System",
|
|
||||||
supervisor: "Home Assistant Supervisor",
|
|
||||||
};
|
|
||||||
|
|
||||||
@customElement("ha-config-updates")
|
@customElement("ha-config-updates")
|
||||||
class HaConfigUpdates extends LitElement {
|
class HaConfigUpdates extends LitElement {
|
||||||
@ -24,62 +17,60 @@ class HaConfigUpdates extends LitElement {
|
|||||||
@property({ type: Boolean }) public narrow!: boolean;
|
@property({ type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public supervisorUpdates?: SupervisorAvailableUpdates[] | null;
|
public updateEntities?: UpdateEntity[];
|
||||||
|
|
||||||
@state() private _showAll = false;
|
@state() private _showAll = false;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
if (!this.supervisorUpdates?.length) {
|
if (!this.updateEntities?.length) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updates =
|
const updates =
|
||||||
this._showAll || this.supervisorUpdates.length <= 3
|
this._showAll || this.updateEntities.length <= 3
|
||||||
? this.supervisorUpdates
|
? this.updateEntities
|
||||||
: this.supervisorUpdates.slice(0, 2);
|
: this.updateEntities.slice(0, 2);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="title">
|
<div class="title">
|
||||||
${this.hass.localize("ui.panel.config.updates.title", {
|
${this.hass.localize("ui.panel.config.updates.title", {
|
||||||
count: this.supervisorUpdates.length,
|
count: this.updateEntities.length,
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
${updates.map(
|
${updates.map(
|
||||||
(update) => html`
|
(entity) => html`
|
||||||
<a href="/hassio${update.panel_path}">
|
<paper-icon-item
|
||||||
<paper-icon-item>
|
@click=${this._openMoreInfo}
|
||||||
<span slot="item-icon" class="icon">
|
.entity_id=${entity.entity_id}
|
||||||
${update.update_type === "addon"
|
>
|
||||||
? update.icon
|
<span slot="item-icon" class="icon">
|
||||||
? html`<img src="/api/hassio${update.icon}" />`
|
<state-badge
|
||||||
: html`<ha-svg-icon
|
.title=${entity.attributes.title ||
|
||||||
.path=${mdiPackageVariant}
|
entity.attributes.friendly_name}
|
||||||
></ha-svg-icon>`
|
.stateObj=${entity}
|
||||||
: html`<ha-logo-svg></ha-logo-svg>`}
|
slot="item-icon"
|
||||||
</span>
|
></state-badge>
|
||||||
<paper-item-body two-line>
|
</span>
|
||||||
${update.update_type === "addon"
|
<paper-item-body two-line>
|
||||||
? update.name
|
${entity.attributes.title || entity.attributes.friendly_name}
|
||||||
: SUPERVISOR_UPDATE_NAMES[update.update_type!]}
|
<div secondary>
|
||||||
<div secondary>
|
${this.hass.localize(
|
||||||
${this.hass.localize(
|
"ui.panel.config.updates.version_available",
|
||||||
"ui.panel.config.updates.version_available",
|
{
|
||||||
{
|
version_available: entity.attributes.latest_version,
|
||||||
version_available: update.version_latest,
|
}
|
||||||
}
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</paper-item-body>
|
||||||
</paper-item-body>
|
${!this.narrow ? html`<ha-icon-next></ha-icon-next>` : ""}
|
||||||
${!this.narrow ? html`<ha-icon-next></ha-icon-next>` : ""}
|
</paper-icon-item>
|
||||||
</paper-icon-item>
|
|
||||||
</a>
|
|
||||||
`
|
`
|
||||||
)}
|
)}
|
||||||
${!this._showAll && this.supervisorUpdates.length >= 4
|
${!this._showAll && this.updateEntities.length >= 4
|
||||||
? html`
|
? html`
|
||||||
<button class="show-more" @click=${this._showAllClicked}>
|
<button class="show-more" @click=${this._showAllClicked}>
|
||||||
${this.hass.localize("ui.panel.config.updates.more_updates", {
|
${this.hass.localize("ui.panel.config.updates.more_updates", {
|
||||||
count: this.supervisorUpdates!.length - updates.length,
|
count: this.updateEntities!.length - updates.length,
|
||||||
})}
|
})}
|
||||||
</button>
|
</button>
|
||||||
`
|
`
|
||||||
@ -87,6 +78,12 @@ class HaConfigUpdates extends LitElement {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _openMoreInfo(ev: MouseEvent): void {
|
||||||
|
fireEvent(this, "hass-more-info", {
|
||||||
|
entityId: (ev.currentTarget as any).entity_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _showAllClicked() {
|
private _showAllClicked() {
|
||||||
this._showAll = true;
|
this._showAll = true;
|
||||||
}
|
}
|
||||||
@ -99,25 +96,11 @@ class HaConfigUpdates extends LitElement {
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
}
|
}
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
.icon {
|
.icon {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
img,
|
|
||||||
ha-svg-icon,
|
|
||||||
ha-logo-svg {
|
|
||||||
--mdc-icon-size: 32px;
|
|
||||||
max-height: 32px;
|
|
||||||
width: 32px;
|
|
||||||
}
|
|
||||||
ha-logo-svg {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
ha-icon-next {
|
ha-icon-next {
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
height: 24px;
|
height: 24px;
|
||||||
@ -139,6 +122,9 @@ class HaConfigUpdates extends LitElement {
|
|||||||
outline: none;
|
outline: none;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
paper-icon-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,6 @@ import { customElement, property, state } from "lit/decorators";
|
|||||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||||
import { listenMediaQuery } from "../../common/dom/media_query";
|
import { listenMediaQuery } from "../../common/dom/media_query";
|
||||||
import { CloudStatus, fetchCloudStatus } from "../../data/cloud";
|
import { CloudStatus, fetchCloudStatus } from "../../data/cloud";
|
||||||
import {
|
|
||||||
fetchSupervisorAvailableUpdates,
|
|
||||||
SupervisorAvailableUpdates,
|
|
||||||
} from "../../data/supervisor/root";
|
|
||||||
import "../../layouts/hass-loading-screen";
|
import "../../layouts/hass-loading-screen";
|
||||||
import { HassRouterPage, RouterOptions } from "../../layouts/hass-router-page";
|
import { HassRouterPage, RouterOptions } from "../../layouts/hass-router-page";
|
||||||
import { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
import { PageNavigation } from "../../layouts/hass-tabs-subpage";
|
||||||
@ -397,8 +393,6 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
|
|
||||||
@state() private _cloudStatus?: CloudStatus;
|
@state() private _cloudStatus?: CloudStatus;
|
||||||
|
|
||||||
@state() private _supervisorUpdates?: SupervisorAvailableUpdates[] | null;
|
|
||||||
|
|
||||||
private _listeners: Array<() => void> = [];
|
private _listeners: Array<() => void> = [];
|
||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
@ -433,19 +427,7 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (isComponentLoaded(this.hass, "hassio")) {
|
|
||||||
this._loadSupervisorUpdates();
|
|
||||||
this.addEventListener("ha-refresh-supervisor", () => {
|
|
||||||
this._loadSupervisorUpdates();
|
|
||||||
});
|
|
||||||
this.addEventListener("connection-status", (ev) => {
|
|
||||||
if (ev.detail === "connected") {
|
|
||||||
this._loadSupervisorUpdates();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this._supervisorUpdates = null;
|
|
||||||
}
|
|
||||||
this.addEventListener("ha-refresh-cloud-status", () =>
|
this.addEventListener("ha-refresh-cloud-status", () =>
|
||||||
this._updateCloudStatus()
|
this._updateCloudStatus()
|
||||||
);
|
);
|
||||||
@ -476,7 +458,6 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
isWide,
|
isWide,
|
||||||
narrow: this.narrow,
|
narrow: this.narrow,
|
||||||
cloudStatus: this._cloudStatus,
|
cloudStatus: this._cloudStatus,
|
||||||
supervisorUpdates: this._supervisorUpdates,
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
el.route = this.routeTail;
|
el.route = this.routeTail;
|
||||||
@ -485,7 +466,6 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
el.isWide = isWide;
|
el.isWide = isWide;
|
||||||
el.narrow = this.narrow;
|
el.narrow = this.narrow;
|
||||||
el.cloudStatus = this._cloudStatus;
|
el.cloudStatus = this._cloudStatus;
|
||||||
el.supervisorUpdates = this._supervisorUpdates;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,16 +483,6 @@ class HaPanelConfig extends HassRouterPage {
|
|||||||
setTimeout(() => this._updateCloudStatus(), 5000);
|
setTimeout(() => this._updateCloudStatus(), 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadSupervisorUpdates(): Promise<void> {
|
|
||||||
try {
|
|
||||||
this._supervisorUpdates = await fetchSupervisorAvailableUpdates(
|
|
||||||
this.hass
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
this._supervisorUpdates = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1079,9 +1079,9 @@
|
|||||||
"learn_more": "Learn more"
|
"learn_more": "Learn more"
|
||||||
},
|
},
|
||||||
"updates": {
|
"updates": {
|
||||||
"check_unavailable": {
|
"no_update_entities": {
|
||||||
"title": "Unable to check for updates",
|
"title": "Unable to check for updates",
|
||||||
"description": "You need to run the Home Assistant operating system to be able to check and install updates from the Home Assistant user interface."
|
"description": "You do not have any integrations that provide updates."
|
||||||
},
|
},
|
||||||
"check_updates": "Check for updates",
|
"check_updates": "Check for updates",
|
||||||
"no_new_updates": "No new updates found",
|
"no_new_updates": "No new updates found",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user