Compare commits

...

12 Commits

Author SHA1 Message Date
Ludeeus
c252827545 hide watchdog if addon.startup !== once 2020-09-03 08:27:13 +00:00
Ludeeus
4a6ae87c7d change 2020-08-29 08:04:57 +00:00
Ludeeus
af92052ad3 Merge branch 'dev' of github.com:home-assistant/frontend into supervisor-confirmation 2020-08-29 08:01:50 +00:00
Ludeeus
05735e3125 hassio-snapshots confirmation 2020-08-28 18:58:27 +00:00
Ludeeus
5093fcbf78 hassio-addon-audio confirmation 2020-08-28 18:53:09 +00:00
Ludeeus
44a25925fe hassio-addon-network confirmation 2020-08-28 18:52:20 +00:00
Ludeeus
ade392ba5e hassio-addon-config confirmation 2020-08-28 18:52:05 +00:00
Ludeeus
2663f43d3d hassio-addon-info confirmation 2020-08-28 18:45:24 +00:00
Ludeeus
efa67d87d5 hassio-supervisor-log confirmation 2020-08-28 18:37:48 +00:00
Ludeeus
c930815f5a hassio-host-info confirmation 2020-08-28 18:35:10 +00:00
Ludeeus
2ee46dac88 hassio-supervisor-info confirmation 2020-08-28 18:31:15 +00:00
Ludeeus
8c3f85ff5c Convert ha-progress-button to lit 2020-08-28 18:29:26 +00:00
9 changed files with 516 additions and 413 deletions

View File

@@ -28,6 +28,7 @@ import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types"; import { HomeAssistant } from "../../../../src/types";
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart"; import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
import { hassioStyle } from "../../resources/hassio-style"; import { hassioStyle } from "../../resources/hassio-style";
import "../../../../src/components/buttons/ha-progress-button";
@customElement("hassio-addon-audio") @customElement("hassio-addon-audio")
class HassioAddonAudio extends LitElement { class HassioAddonAudio extends LitElement {
@@ -91,7 +92,9 @@ class HassioAddonAudio extends LitElement {
</paper-dropdown-menu> </paper-dropdown-menu>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button @click=${this._saveSettings}>Save</mwc-button> <ha-progress-button @click=${this._saveSettings}>
Save
</ha-progress-button>
</div> </div>
</ha-card> </ha-card>
`; `;
@@ -172,7 +175,10 @@ class HassioAddonAudio extends LitElement {
} }
} }
private async _saveSettings(): Promise<void> { private async _saveSettings(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
this._error = undefined; this._error = undefined;
const data: HassioAddonSetOptionParams = { const data: HassioAddonSetOptionParams = {
audio_input: audio_input:
@@ -182,12 +188,14 @@ class HassioAddonAudio extends LitElement {
}; };
try { try {
await setHassioAddonOption(this.hass, this.addon.slug, data); await setHassioAddonOption(this.hass, this.addon.slug, data);
if (this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.addon);
}
} catch { } catch {
this._error = "Failed to set addon audio device"; this._error = "Failed to set addon audio device";
} }
if (!this._error && this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.addon); button.progress = false;
}
} }
} }

View File

@@ -21,6 +21,8 @@ import {
HassioAddonSetOptionParams, HassioAddonSetOptionParams,
setHassioAddonOption, setHassioAddonOption,
} from "../../../../src/data/hassio/addon"; } from "../../../../src/data/hassio/addon";
import "../../../../src/components/buttons/ha-progress-button";
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box"; import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box";
import { haStyle } from "../../../../src/resources/styles"; import { haStyle } from "../../../../src/resources/styles";
import type { HomeAssistant } from "../../../../src/types"; import type { HomeAssistant } from "../../../../src/types";
@@ -55,20 +57,103 @@ class HassioAddonConfig extends LitElement {
${valid ? "" : html` <div class="errors">Invalid YAML</div> `} ${valid ? "" : html` <div class="errors">Invalid YAML</div> `}
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button class="warning" @click=${this._resetTapped}> <ha-progress-button class="warning" @click=${this._resetTapped}>
Reset to defaults Reset to defaults
</mwc-button> </ha-progress-button>
<mwc-button <ha-progress-button
@click=${this._saveTapped} @click=${this._saveTapped}
.disabled=${!this._configHasChanged || !valid} .disabled=${!this._configHasChanged || !valid}
> >
Save Save
</mwc-button> </ha-progress-button>
</div> </div>
</ha-card> </ha-card>
`; `;
} }
protected updated(changedProperties: PropertyValues): void {
super.updated(changedProperties);
if (changedProperties.has("addon")) {
this._editor.setValue(this.addon.options);
}
}
private _configChanged(): void {
this._configHasChanged = true;
this.requestUpdate();
}
private async _resetTapped(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: this.addon.name,
text: "Are you sure you want to reset all your options?",
confirmText: "reset options",
dismissText: "no",
});
if (!confirmed) {
button.progress = false;
return;
}
this._error = undefined;
const data: HassioAddonSetOptionParams = {
options: null,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
this._configHasChanged = false;
const eventdata = {
success: true,
response: undefined,
path: "options",
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err) {
this._error = `Failed to reset addon configuration, ${
err.body?.message || err
}`;
}
button.progress = false;
}
private async _saveTapped(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
let data: HassioAddonSetOptionParams;
this._error = undefined;
try {
data = {
options: this._editor.value,
};
} catch (err) {
this._error = err;
return;
}
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
this._configHasChanged = false;
const eventdata = {
success: true,
response: undefined,
path: "options",
};
fireEvent(this, "hass-api-called", eventdata);
if (this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.addon);
}
} catch (err) {
this._error = `Failed to save addon configuration, ${
err.body?.message || err
}`;
}
button.progress = false;
}
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [ return [
haStyle, haStyle,
@@ -98,80 +183,6 @@ class HassioAddonConfig extends LitElement {
`, `,
]; ];
} }
protected updated(changedProperties: PropertyValues): void {
super.updated(changedProperties);
if (changedProperties.has("addon")) {
this._editor.setValue(this.addon.options);
}
}
private _configChanged(): void {
this._configHasChanged = true;
this.requestUpdate();
}
private async _resetTapped(): Promise<void> {
const confirmed = await showConfirmationDialog(this, {
title: this.addon.name,
text: "Are you sure you want to reset all your options?",
confirmText: "reset options",
dismissText: "no",
});
if (!confirmed) {
return;
}
this._error = undefined;
const data: HassioAddonSetOptionParams = {
options: null,
};
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
this._configHasChanged = false;
const eventdata = {
success: true,
response: undefined,
path: "options",
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err) {
this._error = `Failed to reset addon configuration, ${
err.body?.message || err
}`;
}
}
private async _saveTapped(): Promise<void> {
let data: HassioAddonSetOptionParams;
this._error = undefined;
try {
data = {
options: this._editor.value,
};
} catch (err) {
this._error = err;
return;
}
try {
await setHassioAddonOption(this.hass, this.addon.slug, data);
this._configHasChanged = false;
const eventdata = {
success: true,
response: undefined,
path: "options",
};
fireEvent(this, "hass-api-called", eventdata);
} catch (err) {
this._error = `Failed to save addon configuration, ${
err.body?.message || err
}`;
}
if (!this._error && this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.addon);
}
}
} }
declare global { declare global {

View File

@@ -21,6 +21,7 @@ import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types"; import { HomeAssistant } from "../../../../src/types";
import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart"; import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart";
import { hassioStyle } from "../../resources/hassio-style"; import { hassioStyle } from "../../resources/hassio-style";
import "../../../../src/components/buttons/ha-progress-button";
interface NetworkItem { interface NetworkItem {
description: string; description: string;
@@ -85,38 +86,17 @@ class HassioAddonNetwork extends LitElement {
</table> </table>
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button class="warning" @click=${this._resetTapped}> <ha-progress-button class="warning" @click=${this._resetTapped}>
Reset to defaults Reset to defaults </ha-progress-button
</mwc-button> >>
<mwc-button @click=${this._saveTapped}>Save</mwc-button> <ha-progress-button @click=${this._saveTapped}>
Save
</ha-progress-button>
</div> </div>
</ha-card> </ha-card>
`; `;
} }
static get styles(): CSSResult[] {
return [
haStyle,
hassioStyle,
css`
:host {
display: block;
}
ha-card {
display: block;
}
.errors {
color: var(--error-color);
margin-bottom: 16px;
}
.card-actions {
display: flex;
justify-content: space-between;
}
`,
];
}
protected update(changedProperties: PropertyValues): void { protected update(changedProperties: PropertyValues): void {
super.update(changedProperties); super.update(changedProperties);
if (changedProperties.has("addon")) { if (changedProperties.has("addon")) {
@@ -149,7 +129,10 @@ class HassioAddonNetwork extends LitElement {
}); });
} }
private async _resetTapped(): Promise<void> { private async _resetTapped(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
const data: HassioAddonSetOptionParams = { const data: HassioAddonSetOptionParams = {
network: null, network: null,
}; };
@@ -162,17 +145,22 @@ class HassioAddonNetwork extends LitElement {
path: "option", path: "option",
}; };
fireEvent(this, "hass-api-called", eventdata); fireEvent(this, "hass-api-called", eventdata);
if (this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.addon);
}
} catch (err) { } catch (err) {
this._error = `Failed to set addon network configuration, ${ this._error = `Failed to set addon network configuration, ${
err.body?.message || err err.body?.message || err
}`; }`;
} }
if (!this._error && this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.addon); button.progress = false;
}
} }
private async _saveTapped(): Promise<void> { private async _saveTapped(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
this._error = undefined; this._error = undefined;
const networkconfiguration = {}; const networkconfiguration = {};
this._config!.forEach((item) => { this._config!.forEach((item) => {
@@ -191,14 +179,38 @@ class HassioAddonNetwork extends LitElement {
path: "option", path: "option",
}; };
fireEvent(this, "hass-api-called", eventdata); fireEvent(this, "hass-api-called", eventdata);
if (this.addon?.state === "started") {
await suggestAddonRestart(this, this.hass, this.addon);
}
} catch (err) { } catch (err) {
this._error = `Failed to set addon network configuration, ${ this._error = `Failed to set addon network configuration, ${
err.body?.message || err err.body?.message || err
}`; }`;
} }
if (!this._error && this.addon?.state === "started") { button.progress = false;
await suggestAddonRestart(this, this.hass, this.addon);
} }
static get styles(): CSSResult[] {
return [
haStyle,
hassioStyle,
css`
:host {
display: block;
}
ha-card {
display: block;
}
.errors {
color: var(--error-color);
margin-bottom: 16px;
}
.card-actions {
display: flex;
justify-content: space-between;
}
`,
];
} }
} }

View File

@@ -20,22 +20,13 @@ import {
CSSResult, CSSResult,
customElement, customElement,
html, html,
internalProperty,
LitElement, LitElement,
property, property,
internalProperty,
TemplateResult, TemplateResult,
} from "lit-element"; } from "lit-element";
import { classMap } from "lit-html/directives/class-map"; import { classMap } from "lit-html/directives/class-map";
import { atLeastVersion } from "../../../../src/common/config/version";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { navigate } from "../../../../src/common/navigate";
import "../../../../src/components/buttons/ha-call-api-button";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-label-badge";
import "../../../../src/components/ha-markdown";
import "../../../../src/components/ha-svg-icon";
import "../../../../src/components/ha-switch";
import { import {
fetchHassioAddonChangelog, fetchHassioAddonChangelog,
HassioAddonDetails, HassioAddonDetails,
@@ -46,13 +37,28 @@ import {
setHassioAddonSecurity, setHassioAddonSecurity,
uninstallHassioAddon, uninstallHassioAddon,
} from "../../../../src/data/hassio/addon"; } from "../../../../src/data/hassio/addon";
import { showConfirmationDialog } from "../../../../src/dialogs/generic/show-dialog-box"; import { atLeastVersion } from "../../../../src/common/config/version";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/components/buttons/ha-progress-button";
import { hassioStyle } from "../../resources/hassio-style";
import { haStyle } from "../../../../src/resources/styles"; import { haStyle } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types"; import { HomeAssistant } from "../../../../src/types";
import "../../components/hassio-card-content"; import { navigate } from "../../../../src/common/navigate";
import {
showConfirmationDialog,
showAlertDialog,
} from "../../../../src/dialogs/generic/show-dialog-box";
import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown"; import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown";
import { hassioStyle } from "../../resources/hassio-style";
import "../../../../src/components/buttons/ha-call-api-button";
import "../../../../src/components/buttons/ha-progress-button";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-label-badge";
import "../../../../src/components/ha-markdown";
import "../../../../src/components/ha-settings-row"; import "../../../../src/components/ha-settings-row";
import "../../../../src/components/ha-svg-icon";
import "../../../../src/components/ha-switch";
import "../../components/hassio-card-content";
const STAGE_ICON = { const STAGE_ICON = {
stable: mdiCheckCircle, stable: mdiCheckCircle,
@@ -127,8 +133,6 @@ class HassioAddonInfo extends LitElement {
@internalProperty() private _error?: string; @internalProperty() private _error?: string;
@property({ type: Boolean }) private _installing = false;
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
${this._computeUpdateAvailable ${this._computeUpdateAvailable
@@ -401,7 +405,7 @@ class HassioAddonInfo extends LitElement {
></ha-switch> ></ha-switch>
</ha-settings-row> </ha-settings-row>
${this.hass.userData?.showAdvanced ${this.addon.startup !== "once"
? html` ? html`
<ha-settings-row ?three-line=${this.narrow}> <ha-settings-row ?three-line=${this.narrow}>
<span slot="heading"> <span slot="heading">
@@ -528,12 +532,12 @@ class HassioAddonInfo extends LitElement {
</mwc-button> </mwc-button>
` `
: ""} : ""}
<mwc-button <ha-progress-button
class=" right warning" class=" right warning"
@click=${this._uninstallClicked} @click=${this._uninstallClicked}
> >
Uninstall Uninstall
</mwc-button> </ha-progress-button>
${this.addon.build ${this.addon.build
? html` ? html`
<ha-call-api-button <ha-call-api-button
@@ -555,8 +559,7 @@ class HassioAddonInfo extends LitElement {
` `
: ""} : ""}
<ha-progress-button <ha-progress-button
.disabled=${!this.addon.available || this._installing} .disabled=${!this.addon.available}
.progress=${this._installing}
@click=${this._installClicked} @click=${this._installClicked}
> >
Install Install
@@ -742,7 +745,6 @@ class HassioAddonInfo extends LitElement {
} }
private async _openChangelog(): Promise<void> { private async _openChangelog(): Promise<void> {
this._error = undefined;
try { try {
const content = await fetchHassioAddonChangelog( const content = await fetchHassioAddonChangelog(
this.hass, this.hass,
@@ -753,15 +755,18 @@ class HassioAddonInfo extends LitElement {
content, content,
}); });
} catch (err) { } catch (err) {
this._error = `Failed to get addon changelog, ${ showAlertDialog(this, {
err.body?.message || err title: "Failed to get addon changelog",
}`; text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
} }
} }
private async _installClicked(): Promise<void> { private async _installClicked(ev: CustomEvent): Promise<void> {
this._error = undefined; const button = ev.target as any;
this._installing = true; button.progress = true;
try { try {
await installHassioAddon(this.hass, this.addon.slug); await installHassioAddon(this.hass, this.addon.slug);
const eventdata = { const eventdata = {
@@ -771,12 +776,19 @@ class HassioAddonInfo extends LitElement {
}; };
fireEvent(this, "hass-api-called", eventdata); fireEvent(this, "hass-api-called", eventdata);
} catch (err) { } catch (err) {
this._error = `Failed to install addon, ${err.body?.message || err}`; showAlertDialog(this, {
title: "Failed to install addon",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
} }
this._installing = false; button.progress = false;
} }
private async _uninstallClicked(): Promise<void> { private async _uninstallClicked(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, { const confirmed = await showConfirmationDialog(this, {
title: this.addon.name, title: this.addon.name,
text: "Are you sure you want to uninstall this add-on?", text: "Are you sure you want to uninstall this add-on?",
@@ -785,6 +797,7 @@ class HassioAddonInfo extends LitElement {
}); });
if (!confirmed) { if (!confirmed) {
button.progress = false;
return; return;
} }
@@ -798,8 +811,13 @@ class HassioAddonInfo extends LitElement {
}; };
fireEvent(this, "hass-api-called", eventdata); fireEvent(this, "hass-api-called", eventdata);
} catch (err) { } catch (err) {
this._error = `Failed to uninstall addon, ${err.body?.message || err}`; showAlertDialog(this, {
title: "Failed to uninstall addon",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
} }
button.progress = false;
} }
static get styles(): CSSResult[] { static get styles(): CSSResult[] {

View File

@@ -1,27 +1,27 @@
import "@material/mwc-button"; import "@material/mwc-button";
import "@material/mwc-icon-button"; import "@material/mwc-icon-button";
import { mdiPackageVariant, mdiPackageVariantClosed, mdiReload } from "@mdi/js";
import "@polymer/paper-checkbox/paper-checkbox"; import "@polymer/paper-checkbox/paper-checkbox";
import type { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
import "@polymer/paper-input/paper-input"; import "@polymer/paper-input/paper-input";
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
import "@polymer/paper-radio-button/paper-radio-button"; import "@polymer/paper-radio-button/paper-radio-button";
import "@polymer/paper-radio-group/paper-radio-group"; import "@polymer/paper-radio-group/paper-radio-group";
import type { PaperCheckboxElement } from "@polymer/paper-checkbox/paper-checkbox";
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
import type { PaperRadioGroupElement } from "@polymer/paper-radio-group/paper-radio-group"; import type { PaperRadioGroupElement } from "@polymer/paper-radio-group/paper-radio-group";
import { mdiPackageVariant, mdiPackageVariantClosed, mdiReload } from "@mdi/js";
import { fireEvent } from "../../../src/common/dom/fire_event";
import { import {
css, css,
CSSResultArray, CSSResultArray,
customElement, customElement,
html, html,
internalProperty,
LitElement, LitElement,
property, property,
internalProperty,
PropertyValues, PropertyValues,
TemplateResult, TemplateResult,
} from "lit-element"; } from "lit-element";
import { fireEvent } from "../../../src/common/dom/fire_event";
import "../../../src/components/ha-card";
import "../../../src/components/ha-svg-icon";
import { import {
createHassioFullSnapshot, createHassioFullSnapshot,
createHassioPartialSnapshot, createHassioPartialSnapshot,
@@ -31,15 +31,19 @@ import {
HassioSnapshot, HassioSnapshot,
reloadHassioSnapshots, reloadHassioSnapshots,
} from "../../../src/data/hassio/snapshot"; } from "../../../src/data/hassio/snapshot";
import "../../../src/components/buttons/ha-progress-button";
import { hassioStyle } from "../resources/hassio-style";
import { HassioSupervisorInfo } from "../../../src/data/hassio/supervisor"; import { HassioSupervisorInfo } from "../../../src/data/hassio/supervisor";
import "../../../src/layouts/hass-tabs-subpage";
import { PolymerChangedEvent } from "../../../src/polymer-types";
import { haStyle } from "../../../src/resources/styles"; import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant, Route } from "../../../src/types"; import { HomeAssistant, Route } from "../../../src/types";
import "../components/hassio-card-content"; import { PolymerChangedEvent } from "../../../src/polymer-types";
import { showHassioSnapshotDialog } from "../dialogs/snapshot/show-dialog-hassio-snapshot"; import { showHassioSnapshotDialog } from "../dialogs/snapshot/show-dialog-hassio-snapshot";
import { supervisorTabs } from "../hassio-tabs"; import { supervisorTabs } from "../hassio-tabs";
import { hassioStyle } from "../resources/hassio-style";
import "../../../src/components/ha-card";
import "../../../src/components/ha-svg-icon";
import "../../../src/layouts/hass-tabs-subpage";
import "../components/hassio-card-content";
interface CheckboxItem { interface CheckboxItem {
slug: string; slug: string;
@@ -80,8 +84,6 @@ class HassioSnapshots extends LitElement {
{ slug: "addons/local", name: "Local add-ons", checked: true }, { slug: "addons/local", name: "Local add-ons", checked: true },
]; ];
@internalProperty() private _creatingSnapshot = false;
@internalProperty() private _error = ""; @internalProperty() private _error = "";
public async refreshData() { public async refreshData() {
@@ -192,12 +194,9 @@ class HassioSnapshots extends LitElement {
: undefined} : undefined}
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button <ha-progress-button @click=${this._createSnapshot}>
.disabled=${this._creatingSnapshot}
@click=${this._createSnapshot}
>
Create Create
</mwc-button> </ha-progress-button>
</div> </div>
</ha-card> </ha-card>
</div> </div>
@@ -230,7 +229,7 @@ class HassioSnapshots extends LitElement {
.icon=${snapshot.type === "full" .icon=${snapshot.type === "full"
? mdiPackageVariantClosed ? mdiPackageVariantClosed
: mdiPackageVariant} : mdiPackageVariant}
.icon-class="snapshot" icon-class="snapshot"
></hassio-card-content> ></hassio-card-content>
</div> </div>
</ha-card> </ha-card>
@@ -297,13 +296,16 @@ class HassioSnapshots extends LitElement {
} }
} }
private async _createSnapshot() { private async _createSnapshot(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
this._error = ""; this._error = "";
if (this._snapshotHasPassword && !this._snapshotPassword.length) { if (this._snapshotHasPassword && !this._snapshotPassword.length) {
this._error = "Please enter a password."; this._error = "Please enter a password.";
button.progress = false;
return; return;
} }
this._creatingSnapshot = true;
await this.updateComplete; await this.updateComplete;
const name = const name =
@@ -344,9 +346,8 @@ class HassioSnapshots extends LitElement {
fireEvent(this, "hass-api-called", { success: true, response: null }); fireEvent(this, "hass-api-called", { success: true, response: null });
} catch (err) { } catch (err) {
this._error = err.message; this._error = err.message;
} finally {
this._creatingSnapshot = false;
} }
button.progress = false;
} }
private _computeDetails(snapshot: HassioSnapshot) { private _computeDetails(snapshot: HassioSnapshot) {

View File

@@ -42,6 +42,8 @@ import {
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown"; import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
import { showNetworkDialog } from "../dialogs/network/show-dialog-network"; import { showNetworkDialog } from "../dialogs/network/show-dialog-network";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-button-menu"; import "../../../src/components/ha-button-menu";
import "../../../src/components/ha-card"; import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row"; import "../../../src/components/ha-settings-row";
@@ -108,12 +110,12 @@ class HassioHostInfo extends LitElement {
${this.hostInfo.version !== this.hostInfo.version_latest && ${this.hostInfo.version !== this.hostInfo.version_latest &&
this.hostInfo.features.includes("hassos") this.hostInfo.features.includes("hassos")
? html` ? html`
<mwc-button <ha-progress-button
title="Update the host OS" title="Update the host OS"
label="Update"
@click=${this._osUpdate} @click=${this._osUpdate}
> >
</mwc-button> Update
</ha-progress-button>
` `
: ""} : ""}
</ha-settings-row> </ha-settings-row>
@@ -141,24 +143,24 @@ class HassioHostInfo extends LitElement {
<div class="card-actions"> <div class="card-actions">
${this.hostInfo.features.includes("reboot") ${this.hostInfo.features.includes("reboot")
? html` ? html`
<mwc-button <ha-progress-button
title="Reboot the host OS" title="Reboot the host OS"
label="Reboot"
class="warning" class="warning"
@click=${this._hostReboot} @click=${this._hostReboot}
> >
</mwc-button> Reboot
</ha-progress-button>
` `
: ""} : ""}
${this.hostInfo.features.includes("shutdown") ${this.hostInfo.features.includes("shutdown")
? html` ? html`
<mwc-button <ha-progress-button
title="Shutdown the host OS" title="Shutdown the host OS"
label="Shutdown"
class="warning" class="warning"
@click=${this._hostShutdown} @click=${this._hostShutdown}
> >
</mwc-button> Shutdown
</ha-progress-button>
` `
: ""} : ""}
@@ -185,6 +187,177 @@ class HassioHostInfo extends LitElement {
`; `;
} }
protected firstUpdated(): void {
this._loadData();
}
private _primaryIpAddress = memoizeOne((network_info: NetworkInfo) => {
if (!network_info) {
return "";
}
return Object.keys(network_info?.interfaces)
.map((device) => network_info.interfaces[device])
.find((device) => device.primary)?.ip_address;
});
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
await this._showHardware();
break;
case 1:
await this._importFromUSB();
break;
}
}
private async _showHardware(): Promise<void> {
try {
const content = await fetchHassioHardwareInfo(this.hass);
showHassioMarkdownDialog(this, {
title: "Hardware",
content: `<pre>${safeDump(content, { indent: 2 })}</pre>`,
});
} catch (err) {
showAlertDialog(this, {
title: "Failed to get Hardware list",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
private async _hostReboot(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Reboot",
text: "Are you sure you want to reboot the host?",
confirmText: "reboot host",
dismissText: "no",
});
if (!confirmed) {
button.progress = false;
return;
}
try {
await rebootHost(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to reboot",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
button.progress = false;
}
private async _hostShutdown(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Shutdown",
text: "Are you sure you want to shutdown the host?",
confirmText: "shutdown host",
dismissText: "no",
});
if (!confirmed) {
button.progress = false;
return;
}
try {
await shutdownHost(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to shutdown",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
button.progress = false;
}
private async _osUpdate(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Update",
text: "Are you sure you want to update the OS?",
confirmText: "update os",
dismissText: "no",
});
if (!confirmed) {
button.progress = false;
return;
}
try {
await updateOS(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to update",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
button.progress = false;
}
private async _changeNetworkClicked(): Promise<void> {
showNetworkDialog(this, {
network: this._networkInfo!,
loadData: () => this._loadData(),
});
}
private async _changeHostnameClicked(): Promise<void> {
const curHostname: string = this.hostInfo.hostname;
const hostname = await showPromptDialog(this, {
title: "Change hostname",
inputLabel: "Please enter a new hostname:",
inputType: "string",
defaultValue: curHostname,
});
if (hostname && hostname !== curHostname) {
try {
await changeHostOptions(this.hass, { hostname });
this.hostInfo = await fetchHassioHostInfo(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Setting hostname failed",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
}
private async _importFromUSB(): Promise<void> {
try {
await configSyncOS(this.hass);
this.hostInfo = await fetchHassioHostInfo(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to import from USB",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
private async _loadData(): Promise<void> {
this._networkInfo = await fetchNetworkInfo(this.hass);
}
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [ return [
haStyle, haStyle,
@@ -240,162 +413,6 @@ class HassioHostInfo extends LitElement {
`, `,
]; ];
} }
protected firstUpdated(): void {
this._loadData();
}
private _primaryIpAddress = memoizeOne((network_info: NetworkInfo) => {
if (!network_info) {
return "";
}
return Object.keys(network_info?.interfaces)
.map((device) => network_info.interfaces[device])
.find((device) => device.primary)?.ip_address;
});
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
await this._showHardware();
break;
case 1:
await this._importFromUSB();
break;
}
}
private async _showHardware(): Promise<void> {
try {
const content = await fetchHassioHardwareInfo(this.hass);
showHassioMarkdownDialog(this, {
title: "Hardware",
content: `<pre>${safeDump(content, { indent: 2 })}</pre>`,
});
} catch (err) {
showAlertDialog(this, {
title: "Failed to get Hardware list",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
private async _hostReboot(): Promise<void> {
const confirmed = await showConfirmationDialog(this, {
title: "Reboot",
text: "Are you sure you want to reboot the host?",
confirmText: "reboot host",
dismissText: "no",
});
if (!confirmed) {
return;
}
try {
await rebootHost(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to reboot",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
private async _hostShutdown(): Promise<void> {
const confirmed = await showConfirmationDialog(this, {
title: "Shutdown",
text: "Are you sure you want to shutdown the host?",
confirmText: "shutdown host",
dismissText: "no",
});
if (!confirmed) {
return;
}
try {
await shutdownHost(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to shutdown",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
private async _osUpdate(): Promise<void> {
const confirmed = await showConfirmationDialog(this, {
title: "Update",
text: "Are you sure you want to update the OS?",
confirmText: "update os",
dismissText: "no",
});
if (!confirmed) {
return;
}
try {
await updateOS(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to update",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
private async _changeNetworkClicked(): Promise<void> {
showNetworkDialog(this, {
network: this._networkInfo!,
loadData: () => this._loadData(),
});
}
private async _changeHostnameClicked(): Promise<void> {
const curHostname: string = this.hostInfo.hostname;
const hostname = await showPromptDialog(this, {
title: "Change hostname",
inputLabel: "Please enter a new hostname:",
inputType: "string",
defaultValue: curHostname,
});
if (hostname && hostname !== curHostname) {
try {
await changeHostOptions(this.hass, { hostname });
this.hostInfo = await fetchHassioHostInfo(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Setting hostname failed",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
}
private async _importFromUSB(): Promise<void> {
try {
await configSyncOS(this.hass);
this.hostInfo = await fetchHassioHostInfo(this.hass);
} catch (err) {
showAlertDialog(this, {
title: "Failed to import from USB",
text:
typeof err === "object" ? err.body?.message || "Unkown error" : err,
});
}
}
private async _loadData(): Promise<void> {
this._networkInfo = await fetchNetworkInfo(this.hass);
}
} }
declare global { declare global {

View File

@@ -1,4 +1,3 @@
import "@material/mwc-button";
import { import {
css, css,
CSSResult, CSSResult,
@@ -25,6 +24,7 @@ import {
showConfirmationDialog, showConfirmationDialog,
} from "../../../src/dialogs/generic/show-dialog-box"; } from "../../../src/dialogs/generic/show-dialog-box";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-card"; import "../../../src/components/ha-card";
import "../../../src/components/ha-settings-row"; import "../../../src/components/ha-settings-row";
import "../../../src/components/ha-switch"; import "../../../src/components/ha-switch";
@@ -58,12 +58,12 @@ class HassioSupervisorInfo extends LitElement {
</span> </span>
${this.supervisorInfo.version !== this.supervisorInfo.version_latest ${this.supervisorInfo.version !== this.supervisorInfo.version_latest
? html` ? html`
<mwc-button <ha-progress-button
title="Update the supervisor" title="Update the supervisor"
label="Update"
@click=${this._supervisorUpdate} @click=${this._supervisorUpdate}
> >
</mwc-button> Update
</ha-progress-button>
` `
: ""} : ""}
</ha-settings-row> </ha-settings-row>
@@ -76,21 +76,21 @@ class HassioSupervisorInfo extends LitElement {
</span> </span>
${this.supervisorInfo.channel === "beta" ${this.supervisorInfo.channel === "beta"
? html` ? html`
<mwc-button <ha-progress-button
@click=${this._toggleBeta} @click=${this._toggleBeta}
label="Leave beta channel"
title="Get stable updates for Home Assistant, supervisor and host" title="Get stable updates for Home Assistant, supervisor and host"
> >
</mwc-button> Leave beta channel
</ha-progress-button>
` `
: this.supervisorInfo.channel === "stable" : this.supervisorInfo.channel === "stable"
? html` ? html`
<mwc-button <ha-progress-button
@click=${this._toggleBeta} @click=${this._toggleBeta}
label="Join beta channel"
title="Get beta updates for Home Assistant (RCs), supervisor and host" title="Get beta updates for Home Assistant (RCs), supervisor and host"
> >
</mwc-button> Join beta channel
</ha-progress-button>
` `
: ""} : ""}
</ha-settings-row> </ha-settings-row>
@@ -133,55 +133,21 @@ class HassioSupervisorInfo extends LitElement {
</div>`} </div>`}
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button <ha-progress-button
@click=${this._supervisorReload} @click=${this._supervisorReload}
title="Reload parts of the supervisor." title="Reload parts of the supervisor."
label="Reload"
> >
</mwc-button> Reload
</ha-progress-button>
</div> </div>
</ha-card> </ha-card>
`; `;
} }
static get styles(): CSSResult[] { private async _toggleBeta(ev: CustomEvent): Promise<void> {
return [ const button = ev.target as any;
haStyle, button.progress = true;
hassioStyle,
css`
ha-card {
height: 100%;
justify-content: space-between;
flex-direction: column;
display: flex;
}
.card-actions {
height: 48px;
border-top: none;
display: flex;
justify-content: space-between;
align-items: center;
}
button.link {
color: var(--primary-color);
}
ha-settings-row {
padding: 0;
height: 54px;
width: 100%;
}
ha-settings-row[three-line] {
height: 74px;
}
ha-settings-row > span[slot="description"] {
white-space: normal;
color: var(--secondary-text-color);
}
`,
];
}
private async _toggleBeta(): Promise<void> {
if (this.supervisorInfo.channel === "stable") { if (this.supervisorInfo.channel === "stable") {
const confirmed = await showConfirmationDialog(this, { const confirmed = await showConfirmationDialog(this, {
title: "WARNING", title: "WARNING",
@@ -204,6 +170,7 @@ class HassioSupervisorInfo extends LitElement {
}); });
if (!confirmed) { if (!confirmed) {
button.progress = false;
return; return;
} }
} }
@@ -221,11 +188,15 @@ class HassioSupervisorInfo extends LitElement {
typeof err === "object" ? err.body?.message || "Unkown error" : err, typeof err === "object" ? err.body?.message || "Unkown error" : err,
}); });
} }
button.progress = false;
} }
private async _supervisorReload(): Promise<void> { private async _supervisorReload(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
try { try {
await reloadSupervisor(this.hass); //await reloadSupervisor(this.hass);
} catch (err) { } catch (err) {
showAlertDialog(this, { showAlertDialog(this, {
title: "Failed to reload the supervisor", title: "Failed to reload the supervisor",
@@ -233,9 +204,25 @@ class HassioSupervisorInfo extends LitElement {
typeof err === "object" ? err.body?.message || "Unkown error" : err, typeof err === "object" ? err.body?.message || "Unkown error" : err,
}); });
} }
button.progress = false;
}
private async _supervisorUpdate(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
const confirmed = await showConfirmationDialog(this, {
title: "Update supervisor",
text: `Are you sure you want to upgrade supervisor to version ${this.supervisorInfo.version_latest}?`,
confirmText: "update",
dismissText: "cancel",
});
if (!confirmed) {
button.progress = false;
return;
} }
private async _supervisorUpdate(): Promise<void> {
try { try {
await updateSupervisor(this.hass); await updateSupervisor(this.hass);
} catch (err) { } catch (err) {
@@ -245,6 +232,7 @@ class HassioSupervisorInfo extends LitElement {
typeof err === "object" ? err.body.message || "Unkown error" : err, typeof err === "object" ? err.body.message || "Unkown error" : err,
}); });
} }
button.progress = false;
} }
private async _diagnosticsInformationDialog(): Promise<void> { private async _diagnosticsInformationDialog(): Promise<void> {
@@ -276,6 +264,43 @@ class HassioSupervisorInfo extends LitElement {
}); });
} }
} }
static get styles(): CSSResult[] {
return [
haStyle,
hassioStyle,
css`
ha-card {
height: 100%;
justify-content: space-between;
flex-direction: column;
display: flex;
}
.card-actions {
height: 48px;
border-top: none;
display: flex;
justify-content: space-between;
align-items: center;
}
button.link {
color: var(--primary-color);
}
ha-settings-row {
padding: 0;
height: 54px;
width: 100%;
}
ha-settings-row[three-line] {
height: 74px;
}
ha-settings-row > div[slot="description"] {
white-space: normal;
color: var(--secondary-text-color);
}
`,
];
}
} }
declare global { declare global {

View File

@@ -18,6 +18,7 @@ import { hassioStyle } from "../resources/hassio-style";
import { haStyle } from "../../../src/resources/styles"; import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant } from "../../../src/types"; import { HomeAssistant } from "../../../src/types";
import "../../../src/components/buttons/ha-progress-button";
import "../../../src/components/ha-card"; import "../../../src/components/ha-card";
import "../../../src/layouts/hass-loading-screen"; import "../../../src/layouts/hass-loading-screen";
import "../components/hassio-ansi-to-html"; import "../components/hassio-ansi-to-html";
@@ -104,12 +105,42 @@ class HassioSupervisorLog extends LitElement {
: html`<hass-loading-screen no-toolbar></hass-loading-screen>`} : html`<hass-loading-screen no-toolbar></hass-loading-screen>`}
</div> </div>
<div class="card-actions"> <div class="card-actions">
<mwc-button @click=${this._loadData}>Refresh</mwc-button> <ha-progress-button @click=${this._refresh}>
Refresh
</ha-progress-button>
</div> </div>
</ha-card> </ha-card>
`; `;
} }
private async _setLogProvider(ev): Promise<void> {
const provider = ev.detail.item.getAttribute("provider");
this._selectedLogProvider = provider;
await this._loadData();
}
private async _refresh(ev: CustomEvent): Promise<void> {
const button = ev.target as any;
button.progress = true;
await this._loadData();
button.progress = false;
}
private async _loadData(): Promise<void> {
this._error = undefined;
try {
this._content = await fetchHassioLogs(
this.hass,
this._selectedLogProvider
);
} catch (err) {
this._error = `Failed to get supervisor logs, ${
typeof err === "object" ? err.body?.message || "Unkown error" : err
}`;
}
}
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [ return [
haStyle, haStyle,
@@ -133,27 +164,6 @@ class HassioSupervisorLog extends LitElement {
`, `,
]; ];
} }
private async _setLogProvider(ev): Promise<void> {
const provider = ev.detail.item.getAttribute("provider");
this._selectedLogProvider = provider;
await this._loadData();
}
private async _loadData(): Promise<void> {
this._error = undefined;
try {
this._content = await fetchHassioLogs(
this.hass,
this._selectedLogProvider
);
} catch (err) {
this._error = `Failed to get supervisor logs, ${
typeof err === "object" ? err.body?.message || "Unkown error" : err
}`;
}
}
} }
declare global { declare global {

View File

@@ -52,6 +52,7 @@ export interface HassioAddonDetails extends HassioAddonInfo {
hassio_api: boolean; hassio_api: boolean;
hassio_role: "default" | "homeassistant" | "manager" | "admin"; hassio_role: "default" | "homeassistant" | "manager" | "admin";
homeassistant_api: boolean; homeassistant_api: boolean;
startup: "initialize" | "system" | "services" | "application" | "once";
auth_api: boolean; auth_api: boolean;
full_access: boolean; full_access: boolean;
protected: boolean; protected: boolean;