mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-26 02:36:37 +00:00
Add system-managed addon info (#25132)
* Add system managed addon info dialog * Add system managed alert * Fix translation * Update hassio/src/addon-view/info/hassio-addon-info.ts Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com> --------- Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
This commit is contained in:
parent
71b2e5f827
commit
dcbaa31c96
@ -1,12 +1,11 @@
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { stopPropagation } from "../../../../src/common/dom/stop_propagation";
|
||||
import "../../../../src/components/buttons/ha-progress-button";
|
||||
import "../../../../src/components/ha-alert";
|
||||
import "../../../../src/components/ha-card";
|
||||
import "../../../../src/components/ha-list-item";
|
||||
import "../../../../src/components/ha-select";
|
||||
import type {
|
||||
HassioAddonDetails,
|
||||
@ -29,6 +28,8 @@ class HassioAddonAudio extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@state() private _error?: string;
|
||||
|
||||
@state() private _inputDevices?: HassioHardwareAudioDevice[];
|
||||
@ -48,7 +49,7 @@ class HassioAddonAudio extends LitElement {
|
||||
<div class="card-content">
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this._inputDevices &&
|
||||
html`<ha-select
|
||||
.label=${this.supervisor.localize(
|
||||
@ -59,12 +60,13 @@ class HassioAddonAudio extends LitElement {
|
||||
fixedMenuPosition
|
||||
naturalMenuWidth
|
||||
.value=${this._selectedInput!}
|
||||
.disabled=${this.disabled}
|
||||
>
|
||||
${this._inputDevices.map(
|
||||
(item) => html`
|
||||
<mwc-list-item .value=${item.device || ""}>
|
||||
<ha-list-item .value=${item.device || ""}>
|
||||
${item.name}
|
||||
</mwc-list-item>
|
||||
</ha-list-item>
|
||||
`
|
||||
)}
|
||||
</ha-select>`}
|
||||
@ -78,18 +80,22 @@ class HassioAddonAudio extends LitElement {
|
||||
fixedMenuPosition
|
||||
naturalMenuWidth
|
||||
.value=${this._selectedOutput!}
|
||||
.disabled=${this.disabled}
|
||||
>
|
||||
${this._outputDevices.map(
|
||||
(item) => html`
|
||||
<mwc-list-item .value=${item.device || ""}
|
||||
>${item.name}</mwc-list-item
|
||||
<ha-list-item .value=${item.device || ""}
|
||||
>${item.name}</ha-list-item
|
||||
>
|
||||
`
|
||||
)}
|
||||
</ha-select>`}
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-progress-button @click=${this._saveSettings}>
|
||||
<ha-progress-button
|
||||
.disabled=${this.disabled}
|
||||
@click=${this._saveSettings}
|
||||
>
|
||||
${this.supervisor.localize("common.save")}
|
||||
</ha-progress-button>
|
||||
</div>
|
||||
@ -171,6 +177,10 @@ class HassioAddonAudio extends LitElement {
|
||||
}
|
||||
|
||||
private async _saveSettings(ev: CustomEvent): Promise<void> {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = ev.currentTarget as any;
|
||||
button.progress = true;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import "../../../../src/components/ha-spinner";
|
||||
import type { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
@ -7,6 +7,7 @@ import type { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
import type { HomeAssistant } from "../../../../src/types";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import "../info/hassio-addon-system-managed";
|
||||
import "./hassio-addon-audio";
|
||||
import "./hassio-addon-config";
|
||||
import "./hassio-addon-network";
|
||||
@ -19,6 +20,11 @@ class HassioAddonConfigDashboard extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ type: Boolean, attribute: "control-enabled" })
|
||||
public controlEnabled = false;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.addon) {
|
||||
return html`<ha-spinner></ha-spinner>`;
|
||||
@ -29,6 +35,16 @@ class HassioAddonConfigDashboard extends LitElement {
|
||||
|
||||
return html`
|
||||
<div class="content">
|
||||
${this.addon.system_managed &&
|
||||
(hasConfiguration || this.addon.network || this.addon.audio)
|
||||
? html`
|
||||
<hassio-addon-system-managed
|
||||
.supervisor=${this.supervisor}
|
||||
.narrow=${this.narrow}
|
||||
.hideButton=${this.controlEnabled}
|
||||
></hassio-addon-system-managed>
|
||||
`
|
||||
: nothing}
|
||||
${hasConfiguration || this.addon.network || this.addon.audio
|
||||
? html`
|
||||
${hasConfiguration
|
||||
@ -37,27 +53,33 @@ class HassioAddonConfigDashboard extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.addon=${this.addon}
|
||||
.supervisor=${this.supervisor}
|
||||
.disabled=${this.addon.system_managed &&
|
||||
!this.controlEnabled}
|
||||
></hassio-addon-config>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.network
|
||||
? html`
|
||||
<hassio-addon-network
|
||||
.hass=${this.hass}
|
||||
.addon=${this.addon}
|
||||
.supervisor=${this.supervisor}
|
||||
.disabled=${this.addon.system_managed &&
|
||||
!this.controlEnabled}
|
||||
></hassio-addon-network>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.audio
|
||||
? html`
|
||||
<hassio-addon-audio
|
||||
.hass=${this.hass}
|
||||
.addon=${this.addon}
|
||||
.supervisor=${this.supervisor}
|
||||
.disabled=${this.addon.system_managed &&
|
||||
!this.controlEnabled}
|
||||
></hassio-addon-audio>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
`
|
||||
: this.supervisor.localize("addon.configuration.no_configuration")}
|
||||
</div>
|
||||
|
@ -61,6 +61,8 @@ class HassioAddonConfig extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@state() private _configHasChanged = false;
|
||||
|
||||
@state() private _valid = true;
|
||||
@ -176,7 +178,7 @@ class HassioAddonConfig extends LitElement {
|
||||
.path=${mdiDotsVertical}
|
||||
slot="trigger"
|
||||
></ha-icon-button>
|
||||
<mwc-list-item .disabled=${!this._canShowSchema}>
|
||||
<mwc-list-item .disabled=${!this._canShowSchema || this.disabled}>
|
||||
${this._yamlMode
|
||||
? this.supervisor.localize(
|
||||
"addon.configuration.options.edit_in_ui"
|
||||
@ -185,7 +187,10 @@ class HassioAddonConfig extends LitElement {
|
||||
"addon.configuration.options.edit_in_yaml"
|
||||
)}
|
||||
</mwc-list-item>
|
||||
<mwc-list-item class="warning">
|
||||
<mwc-list-item
|
||||
class=${!this.disabled ? "warning" : ""}
|
||||
.disabled=${this.disabled}
|
||||
>
|
||||
${this.supervisor.localize("common.reset_defaults")}
|
||||
</mwc-list-item>
|
||||
</ha-button-menu>
|
||||
@ -195,6 +200,7 @@ class HassioAddonConfig extends LitElement {
|
||||
<div class="card-content">
|
||||
${showForm
|
||||
? html`<ha-form
|
||||
.disabled=${this.disabled}
|
||||
.data=${this._options!}
|
||||
@value-changed=${this._configChanged}
|
||||
.computeLabel=${this.computeLabel}
|
||||
@ -208,7 +214,7 @@ class HassioAddonConfig extends LitElement {
|
||||
)
|
||||
)}
|
||||
></ha-form>`
|
||||
: html` <ha-yaml-editor
|
||||
: html`<ha-yaml-editor
|
||||
@value-changed=${this._configChanged}
|
||||
.yamlSchema=${ADDON_YAML_SCHEMA}
|
||||
></ha-yaml-editor>`}
|
||||
@ -244,7 +250,9 @@ class HassioAddonConfig extends LitElement {
|
||||
<div class="card-actions right">
|
||||
<ha-progress-button
|
||||
@click=${this._saveTapped}
|
||||
.disabled=${!this._configHasChanged || !this._valid}
|
||||
.disabled=${this.disabled ||
|
||||
!this._configHasChanged ||
|
||||
!this._valid}
|
||||
>
|
||||
${this.supervisor.localize("common.save")}
|
||||
</ha-progress-button>
|
||||
@ -346,6 +354,10 @@ class HassioAddonConfig extends LitElement {
|
||||
}
|
||||
|
||||
private async _saveTapped(ev: CustomEvent): Promise<void> {
|
||||
if (this.disabled || !this._configHasChanged || !this._valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = ev.currentTarget as any;
|
||||
const options: Record<string, unknown> = this._yamlMode
|
||||
? this._editor?.value
|
||||
|
@ -28,6 +28,8 @@ class HassioAddonNetwork extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@state() private _showOptional = false;
|
||||
|
||||
@state() private _configHasChanged = false;
|
||||
@ -65,9 +67,10 @@ class HassioAddonNetwork extends LitElement {
|
||||
</p>
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||
: ""}
|
||||
: nothing}
|
||||
|
||||
<ha-form
|
||||
.disabled=${this.disabled}
|
||||
.data=${this._config}
|
||||
@value-changed=${this._configChanged}
|
||||
.computeLabel=${this._computeLabel}
|
||||
@ -92,14 +95,18 @@ class HassioAddonNetwork extends LitElement {
|
||||
>
|
||||
</ha-switch>
|
||||
</ha-formfield>`
|
||||
: ""}
|
||||
: nothing}
|
||||
<div class="card-actions">
|
||||
<ha-progress-button class="warning" @click=${this._resetTapped}>
|
||||
<ha-progress-button
|
||||
class="warning"
|
||||
.disabled=${this.disabled}
|
||||
@click=${this._resetTapped}
|
||||
>
|
||||
${this.supervisor.localize("common.reset_defaults")}
|
||||
</ha-progress-button>
|
||||
<ha-progress-button
|
||||
@click=${this._saveTapped}
|
||||
.disabled=${!this._configHasChanged}
|
||||
.disabled=${!this._configHasChanged || this.disabled}
|
||||
>
|
||||
${this.supervisor.localize("common.save")}
|
||||
</ha-progress-button>
|
||||
@ -155,6 +162,10 @@ class HassioAddonNetwork extends LitElement {
|
||||
}
|
||||
|
||||
private async _resetTapped(ev: CustomEvent): Promise<void> {
|
||||
if (this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = ev.currentTarget as any;
|
||||
const data: HassioAddonSetOptionParams = {
|
||||
network: null,
|
||||
@ -186,6 +197,10 @@ class HassioAddonNetwork extends LitElement {
|
||||
}
|
||||
|
||||
private async _saveTapped(ev: CustomEvent): Promise<void> {
|
||||
if (!this._configHasChanged || this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = ev.currentTarget as any;
|
||||
|
||||
this._error = undefined;
|
||||
|
@ -52,6 +52,9 @@ class HassioAddonDashboard extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@state()
|
||||
private _controlEnabled = false;
|
||||
|
||||
@state() private _error?: string;
|
||||
|
||||
private _backPath = new URLSearchParams(window.parent.location.search).get(
|
||||
@ -134,11 +137,17 @@ class HassioAddonDashboard extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.supervisor=${this.supervisor}
|
||||
.addon=${this.addon}
|
||||
.controlEnabled=${this._controlEnabled}
|
||||
@system-managed-take-control=${this._enableControl}
|
||||
></hassio-addon-router>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
private _enableControl() {
|
||||
this._controlEnabled = true;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
|
@ -23,6 +23,9 @@ class HassioAddonRouter extends HassRouterPage {
|
||||
| HassioAddonDetails
|
||||
| StoreAddonDetails;
|
||||
|
||||
@property({ type: Boolean, attribute: "control-enabled" })
|
||||
public controlEnabled = false;
|
||||
|
||||
protected routerOptions: RouterOptions = {
|
||||
defaultPage: "info",
|
||||
showLoading: true,
|
||||
@ -48,6 +51,7 @@ class HassioAddonRouter extends HassRouterPage {
|
||||
el.supervisor = this.supervisor;
|
||||
el.addon = this.addon;
|
||||
el.narrow = this.narrow;
|
||||
el.controlEnabled = this.controlEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,9 @@ class HassioAddonInfoDashboard extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public addon?: HassioAddonDetails;
|
||||
|
||||
@property({ type: Boolean, attribute: "control-enabled" })
|
||||
public controlEnabled = false;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.addon) {
|
||||
return html`<ha-spinner></ha-spinner>`;
|
||||
@ -34,6 +37,7 @@ class HassioAddonInfoDashboard extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.supervisor=${this.supervisor}
|
||||
.addon=${this.addon}
|
||||
.controlEnabled=${this.controlEnabled}
|
||||
></hassio-addon-info>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,8 +1,6 @@
|
||||
import "@material/mwc-button";
|
||||
import {
|
||||
mdiCheckCircle,
|
||||
mdiChip,
|
||||
mdiPlayCircle,
|
||||
mdiCircleOffOutline,
|
||||
mdiCursorDefaultClickOutline,
|
||||
mdiDocker,
|
||||
@ -19,27 +17,30 @@ import {
|
||||
mdiNumeric6,
|
||||
mdiNumeric7,
|
||||
mdiNumeric8,
|
||||
mdiPlayCircle,
|
||||
mdiPound,
|
||||
mdiShield,
|
||||
} from "@mdi/js";
|
||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { atLeastVersion } from "../../../../src/common/config/version";
|
||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||
import { navigate } from "../../../../src/common/navigate";
|
||||
import { capitalizeFirstLetter } from "../../../../src/common/string/capitalize-first-letter";
|
||||
import "../../../../src/components/buttons/ha-progress-button";
|
||||
import "../../../../src/components/ha-alert";
|
||||
import "../../../../src/components/ha-card";
|
||||
import "../../../../src/components/chips/ha-chip-set";
|
||||
import "../../../../src/components/chips/ha-assist-chip";
|
||||
import "../../../../src/components/chips/ha-chip-set";
|
||||
import "../../../../src/components/ha-alert";
|
||||
import "../../../../src/components/ha-button";
|
||||
import "../../../../src/components/ha-card";
|
||||
import "../../../../src/components/ha-formfield";
|
||||
import "../../../../src/components/ha-markdown";
|
||||
import "../../../../src/components/ha-settings-row";
|
||||
import "../../../../src/components/ha-svg-icon";
|
||||
import "../../../../src/components/ha-switch";
|
||||
import "../../../../src/components/ha-formfield";
|
||||
import type { HaSwitch } from "../../../../src/components/ha-switch";
|
||||
import type {
|
||||
AddonCapability,
|
||||
@ -81,10 +82,11 @@ import { bytesToString } from "../../../../src/util/bytes-to-string";
|
||||
import "../../components/hassio-card-content";
|
||||
import "../../components/supervisor-metric";
|
||||
import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown";
|
||||
import { showSystemManagedDialog } from "../../dialogs/system-managed/show-dialog-system-managed";
|
||||
import { hassioStyle } from "../../resources/hassio-style";
|
||||
import "../../update-available/update-available-card";
|
||||
import { addonArchIsSupported, extractChangelog } from "../../util/addon";
|
||||
import { capitalizeFirstLetter } from "../../../../src/common/string/capitalize-first-letter";
|
||||
import "./hassio-addon-system-managed";
|
||||
|
||||
const STAGE_ICON = {
|
||||
stable: mdiCheckCircle,
|
||||
@ -117,6 +119,9 @@ class HassioAddonInfo extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||
|
||||
@property({ type: Boolean, attribute: "control-enabled" })
|
||||
public controlEnabled = false;
|
||||
|
||||
@state() private _metrics?: HassioStats;
|
||||
|
||||
@state() private _error?: string;
|
||||
@ -155,6 +160,9 @@ class HassioAddonInfo extends LitElement {
|
||||
)}`,
|
||||
},
|
||||
];
|
||||
|
||||
const systemManaged = this._isSystemManaged(this.addon);
|
||||
|
||||
return html`
|
||||
${this.addon.update_available
|
||||
? html`
|
||||
@ -166,7 +174,7 @@ class HassioAddonInfo extends LitElement {
|
||||
@update-complete=${this._updateComplete}
|
||||
></update-available-card>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${"protected" in this.addon && !this.addon.protected
|
||||
? html`
|
||||
<ha-alert
|
||||
@ -178,22 +186,31 @@ class HassioAddonInfo extends LitElement {
|
||||
${this.supervisor.localize(
|
||||
"addon.dashboard.protection_mode.content"
|
||||
)}
|
||||
<mwc-button
|
||||
<ha-button
|
||||
slot="action"
|
||||
.label=${this.supervisor.localize(
|
||||
"addon.dashboard.protection_mode.enable"
|
||||
)}
|
||||
@click=${this._protectionToggled}
|
||||
>
|
||||
</mwc-button>
|
||||
</ha-button>
|
||||
</ha-alert>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${systemManaged
|
||||
? html`
|
||||
<hassio-addon-system-managed
|
||||
.supervisor=${this.supervisor}
|
||||
.narrow=${this.narrow}
|
||||
.hideButton=${this.controlEnabled}
|
||||
></hassio-addon-system-managed>
|
||||
`
|
||||
: nothing}
|
||||
|
||||
<ha-card outlined>
|
||||
<div class="card-content">
|
||||
<div class="addon-header">
|
||||
${!this.narrow ? this.addon.name : ""}
|
||||
${!this.narrow ? this.addon.name : nothing}
|
||||
<div class="addon-version light-color">
|
||||
${this.addon.version
|
||||
? html`
|
||||
@ -266,7 +283,7 @@ class HassioAddonInfo extends LitElement {
|
||||
</ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
|
||||
<ha-assist-chip
|
||||
filled
|
||||
@ -301,7 +318,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiNetwork}> </ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.full_access
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -317,7 +334,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiChip}></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.homeassistant_api
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -336,7 +353,7 @@ class HassioAddonInfo extends LitElement {
|
||||
></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this._computeHassioApi
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -355,7 +372,7 @@ class HassioAddonInfo extends LitElement {
|
||||
></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.docker_api
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -371,7 +388,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiDocker}></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.host_pid
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -387,7 +404,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiPound}></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.apparmor !== "default"
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -404,7 +421,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiShield}></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.auth_api
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -420,7 +437,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiKey}></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.ingress
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -439,7 +456,7 @@ class HassioAddonInfo extends LitElement {
|
||||
></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.signed
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
@ -455,7 +472,24 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-svg-icon slot="icon" .path=${mdiLinkLock}></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${systemManaged
|
||||
? html`
|
||||
<ha-assist-chip
|
||||
filled
|
||||
@click=${this._showSystemManagedDialog}
|
||||
id="system_managed"
|
||||
.label=${capitalizeFirstLetter(
|
||||
this.supervisor.localize("addon.system_managed.badge")
|
||||
)}
|
||||
>
|
||||
<ha-svg-icon
|
||||
slot="icon"
|
||||
.path=${mdiHomeAssistant}
|
||||
></ha-svg-icon>
|
||||
</ha-assist-chip>
|
||||
`
|
||||
: nothing}
|
||||
</ha-chip-set>
|
||||
|
||||
<div class="description light-color">
|
||||
@ -479,7 +513,7 @@ class HassioAddonInfo extends LitElement {
|
||||
src="/api/hassio/addons/${this.addon.slug}/logo"
|
||||
/>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.version
|
||||
? html`
|
||||
<div
|
||||
@ -500,6 +534,7 @@ class HassioAddonInfo extends LitElement {
|
||||
)}
|
||||
</span>
|
||||
<ha-switch
|
||||
.disabled=${systemManaged && !this.controlEnabled}
|
||||
@change=${this._startOnBootToggled}
|
||||
.checked=${this.addon.boot === "auto"}
|
||||
haptic
|
||||
@ -520,13 +555,15 @@ class HassioAddonInfo extends LitElement {
|
||||
)}
|
||||
</span>
|
||||
<ha-switch
|
||||
.disabled=${systemManaged &&
|
||||
!this.controlEnabled}
|
||||
@change=${this._watchdogToggled}
|
||||
.checked=${this.addon.watchdog}
|
||||
.checked=${this.addon.watchdog || false}
|
||||
haptic
|
||||
></ha-switch>
|
||||
</ha-settings-row>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this.addon.auto_update ||
|
||||
this.hass.userData?.showAdvanced
|
||||
? html`
|
||||
@ -542,13 +579,15 @@ class HassioAddonInfo extends LitElement {
|
||||
)}
|
||||
</span>
|
||||
<ha-switch
|
||||
.disabled=${systemManaged &&
|
||||
!this.controlEnabled}
|
||||
@change=${this._autoUpdateToggled}
|
||||
.checked=${this.addon.auto_update}
|
||||
haptic
|
||||
></ha-switch>
|
||||
</ha-settings-row>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${!this._computeCannotIngressSidebar && this.addon.ingress
|
||||
? html`
|
||||
<ha-settings-row ?three-line=${this.narrow}>
|
||||
@ -563,13 +602,15 @@ class HassioAddonInfo extends LitElement {
|
||||
)}
|
||||
</span>
|
||||
<ha-switch
|
||||
.disabled=${systemManaged &&
|
||||
!this.controlEnabled}
|
||||
@change=${this._panelToggled}
|
||||
.checked=${this.addon.ingress_panel}
|
||||
haptic
|
||||
></ha-switch>
|
||||
</ha-settings-row>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this._computeUsesProtectedOptions
|
||||
? html`
|
||||
<ha-settings-row ?three-line=${this.narrow}>
|
||||
@ -584,16 +625,18 @@ class HassioAddonInfo extends LitElement {
|
||||
)}
|
||||
</span>
|
||||
<ha-switch
|
||||
.disabled=${systemManaged &&
|
||||
!this.controlEnabled}
|
||||
@change=${this._protectionToggled}
|
||||
.checked=${this.addon.protected}
|
||||
haptic
|
||||
></ha-switch>
|
||||
</ha-settings-row>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
</div>
|
||||
<div>
|
||||
${this.addon.version && this.addon.state === "started"
|
||||
@ -612,12 +655,12 @@ class HassioAddonInfo extends LitElement {
|
||||
></supervisor-metric>
|
||||
`
|
||||
)}`
|
||||
: ""}
|
||||
: nothing}
|
||||
</div>
|
||||
</div>
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
|
||||
: ""}
|
||||
: nothing}
|
||||
${!this.addon.version && addonStoreInfo && !this.addon.available
|
||||
? !addonArchIsSupported(
|
||||
this.supervisor.info.supported_arch,
|
||||
@ -641,7 +684,7 @@ class HassioAddonInfo extends LitElement {
|
||||
)}
|
||||
</ha-alert>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<div>
|
||||
@ -651,6 +694,7 @@ class HassioAddonInfo extends LitElement {
|
||||
<ha-progress-button
|
||||
class="warning"
|
||||
@click=${this._stopClicked}
|
||||
.disabled=${systemManaged && !this.controlEnabled}
|
||||
>
|
||||
${this.supervisor.localize("addon.dashboard.stop")}
|
||||
</ha-progress-button>
|
||||
@ -688,26 +732,27 @@ class HassioAddonInfo extends LitElement {
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<mwc-button>
|
||||
<ha-button>
|
||||
${this.supervisor.localize(
|
||||
"addon.dashboard.open_web_ui"
|
||||
)}
|
||||
</mwc-button>
|
||||
</ha-button>
|
||||
</a>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this._computeShowIngressUI
|
||||
? html`
|
||||
<mwc-button @click=${this._openIngress}>
|
||||
<ha-button @click=${this._openIngress}>
|
||||
${this.supervisor.localize(
|
||||
"addon.dashboard.open_web_ui"
|
||||
)}
|
||||
</mwc-button>
|
||||
</ha-button>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
<ha-progress-button
|
||||
class="warning"
|
||||
@click=${this._uninstallClicked}
|
||||
.disabled=${systemManaged && !this.controlEnabled}
|
||||
>
|
||||
${this.supervisor.localize("addon.dashboard.uninstall")}
|
||||
</ha-progress-button>
|
||||
@ -720,8 +765,8 @@ class HassioAddonInfo extends LitElement {
|
||||
${this.supervisor.localize("addon.dashboard.rebuild")}
|
||||
</ha-progress-button>
|
||||
`
|
||||
: ""}`
|
||||
: ""}
|
||||
: nothing}`
|
||||
: nothing}
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
@ -737,7 +782,7 @@ class HassioAddonInfo extends LitElement {
|
||||
</div>
|
||||
</ha-card>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
`;
|
||||
}
|
||||
|
||||
@ -822,6 +867,13 @@ class HassioAddonInfo extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _showSystemManagedDialog() {
|
||||
showSystemManagedDialog(this, {
|
||||
addon: this.addon as HassioAddonDetails,
|
||||
supervisor: this.supervisor,
|
||||
});
|
||||
}
|
||||
|
||||
private get _computeIsRunning(): boolean {
|
||||
return (this.addon as HassioAddonDetails)?.state === "started";
|
||||
}
|
||||
@ -1014,6 +1066,10 @@ class HassioAddonInfo extends LitElement {
|
||||
}
|
||||
|
||||
private async _stopClicked(ev: CustomEvent): Promise<void> {
|
||||
if (this._isSystemManaged(this.addon) && !this.controlEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = ev.currentTarget as any;
|
||||
button.progress = true;
|
||||
|
||||
@ -1125,6 +1181,10 @@ class HassioAddonInfo extends LitElement {
|
||||
}
|
||||
|
||||
private async _uninstallClicked(ev: CustomEvent): Promise<void> {
|
||||
if (this._isSystemManaged(this.addon) && !this.controlEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = ev.currentTarget as any;
|
||||
button.progress = true;
|
||||
let removeData = false;
|
||||
@ -1179,6 +1239,11 @@ class HassioAddonInfo extends LitElement {
|
||||
button.progress = false;
|
||||
}
|
||||
|
||||
private _isSystemManaged = memoizeOne(
|
||||
(addon: HassioAddonDetails | StoreAddonDetails) =>
|
||||
"system_managed" in addon && addon.system_managed
|
||||
);
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
@ -1201,7 +1266,7 @@ class HassioAddonInfo extends LitElement {
|
||||
ha-card.warning .card-content {
|
||||
color: white;
|
||||
}
|
||||
ha-card.warning mwc-button {
|
||||
ha-card.warning ha-button {
|
||||
--mdc-theme-primary: white !important;
|
||||
}
|
||||
.warning {
|
||||
@ -1246,7 +1311,7 @@ class HassioAddonInfo extends LitElement {
|
||||
ha-svg-icon.stopped {
|
||||
color: var(--error-color);
|
||||
}
|
||||
protection-enable mwc-button {
|
||||
protection-enable ha-button {
|
||||
--mdc-theme-primary: white;
|
||||
}
|
||||
.description a {
|
||||
@ -1328,7 +1393,7 @@ class HassioAddonInfo extends LitElement {
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
ha-alert mwc-button {
|
||||
ha-alert ha-button {
|
||||
--mdc-theme-primary: var(--primary-text-color);
|
||||
}
|
||||
|
||||
|
60
hassio/src/addon-view/info/hassio-addon-system-managed.ts
Normal file
60
hassio/src/addon-view/info/hassio-addon-system-managed.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import "@material/mwc-button";
|
||||
import type { TemplateResult } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||
import "../../../../src/components/ha-alert";
|
||||
import "../../../../src/components/ha-button";
|
||||
import type { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
||||
|
||||
@customElement("hassio-addon-system-managed")
|
||||
class HassioAddonSystemManaged extends LitElement {
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||
|
||||
@property({ type: Boolean, attribute: "hide-button" }) public hideButton =
|
||||
false;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-alert
|
||||
alert-type="warning"
|
||||
.title=${this.supervisor.localize("addon.system_managed.title")}
|
||||
.narrow=${this.narrow}
|
||||
>
|
||||
${this.supervisor.localize("addon.system_managed.description")}
|
||||
${!this.hideButton
|
||||
? html`
|
||||
<ha-button slot="action" @click=${this._takeControl}>
|
||||
${this.supervisor.localize("addon.system_managed.take_control")}
|
||||
</ha-button>
|
||||
`
|
||||
: nothing}
|
||||
</ha-alert>
|
||||
`;
|
||||
}
|
||||
|
||||
private _takeControl() {
|
||||
fireEvent(this, "system-managed-take-control");
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
ha-alert {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
ha-button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
}
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hassio-addon-system-managed": HassioAddonSystemManaged;
|
||||
}
|
||||
|
||||
interface HASSDomEvents {
|
||||
"system-managed-take-control": undefined;
|
||||
}
|
||||
}
|
@ -38,6 +38,7 @@ class HassioMarkdownDialog extends LitElement {
|
||||
open
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${createCloseHeading(this.hass, this.title)}
|
||||
hideactions
|
||||
>
|
||||
<ha-markdown
|
||||
.content=${this.content || ""}
|
||||
|
192
hassio/src/dialogs/system-managed/dialog-system-managed.ts
Normal file
192
hassio/src/dialogs/system-managed/dialog-system-managed.ts
Normal file
@ -0,0 +1,192 @@
|
||||
import { mdiClose, mdiPuzzle, mdiSwapHorizontal } from "@mdi/js";
|
||||
import type { CSSResultGroup } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { atLeastVersion } from "../../../../src/common/config/version";
|
||||
import "../../../../src/components/ha-dialog-header";
|
||||
import "../../../../src/components/ha-icon-button";
|
||||
import "../../../../src/components/ha-icon-next";
|
||||
import "../../../../src/components/ha-md-dialog";
|
||||
import type { HaMdDialog } from "../../../../src/components/ha-md-dialog";
|
||||
import "../../../../src/components/ha-md-list";
|
||||
import "../../../../src/components/ha-md-list-item";
|
||||
import "../../../../src/components/ha-svg-icon";
|
||||
import {
|
||||
getConfigEntry,
|
||||
type ConfigEntry,
|
||||
} from "../../../../src/data/config_entries";
|
||||
import type { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import type { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
||||
import { mdiHomeAssistant } from "../../../../src/resources/home-assistant-logo-svg";
|
||||
import { haStyle } from "../../../../src/resources/styles";
|
||||
import type { HomeAssistant } from "../../../../src/types";
|
||||
import { brandsUrl } from "../../../../src/util/brands-url";
|
||||
import type { SystemManagedDialogParams } from "./show-dialog-system-managed";
|
||||
|
||||
@customElement("dialog-system-managed")
|
||||
class HassioSystemManagedDialog extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _supervisor?: Supervisor;
|
||||
|
||||
@state() private _addon?: HassioAddonDetails;
|
||||
|
||||
@state() private _open = false;
|
||||
|
||||
@state() private _configEntry?: ConfigEntry;
|
||||
|
||||
@query("ha-md-dialog") private _dialog?: HaMdDialog;
|
||||
|
||||
public async showDialog(
|
||||
dialogParams: SystemManagedDialogParams
|
||||
): Promise<void> {
|
||||
this._addon = dialogParams.addon;
|
||||
this._supervisor = dialogParams.supervisor;
|
||||
this._open = true;
|
||||
this._loadConfigEntry();
|
||||
}
|
||||
|
||||
private _dialogClosed() {
|
||||
this._addon = undefined;
|
||||
this._supervisor = undefined;
|
||||
this._configEntry = undefined;
|
||||
this._open = false;
|
||||
}
|
||||
|
||||
public closeDialog() {
|
||||
this._dialog?.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._addon || !this._open || !this._supervisor) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const addonImage =
|
||||
atLeastVersion(this.hass.config.version, 0, 105) && this._addon.icon
|
||||
? `/api/hassio/addons/${this._addon.slug}/icon`
|
||||
: undefined;
|
||||
|
||||
return html`
|
||||
<ha-md-dialog open @closed=${this._dialogClosed}>
|
||||
<ha-dialog-header slot="headline">
|
||||
<ha-icon-button
|
||||
slot="navigationIcon"
|
||||
.path=${mdiClose}
|
||||
@click=${this.closeDialog}
|
||||
></ha-icon-button>
|
||||
<span slot="title">${this._addon?.name}</span>
|
||||
</ha-dialog-header>
|
||||
<div slot="content">
|
||||
<div class="icons">
|
||||
<ha-svg-icon
|
||||
class="primary"
|
||||
.path=${mdiHomeAssistant}
|
||||
></ha-svg-icon>
|
||||
<ha-svg-icon .path=${mdiSwapHorizontal}></ha-svg-icon>
|
||||
${addonImage
|
||||
? html`<img src=${addonImage} alt=${this._addon.name} />`
|
||||
: html`<ha-svg-icon .path=${mdiPuzzle}></ha-svg-icon>`}
|
||||
</div>
|
||||
${this._supervisor.localize("addon.system_managed.title")}.<br />
|
||||
${this._supervisor.localize("addon.system_managed.description")}
|
||||
${this._configEntry
|
||||
? html`
|
||||
<h3>
|
||||
${this._supervisor.localize(
|
||||
"addon.system_managed.managed_by"
|
||||
)}:
|
||||
</h3>
|
||||
<ha-md-list>
|
||||
<ha-md-list-item
|
||||
type="link"
|
||||
href=${`/config/integrations/integration/${this._configEntry.domain}`}
|
||||
>
|
||||
<img
|
||||
slot="start"
|
||||
class="integration-icon"
|
||||
alt=${this._configEntry.title}
|
||||
src=${brandsUrl({
|
||||
domain: this._configEntry.domain,
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
@error=${this._onImageError}
|
||||
@load=${this._onImageLoad}
|
||||
/>
|
||||
${this._configEntry.title}
|
||||
<ha-icon-next slot="end"></ha-icon-next>
|
||||
</ha-md-list-item>
|
||||
</ha-md-list>
|
||||
`
|
||||
: nothing}
|
||||
</div>
|
||||
</ha-md-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _onImageLoad(ev) {
|
||||
ev.target.style.visibility = "initial";
|
||||
}
|
||||
|
||||
private _onImageError(ev) {
|
||||
ev.target.style.visibility = "hidden";
|
||||
}
|
||||
|
||||
private async _loadConfigEntry() {
|
||||
if (this._addon?.system_managed_config_entry) {
|
||||
try {
|
||||
const { config_entry } = await getConfigEntry(
|
||||
this.hass,
|
||||
this._addon.system_managed_config_entry
|
||||
);
|
||||
this._configEntry = config_entry;
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.icons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
--mdc-icon-size: 48px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.icons img {
|
||||
width: 48px;
|
||||
}
|
||||
.icons .primary {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.integration-icon {
|
||||
width: 24px;
|
||||
}
|
||||
ha-md-list-item {
|
||||
--md-list-item-leading-space: 4px;
|
||||
--md-list-item-trailing-space: 4px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"dialog-system-managed": HassioSystemManagedDialog;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
import { fireEvent } from "../../../../src/common/dom/fire_event";
|
||||
import type { HassioAddonDetails } from "../../../../src/data/hassio/addon";
|
||||
import type { Supervisor } from "../../../../src/data/supervisor/supervisor";
|
||||
|
||||
export interface SystemManagedDialogParams {
|
||||
addon: HassioAddonDetails;
|
||||
supervisor: Supervisor;
|
||||
}
|
||||
|
||||
export const showSystemManagedDialog = (
|
||||
element: HTMLElement,
|
||||
dialogParams: SystemManagedDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "dialog-system-managed",
|
||||
dialogImport: () => import("./dialog-system-managed"),
|
||||
dialogParams,
|
||||
});
|
||||
};
|
@ -101,6 +101,8 @@ export interface HassioAddonDetails extends HassioAddonInfo {
|
||||
slug: string;
|
||||
startup: AddonStartup;
|
||||
stdin: boolean;
|
||||
system_managed: boolean;
|
||||
system_managed_config_entry: string | null;
|
||||
translations: Record<string, AddonTranslations>;
|
||||
watchdog: null | boolean;
|
||||
webui: null | string;
|
||||
|
@ -8932,6 +8932,13 @@
|
||||
},
|
||||
"logs": {
|
||||
"get_logs": "Failed to get add-on logs, {error}"
|
||||
},
|
||||
"system_managed": {
|
||||
"badge": "System-managed",
|
||||
"title": "This add-on is managed by Home Assistant",
|
||||
"description": "Manually modifying this configuration may cause the add-on or integration to stop working properly.",
|
||||
"managed_by": "Managed by",
|
||||
"take_control": "Take control"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
@ -8955,6 +8962,7 @@
|
||||
"running_version": "You are currently running version {version}",
|
||||
"save": "[%key:ui::common::save%]",
|
||||
"close": "[%key:ui::common::close%]",
|
||||
"back": "[%key:ui::common::back%]",
|
||||
"menu": "[%key:ui::common::menu%]",
|
||||
"show": "[%key:ui::panel::config::updates::show%]",
|
||||
"show_more": "Show more information about this",
|
||||
|
Loading…
x
Reference in New Issue
Block a user