First pass

This commit is contained in:
Zack 2022-08-01 15:39:41 -05:00
parent c27e3325d9
commit ef834ef536
8 changed files with 310 additions and 16 deletions

View File

@ -1,12 +1,13 @@
import "../../../components/ha-alert";
import "../../../components/ha-faded";
import "@material/mwc-button/mwc-button";
import "@material/mwc-linear-progress/mwc-linear-progress";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { BINARY_STATE_OFF } from "../../../common/const";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-alert";
import "../../../components/ha-checkbox";
import "../../../components/ha-circular-progress";
import "../../../components/ha-faded";
import "../../../components/ha-formfield";
import "../../../components/ha-markdown";
import { UNAVAILABLE_STATES } from "../../../data/entity";
@ -21,7 +22,6 @@ import {
UPDATE_SUPPORT_SPECIFIC_VERSION,
} from "../../../data/update";
import type { HomeAssistant } from "../../../types";
import { BINARY_STATE_OFF } from "../../../common/const";
@customElement("more-info-update")
class MoreInfoUpdate extends LitElement {
@ -114,7 +114,8 @@ class MoreInfoUpdate extends LitElement {
></ha-markdown>`
: ""}
${supportsFeature(this.stateObj, UPDATE_SUPPORT_BACKUP)
? html`<hr />
? html`
<hr />
<ha-formfield
.label=${this.hass.localize(
"ui.dialogs.more_info_control.update.create_backup"
@ -124,7 +125,8 @@ class MoreInfoUpdate extends LitElement {
checked
.disabled=${updateIsInstalling(this.stateObj)}
></ha-checkbox>
</ha-formfield> `
</ha-formfield>
`
: ""}
<hr />
<div class="actions">

View File

@ -43,8 +43,8 @@ import { documentationUrl } from "../../../util/documentation-url";
import "../ha-config-section";
import { configSections } from "../ha-panel-config";
import "../repairs/ha-config-repairs";
import "../updates/ha-config-updates";
import "./ha-config-navigation";
import "./ha-config-updates";
const randomTip = (hass: HomeAssistant, narrow: boolean) => {
const weighted: string[] = [];

View File

@ -441,7 +441,7 @@ class HaPanelConfig extends HassRouterPage {
},
updates: {
tag: "ha-config-section-updates",
load: () => import("./core/ha-config-section-updates"),
load: () => import("./updates/ha-config-section-updates"),
},
repairs: {
tag: "ha-config-repairs-dashboard",

View File

@ -0,0 +1,263 @@
import "@material/mwc-button/mwc-button";
import "@material/mwc-linear-progress/mwc-linear-progress";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { BINARY_STATE_OFF } from "../../../common/const";
import { fireEvent } from "../../../common/dom/fire_event";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-checkbox";
import "../../../components/ha-circular-progress";
import { createCloseHeading } from "../../../components/ha-dialog";
import "../../../components/ha-faded";
import "../../../components/ha-formfield";
import "../../../components/ha-markdown";
import {
UpdateEntity,
updateIsInstalling,
updateReleaseNotes,
UPDATE_SUPPORT_BACKUP,
UPDATE_SUPPORT_PROGRESS,
UPDATE_SUPPORT_RELEASE_NOTES,
UPDATE_SUPPORT_SPECIFIC_VERSION,
} from "../../../data/update";
import { haStyle, haStyleDialog } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types";
import type { UpdateDialogParams } from "./show-update-dialog";
@customElement("dialog-update")
class DialogUpdate extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@state() private _entity?: UpdateEntity;
@state() private _releaseNotes?: string | null;
@state() private _error?: string;
@state() private _params?: UpdateDialogParams;
public showDialog(params: UpdateDialogParams): void {
this._params = params;
this._entity = this._params.entity;
if (supportsFeature(this._entity, UPDATE_SUPPORT_RELEASE_NOTES)) {
updateReleaseNotes(this.hass, this._entity!.entity_id)
.then((result) => {
this._releaseNotes = result;
})
.catch((err) => {
this._error = err.message;
});
}
}
public closeDialog() {
this._params = undefined;
this._entity = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
if (!this._entity) {
return html``;
}
const entity = this._entity;
const skippedVersion =
this._entity.attributes.latest_version &&
this._entity.attributes.skipped_version ===
this._entity.attributes.latest_version;
return html`
<ha-dialog
open
@closed=${this.closeDialog}
scrimClickAction
escapeKeyAction
.heading=${createCloseHeading(
this.hass,
this.hass.localize("ui.panel.config.updates.dialog.title", {
entity_name:
entity.attributes.title || entity.attributes.friendly_name,
})
)}
>
${this._error
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
: ""}
<div class="latest_version">
${this.hass.localize(
"ui.panel.config.updates.dialog.latest_version",
{
latest_version:
entity.attributes.latest_version ??
this.hass.localize("state.default.unavailable"),
}
)}
</div>
${this._entity.attributes.in_progress
? supportsFeature(this._entity, UPDATE_SUPPORT_PROGRESS) &&
typeof this._entity.attributes.in_progress === "number"
? html`<mwc-linear-progress
.progress=${this._entity.attributes.in_progress / 100}
buffer=""
></mwc-linear-progress>`
: html`<mwc-linear-progress indeterminate></mwc-linear-progress>`
: ""}
${supportsFeature(this._entity, UPDATE_SUPPORT_RELEASE_NOTES) &&
!this._error
? this._releaseNotes === undefined
? html`<ha-circular-progress active></ha-circular-progress>`
: html`
<ha-faded>
<ha-markdown .content=${this._releaseNotes}></ha-markdown>
</ha-faded>
`
: this._entity.attributes.release_summary
? html`
<ha-markdown
.content=${this._entity.attributes.release_summary}
></ha-markdown>
`
: ""}
${this._entity.attributes.release_url
? html`
<div class="release_url">
<a
href=${this._entity.attributes.release_url}
target="_blank"
rel="noreferrer"
class="button"
>
${this.hass.localize(
"ui.panel.config.updates.dialog.release_notes"
)}
</a>
</div>
`
: ""}
${supportsFeature(this._entity, UPDATE_SUPPORT_BACKUP)
? html`
<div class="backup">
<hr />
<ha-formfield
.label=${this.hass.localize(
"ui.panel.config.updates.dialog.create_backup"
)}
>
<ha-checkbox
checked
.disabled=${updateIsInstalling(this._entity)}
></ha-checkbox>
</ha-formfield>
</div>
`
: ""}
${this._entity.attributes.auto_update
? ""
: html`
<mwc-button
slot="secondaryAction"
@click=${this._handleSkip}
.disabled=${skippedVersion ||
this._entity.state === BINARY_STATE_OFF ||
updateIsInstalling(this._entity)}
>
${this._entity.state === BINARY_STATE_OFF &&
this._entity.attributes.skipped_version
? this.hass.localize(
"ui.panel.config.updates.dialog.clear_skipped"
)
: this.hass.localize("ui.panel.config.updates.dialog.skip")}
</mwc-button>
`}
<mwc-button
slot="primaryAction"
@click=${this._handleInstall}
.disabled=${updateIsInstalling(this._entity)}
>
${this.hass.localize("ui.panel.config.updates.dialog.update_now")}
</mwc-button>
</ha-dialog>
`;
}
get _shouldCreateBackup(): boolean | null {
if (!supportsFeature(this._entity!, UPDATE_SUPPORT_BACKUP)) {
return null;
}
const checkbox = this.shadowRoot?.querySelector("ha-checkbox");
if (checkbox) {
return checkbox.checked;
}
return true;
}
private _handleInstall(): void {
const installData: Record<string, any> = {
entity_id: this._entity!.entity_id,
};
if (this._shouldCreateBackup) {
installData.backup = true;
}
if (
supportsFeature(this._entity!, UPDATE_SUPPORT_SPECIFIC_VERSION) &&
this._entity!.attributes.latest_version
) {
installData.version = this._entity!.attributes.latest_version;
}
this.hass.callService("update", "install", installData);
}
private _handleSkip(): void {
this.hass.callService("update", "skip", {
entity_id: this._entity!.entity_id,
});
}
static styles: CSSResultGroup = [
haStyleDialog,
haStyle,
css`
ha-expansion-panel,
ha-markdown {
margin: 16px 0;
}
.latest_version {
font-weight: 500;
}
.backup {
margin-top: 16px;
}
ha-circular-progress {
width: 100%;
justify-content: center;
}
mwc-linear-progress {
margin-bottom: -10px;
margin-top: -10px;
}
.release_url {
text-align: center;
margin: 16px 0;
}
a.button {
display: inline-block;
text-decoration: none;
color: var(--primary-text-color);
padding: 6px 16px;
border-radius: 32px;
border: 1px solid var(--divider-color);
}
`,
];
}
declare global {
interface HTMLElementTagNameMap {
"dialog-update": DialogUpdate;
}
}

View File

@ -30,7 +30,7 @@ import {
} from "../../../dialogs/generic/show-dialog-box";
import "../../../layouts/hass-subpage";
import type { HomeAssistant } from "../../../types";
import "../dashboard/ha-config-updates";
import "./ha-config-updates";
@customElement("ha-config-section-updates")
class HaConfigSectionUpdates extends LitElement {

View File

@ -2,14 +2,14 @@ import "@material/mwc-button/mwc-button";
import "@material/mwc-list/mwc-list";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/entity/state-badge";
import "../../../components/ha-alert";
import "../../../components/ha-circular-progress";
import "../../../components/ha-icon-next";
import "../../../components/ha-list-item";
import type { UpdateEntity } from "../../../data/update";
import type { HomeAssistant } from "../../../types";
import "../../../components/ha-circular-progress";
import "../../../components/ha-list-item";
import { showUpdateDialog } from "./show-update-dialog";
@customElement("ha-config-updates")
class HaConfigUpdates extends LitElement {
@ -43,7 +43,7 @@ class HaConfigUpdates extends LitElement {
twoline
graphic="avatar"
class=${entity.attributes.skipped_version ? "skipped" : ""}
.entity_id=${entity.entity_id}
.entity=${entity}
.hasMeta=${!this.narrow}
@click=${this._openMoreInfo}
>
@ -95,9 +95,10 @@ class HaConfigUpdates extends LitElement {
}
private _openMoreInfo(ev: MouseEvent): void {
fireEvent(this, "hass-more-info", {
entityId: (ev.currentTarget as any).entity_id,
});
showUpdateDialog(this, { entity: (ev.currentTarget as any).entity });
// fireEvent(this, "hass-more-info", {
// entityId: (ev.currentTarget as any).entity.entity_id,
// });
}
static get styles(): CSSResultGroup[] {

View File

@ -0,0 +1,19 @@
import { fireEvent } from "../../../common/dom/fire_event";
import type { UpdateEntity } from "../../../data/update";
export interface UpdateDialogParams {
entity: UpdateEntity;
}
export const loadUpdateDialog = () => import("./dialog-update");
export const showUpdateDialog = (
element: HTMLElement,
updateParams: UpdateDialogParams
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-update",
dialogImport: loadUpdateDialog,
dialogParams: updateParams,
});
};

View File

@ -1223,7 +1223,16 @@
"show_skipped": "Show skipped updates",
"join_beta": "[%key:supervisor::system::supervisor::join_beta_action%]",
"leave_beta": "[%key:supervisor::system::supervisor::leave_beta_action%]",
"skipped": "Skipped"
"skipped": "Skipped",
"dialog": {
"title": "{entity_name} Update Available",
"create_backup": "[%key:ui::dialogs::more_info_control::update::create_backup%]",
"release_notes": "Read release notes",
"update_now": "Update now",
"skip": "[%key:ui::dialogs::more_info_control::update::skip%]",
"clear_skip": "[%key:ui::dialogs::more_info_control::update::clear_skipped%]",
"latest_version": "New version available: {latest_version}"
}
},
"repairs": {
"caption": "Repairs",