diff --git a/hassio/src/addon-view/config/hassio-addon-config.ts b/hassio/src/addon-view/config/hassio-addon-config.ts index beb8b6a74974..02d420f46f3d 100644 --- a/hassio/src/addon-view/config/hassio-addon-config.ts +++ b/hassio/src/addon-view/config/hassio-addon-config.ts @@ -1,4 +1,7 @@ import "@material/mwc-button"; +import { ActionDetail } from "@material/mwc-list"; +import "@material/mwc-list/mwc-list-item"; +import { mdiDotsVertical } from "@mdi/js"; import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea"; import { css, @@ -14,7 +17,9 @@ import { } from "lit-element"; import { fireEvent } from "../../../../src/common/dom/fire_event"; import "../../../../src/components/buttons/ha-progress-button"; +import "../../../../src/components/ha-button-menu"; import "../../../../src/components/ha-card"; +import "../../../../src/components/ha-form/ha-form"; import "../../../../src/components/ha-yaml-editor"; import type { HaYamlEditor } from "../../../../src/components/ha-yaml-editor"; import { @@ -29,35 +34,67 @@ import type { HomeAssistant } from "../../../../src/types"; import { suggestAddonRestart } from "../../dialogs/suggestAddonRestart"; import { hassioStyle } from "../../resources/hassio-style"; +const SUPPORTED_UI_TYPES = ["string", "select", "boolean", "integer", "float"]; + @customElement("hassio-addon-config") class HassioAddonConfig extends LitElement { - @property({ attribute: false }) public hass!: HomeAssistant; - @property({ attribute: false }) public addon!: HassioAddonDetails; - @internalProperty() private _error?: string; + @property({ attribute: false }) public hass!: HomeAssistant; @property({ type: Boolean }) private _configHasChanged = false; @property({ type: Boolean }) private _valid = true; - @query("ha-yaml-editor", true) private _editor!: HaYamlEditor; + @internalProperty() private _canShowSchema = false; + + @internalProperty() private _error?: string; + + @internalProperty() private _options?: Record; + + @internalProperty() private _yamlMode = false; + + @query("ha-yaml-editor") private _editor?: HaYamlEditor; protected render(): TemplateResult { return html`

${this.addon.name}

- + +
+

Configuration

+
+ + + + + + ${this._yamlMode ? "Edit in UI" : "Edit in YAML"} + + + Reset to defaults + + +
+
+
- + ${!this._yamlMode && this._canShowSchema && this.addon.schema + ? html`` + : html` `} ${this._error ? html`
${this._error}
` : ""} - ${this._valid ? "" : html`
Invalid YAML
`} + ${!this._yamlMode || + (this._canShowSchema && this.addon.schema) || + this._valid + ? "" + : html`
Invalid YAML
`}
- - Reset to defaults - !SUPPORTED_UI_TYPES.includes(entry.type) + ); + this._yamlMode = !this._canShowSchema; + } + protected updated(changedProperties: PropertyValues): void { - super.updated(changedProperties); if (changedProperties.has("addon")) { - this._editor.setValue(this.addon.options); + this._options = { ...this.addon.options }; + } + super.updated(changedProperties); + if ( + changedProperties.has("_yamlMode") || + changedProperties.has("_options") + ) { + if (this._yamlMode) { + const editor = this._editor; + if (editor) { + editor.setValue(this._options!); + } + } + } + } + + private _handleAction(ev: CustomEvent) { + switch (ev.detail.index) { + case 0: + this._yamlMode = !this._yamlMode; + break; + case 1: + this._resetTapped(ev); + break; } } private _configChanged(ev): void { - this._configHasChanged = true; - this._valid = ev.detail.isValid; + if (this.addon.schema && this._canShowSchema && !this._yamlMode) { + this._valid = true; + this._configHasChanged = true; + } else { + this._configHasChanged = true; + this._valid = ev.detail.isValid; + } + if (this._valid) { + this._options! = ev.detail.value; + } } private async _resetTapped(ev: CustomEvent): Promise { @@ -122,18 +197,12 @@ class HassioAddonConfig extends LitElement { const button = ev.currentTarget 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); + await setHassioAddonOption(this.hass, this.addon.slug, { + options: this._options!, + }); this._configHasChanged = false; const eventdata = { success: true, @@ -178,6 +247,29 @@ class HassioAddonConfig extends LitElement { .syntaxerror { color: var(--error-color); } + .card-menu { + float: right; + z-index: 3; + --mdc-theme-text-primary-on-background: var(--primary-text-color); + } + mwc-list-item[disabled] { + --mdc-theme-text-primary-on-background: var(--disabled-text-color); + } + .header { + display: flex; + justify-content: space-between; + } + .header h2 { + color: var(--ha-card-header-color, --primary-text-color); + font-family: var(--ha-card-header-font-family, inherit); + font-size: var(--ha-card-header-font-size, 24px); + letter-spacing: -0.012em; + line-height: 48px; + padding: 12px 16px 16px; + display: block; + margin-block: 0px; + font-weight: normal; + } `, ]; } diff --git a/src/data/hassio/addon.ts b/src/data/hassio/addon.ts index 963af90aa664..93a3e222ee15 100644 --- a/src/data/hassio/addon.ts +++ b/src/data/hassio/addon.ts @@ -1,3 +1,4 @@ +import { HaFormSchema } from "../../components/ha-form/ha-form"; import { HomeAssistant } from "../../types"; import { hassioApiResultExtractor, HassioResponse } from "./common"; @@ -62,7 +63,7 @@ export interface HassioAddonDetails extends HassioAddonInfo { privileged: any; protected: boolean; rating: "1-6"; - schema: Record; + schema: HaFormSchema[]; services_role: string[]; slug: string; startup: "initialize" | "system" | "services" | "application" | "once";