mirror of
https://github.com/home-assistant/frontend.git
synced 2026-06-12 11:22:58 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 10bf185d2f |
@@ -10,13 +10,21 @@ import "../../components/ha-button";
|
||||
import type { HaSwitch } from "../../components/ha-switch";
|
||||
import type { ConfigEntryMutableParams } from "../../data/config_entries";
|
||||
import { updateConfigEntry } from "../../data/config_entries";
|
||||
import { DirtyStateProviderMixin } from "../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyleDialog } from "../../resources/styles";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
import { showAlertDialog } from "../generic/show-dialog-box";
|
||||
import type { ConfigEntrySystemOptionsDialogParams } from "./show-dialog-config-entry-system-options";
|
||||
|
||||
interface SystemOptionsState {
|
||||
disableNewEntities: boolean;
|
||||
disablePolling: boolean;
|
||||
}
|
||||
|
||||
@customElement("dialog-config-entry-system-options")
|
||||
class DialogConfigEntrySystemOptions extends LitElement {
|
||||
class DialogConfigEntrySystemOptions extends DirtyStateProviderMixin<SystemOptionsState>()(
|
||||
LitElement
|
||||
) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _disableNewEntities!: boolean;
|
||||
@@ -38,6 +46,13 @@ class DialogConfigEntrySystemOptions extends LitElement {
|
||||
this._error = undefined;
|
||||
this._disableNewEntities = params.entry.pref_disable_new_entities;
|
||||
this._disablePolling = params.entry.pref_disable_polling;
|
||||
this._initDirtyTracking(
|
||||
{ type: "shallow" },
|
||||
{
|
||||
disableNewEntities: this._disableNewEntities,
|
||||
disablePolling: this._disablePolling,
|
||||
}
|
||||
);
|
||||
this._open = true;
|
||||
}
|
||||
|
||||
@@ -68,7 +83,7 @@ class DialogConfigEntrySystemOptions extends LitElement {
|
||||
) || this._params.entry.domain,
|
||||
}
|
||||
)}
|
||||
prevent-scrim-close
|
||||
.preventScrimClose=${this.isDirtyState}
|
||||
@closed=${this._dialogClosed}
|
||||
>
|
||||
${this._error ? html` <div class="error">${this._error}</div> ` : ""}
|
||||
@@ -135,7 +150,7 @@ class DialogConfigEntrySystemOptions extends LitElement {
|
||||
<ha-button
|
||||
slot="primaryAction"
|
||||
@click=${this._updateEntry}
|
||||
.disabled=${this._submitting}
|
||||
.disabled=${this._submitting || !this.isDirtyState}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.dialogs.config_entry_system_options.update"
|
||||
@@ -149,11 +164,19 @@ class DialogConfigEntrySystemOptions extends LitElement {
|
||||
private _disableNewEntitiesChanged(ev: Event): void {
|
||||
this._error = undefined;
|
||||
this._disableNewEntities = !(ev.target as HaSwitch).checked;
|
||||
this._updateDirtyState({
|
||||
disableNewEntities: this._disableNewEntities,
|
||||
disablePolling: this._disablePolling,
|
||||
});
|
||||
}
|
||||
|
||||
private _disablePollingChanged(ev: Event): void {
|
||||
this._error = undefined;
|
||||
this._disablePolling = !(ev.target as HaSwitch).checked;
|
||||
this._updateDirtyState({
|
||||
disableNewEntities: this._disableNewEntities,
|
||||
disablePolling: this._disablePolling,
|
||||
});
|
||||
}
|
||||
|
||||
private async _updateEntry(): Promise<void> {
|
||||
|
||||
@@ -23,18 +23,28 @@ import {
|
||||
} from "../../../data/application_credential";
|
||||
import type { IntegrationManifest } from "../../../data/integration";
|
||||
import { domainToName } from "../../../data/integration";
|
||||
import { DirtyStateProviderMixin } from "../../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { documentationUrl } from "../../../util/documentation-url";
|
||||
import type { AddApplicationCredentialDialogParams } from "./show-dialog-add-application-credential";
|
||||
|
||||
interface CredentialFormState {
|
||||
domain: string;
|
||||
name: string;
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
}
|
||||
|
||||
interface Domain {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
@customElement("dialog-add-application-credential")
|
||||
export class DialogAddApplicationCredential extends LitElement {
|
||||
export class DialogAddApplicationCredential extends DirtyStateProviderMixin<CredentialFormState>()(
|
||||
LitElement
|
||||
) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _loading = false;
|
||||
@@ -76,6 +86,7 @@ export class DialogAddApplicationCredential extends LitElement {
|
||||
this._error = undefined;
|
||||
this._loading = false;
|
||||
this._open = true;
|
||||
this._initDirtyTracking({ type: "shallow" }, this._currentState());
|
||||
this._fetchConfig();
|
||||
}
|
||||
|
||||
@@ -100,10 +111,7 @@ export class DialogAddApplicationCredential extends LitElement {
|
||||
<ha-dialog
|
||||
.open=${this._open}
|
||||
@closed=${this._abortDialog}
|
||||
.preventScrimClose=${!!this._domain ||
|
||||
!!this._name ||
|
||||
!!this._clientId ||
|
||||
!!this._clientSecret}
|
||||
.preventScrimClose=${this.isDirtyState}
|
||||
.headerTitle=${this.hass.localize(
|
||||
"ui.panel.config.application_credentials.editor.caption"
|
||||
)}
|
||||
@@ -284,6 +292,7 @@ export class DialogAddApplicationCredential extends LitElement {
|
||||
ev.stopPropagation();
|
||||
this._domain = ev.detail.value;
|
||||
this._updateDescription();
|
||||
this._updateDirtyState(this._currentState());
|
||||
}
|
||||
|
||||
private async _updateDescription() {
|
||||
@@ -307,6 +316,16 @@ export class DialogAddApplicationCredential extends LitElement {
|
||||
const name = (ev.target as any).name;
|
||||
const value = (ev.target as any).value;
|
||||
this[`_${name}`] = value;
|
||||
this._updateDirtyState(this._currentState());
|
||||
}
|
||||
|
||||
private _currentState(): CredentialFormState {
|
||||
return {
|
||||
domain: this._domain || "",
|
||||
name: this._name || "",
|
||||
clientId: this._clientId || "",
|
||||
clientSecret: this._clientSecret || "",
|
||||
};
|
||||
}
|
||||
|
||||
private _abortDialog() {
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
import { extractApiErrorMessage } from "../../../../../data/hassio/common";
|
||||
import type { ObjectSelector, Selector } from "../../../../../data/selector";
|
||||
import { showConfirmationDialog } from "../../../../../dialogs/generic/show-dialog-box";
|
||||
import { DirtyStateProviderMixin } from "../../../../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../../types";
|
||||
import { supervisorAppsStyle } from "../../resources/supervisor-apps-style";
|
||||
@@ -56,15 +57,15 @@ const ADDON_YAML_SCHEMA = DEFAULT_SCHEMA.extend([
|
||||
const MASKED_FIELDS = ["password", "secret", "token"];
|
||||
|
||||
@customElement("supervisor-app-config")
|
||||
class SupervisorAppConfig extends LitElement {
|
||||
class SupervisorAppConfig extends DirtyStateProviderMixin<
|
||||
Record<string, unknown>
|
||||
>()(LitElement) {
|
||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@state() private _configHasChanged = false;
|
||||
|
||||
@state() private _valid = true;
|
||||
|
||||
@state() private _canShowSchema = false;
|
||||
@@ -351,9 +352,7 @@ class SupervisorAppConfig extends LitElement {
|
||||
<div class="card-actions right">
|
||||
<ha-progress-button
|
||||
@click=${this._saveTapped}
|
||||
.disabled=${this.disabled ||
|
||||
!this._configHasChanged ||
|
||||
!this._valid}
|
||||
.disabled=${this.disabled || !this.isDirtyState || !this._valid}
|
||||
>
|
||||
${this.hass.localize("ui.common.save")}
|
||||
</ha-progress-button>
|
||||
@@ -377,6 +376,7 @@ class SupervisorAppConfig extends LitElement {
|
||||
protected updated(changedProperties: PropertyValues): void {
|
||||
if (changedProperties.has("addon")) {
|
||||
this._options = { ...this.addon.options };
|
||||
this._initDirtyTracking({ type: "deep" }, this.addon.options);
|
||||
}
|
||||
super.updated(changedProperties);
|
||||
if (
|
||||
@@ -415,11 +415,13 @@ class SupervisorAppConfig extends LitElement {
|
||||
private _configChanged(ev): void {
|
||||
if (this.addon.schema && this._canShowSchema && !this._yamlMode) {
|
||||
this._valid = true;
|
||||
this._configHasChanged = true;
|
||||
this._options = ev.detail.value;
|
||||
this._updateDirtyState(ev.detail.value);
|
||||
} else {
|
||||
this._configHasChanged = true;
|
||||
this._valid = ev.detail.isValid;
|
||||
if (ev.detail.isValid) {
|
||||
this._updateDirtyState(ev.detail.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,7 +452,7 @@ class SupervisorAppConfig extends LitElement {
|
||||
};
|
||||
try {
|
||||
await setHassioAddonOption(this.hass.callWS, this.addon.slug, data);
|
||||
this._configHasChanged = false;
|
||||
this._markDirtyStateClean();
|
||||
const eventdata = {
|
||||
success: true,
|
||||
response: undefined,
|
||||
@@ -469,7 +471,7 @@ class SupervisorAppConfig extends LitElement {
|
||||
}
|
||||
|
||||
private async _saveTapped(ev: CustomEvent): Promise<void> {
|
||||
if (this.disabled || !this._configHasChanged || !this._valid) {
|
||||
if (this.disabled || !this.isDirtyState || !this._valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -499,7 +501,7 @@ class SupervisorAppConfig extends LitElement {
|
||||
options,
|
||||
});
|
||||
|
||||
this._configHasChanged = false;
|
||||
this._markDirtyStateClean();
|
||||
if (this.addon?.state === "started") {
|
||||
await suggestSupervisorAppRestart(this, this.hass, this.addon);
|
||||
}
|
||||
|
||||
@@ -15,13 +15,16 @@ import type {
|
||||
} from "../../../../../data/hassio/addon";
|
||||
import { setHassioAddonOption } from "../../../../../data/hassio/addon";
|
||||
import { extractApiErrorMessage } from "../../../../../data/hassio/common";
|
||||
import { DirtyStateProviderMixin } from "../../../../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../../types";
|
||||
import { supervisorAppsStyle } from "../../resources/supervisor-apps-style";
|
||||
import { suggestSupervisorAppRestart } from "../dialogs/suggestSupervisorAppRestart";
|
||||
|
||||
@customElement("supervisor-app-network")
|
||||
class SupervisorAppNetwork extends LitElement {
|
||||
class SupervisorAppNetwork extends DirtyStateProviderMixin<
|
||||
Record<string, number | null>
|
||||
>()(LitElement) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public addon!: HassioAddonDetails;
|
||||
@@ -30,19 +33,19 @@ class SupervisorAppNetwork extends LitElement {
|
||||
|
||||
@state() private _showOptional = false;
|
||||
|
||||
@state() private _configHasChanged = false;
|
||||
|
||||
@state() private _error?: string;
|
||||
|
||||
@state() private _config?: Record<string, any>;
|
||||
@state() private _config?: Record<string, number | null>;
|
||||
|
||||
protected render() {
|
||||
if (!this._config) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const hasHiddenOptions = Object.keys(this._config).find(
|
||||
(entry) => this._config![entry] === null
|
||||
const config = this._config;
|
||||
|
||||
const hasHiddenOptions = Object.keys(config).find(
|
||||
(entry) => config[entry] === null
|
||||
);
|
||||
|
||||
return html`
|
||||
@@ -98,7 +101,7 @@ class SupervisorAppNetwork extends LitElement {
|
||||
</ha-progress-button>
|
||||
<ha-progress-button
|
||||
@click=${this._saveTapped}
|
||||
.disabled=${!this._configHasChanged || this.disabled}
|
||||
.disabled=${!this.isDirtyState || this.disabled}
|
||||
>
|
||||
${this.hass.localize("ui.common.save")}
|
||||
</ha-progress-button>
|
||||
@@ -115,7 +118,10 @@ class SupervisorAppNetwork extends LitElement {
|
||||
}
|
||||
|
||||
private _createSchema = memoizeOne(
|
||||
(config: Record<string, number>, showOptional: boolean): HaFormSchema[] =>
|
||||
(
|
||||
config: Record<string, number | null>,
|
||||
showOptional: boolean
|
||||
): HaFormSchema[] =>
|
||||
(showOptional
|
||||
? Object.keys(config)
|
||||
: Object.keys(config).filter((entry) => config[entry] !== null)
|
||||
@@ -141,12 +147,14 @@ class SupervisorAppNetwork extends LitElement {
|
||||
item.name;
|
||||
|
||||
private _setNetworkConfig(): void {
|
||||
this._config = this.addon.network || {};
|
||||
const config = this.addon.network || {};
|
||||
this._config = config;
|
||||
this._initDirtyTracking({ type: "shallow" }, config);
|
||||
}
|
||||
|
||||
private async _configChanged(ev: CustomEvent): Promise<void> {
|
||||
this._configHasChanged = true;
|
||||
private _configChanged(ev: CustomEvent): void {
|
||||
this._config = ev.detail.value;
|
||||
this._updateDirtyState(ev.detail.value);
|
||||
}
|
||||
|
||||
private async _resetTapped(ev: CustomEvent): Promise<void> {
|
||||
@@ -161,7 +169,7 @@ class SupervisorAppNetwork extends LitElement {
|
||||
|
||||
try {
|
||||
await setHassioAddonOption(this.hass.callWS, this.addon.slug, data);
|
||||
this._configHasChanged = false;
|
||||
this._markDirtyStateClean();
|
||||
const eventdata = {
|
||||
success: true,
|
||||
response: undefined,
|
||||
@@ -188,14 +196,14 @@ class SupervisorAppNetwork extends LitElement {
|
||||
}
|
||||
|
||||
private async _saveTapped(ev: CustomEvent): Promise<void> {
|
||||
if (!this._configHasChanged || this.disabled) {
|
||||
if (!this.isDirtyState || this.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const button = ev.currentTarget as any;
|
||||
|
||||
this._error = undefined;
|
||||
const networkconfiguration = {};
|
||||
const networkconfiguration: Record<string, number | null> = {};
|
||||
Object.entries(this._config!).forEach(([key, value]) => {
|
||||
networkconfiguration[key] = value ?? null;
|
||||
});
|
||||
@@ -206,7 +214,7 @@ class SupervisorAppNetwork extends LitElement {
|
||||
|
||||
try {
|
||||
await setHassioAddonOption(this.hass.callWS, this.addon.slug, data);
|
||||
this._configHasChanged = false;
|
||||
this._markDirtyStateClean();
|
||||
const eventdata = {
|
||||
success: true,
|
||||
response: undefined,
|
||||
|
||||
@@ -16,6 +16,7 @@ import type {
|
||||
AssistPipelineMutableParams,
|
||||
} from "../../../data/assist_pipeline";
|
||||
import { fetchAssistPipelineLanguages } from "../../../data/assist_pipeline";
|
||||
import { DirtyStateProviderMixin } from "../../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import "./assist-pipeline-detail/assist-pipeline-detail-config";
|
||||
@@ -28,7 +29,9 @@ import type { VoiceAssistantPipelineDetailsDialogParams } from "./show-dialog-vo
|
||||
import type { HaDropdownSelectEvent } from "../../../components/ha-dropdown";
|
||||
|
||||
@customElement("dialog-voice-assistant-pipeline-detail")
|
||||
export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
export class DialogVoiceAssistantPipelineDetail extends DirtyStateProviderMixin<
|
||||
Partial<AssistPipeline>
|
||||
>()(LitElement) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _params?: VoiceAssistantPipelineDetailsDialogParams;
|
||||
@@ -62,6 +65,7 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
|
||||
this._hideWakeWord =
|
||||
this._params.hideWakeWord || !this._data.wake_word_entity;
|
||||
this._initDirtyTracking({ type: "deep" }, this._data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -98,6 +102,7 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
stt_engine: this._params.pipeline?.stt_engine || sstDefault,
|
||||
tts_engine: this._params.pipeline?.tts_engine || ttsDefault,
|
||||
};
|
||||
this._initDirtyTracking({ type: "deep" }, this._data);
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
@@ -145,7 +150,7 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
<ha-dialog
|
||||
.open=${this._open}
|
||||
header-title=${title}
|
||||
prevent-scrim-close
|
||||
.preventScrimClose=${this.isDirtyState}
|
||||
@closed=${this._dialogClosed}
|
||||
>
|
||||
${!this._hideWakeWord ||
|
||||
@@ -266,6 +271,7 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
|
||||
value[key] = ev.detail.value[key];
|
||||
});
|
||||
this._data = { ...this._data, ...value };
|
||||
this._updateDirtyState(this._data);
|
||||
}
|
||||
|
||||
private async _updatePipeline() {
|
||||
|
||||
@@ -8,6 +8,7 @@ import "../../../components/ha-dialog";
|
||||
import "../../../components/ha-form/ha-form";
|
||||
import "../../../components/ha-button";
|
||||
import type { HomeZoneMutableParams } from "../../../data/zone";
|
||||
import { DirtyStateProviderMixin } from "../../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { HomeZoneDetailDialogParams } from "./show-dialog-home-zone-detail";
|
||||
@@ -21,7 +22,9 @@ const SCHEMA = [
|
||||
];
|
||||
|
||||
@customElement("dialog-home-zone-detail")
|
||||
class DialogHomeZoneDetail extends LitElement {
|
||||
class DialogHomeZoneDetail extends DirtyStateProviderMixin<HomeZoneMutableParams>()(
|
||||
LitElement
|
||||
) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _error?: Record<string, string>;
|
||||
@@ -43,6 +46,7 @@ class DialogHomeZoneDetail extends LitElement {
|
||||
longitude: this.hass.config.longitude,
|
||||
radius: this.hass.config.radius,
|
||||
};
|
||||
this._initDirtyTracking({ type: "deep" }, this._data);
|
||||
this._open = true;
|
||||
}
|
||||
|
||||
@@ -71,7 +75,7 @@ class DialogHomeZoneDetail extends LitElement {
|
||||
header-title=${this.hass!.localize("ui.common.edit_item", {
|
||||
name: this._data.name,
|
||||
})}
|
||||
prevent-scrim-close
|
||||
.preventScrimClose=${this.isDirtyState}
|
||||
@closed=${this._dialogClosed}
|
||||
>
|
||||
<ha-form
|
||||
@@ -120,6 +124,7 @@ class DialogHomeZoneDetail extends LitElement {
|
||||
value.radius = value.location.radius;
|
||||
delete value.location;
|
||||
this._data = value;
|
||||
this._updateDirtyState(value);
|
||||
}
|
||||
|
||||
private _computeLabel = (): string => "";
|
||||
|
||||
@@ -11,12 +11,15 @@ import "../../../components/ha-button";
|
||||
import type { SchemaUnion } from "../../../components/ha-form/types";
|
||||
import type { ZoneMutableParams } from "../../../data/zone";
|
||||
import { getZoneEditorInitData } from "../../../data/zone";
|
||||
import { DirtyStateProviderMixin } from "../../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { ZoneDetailDialogParams } from "./show-dialog-zone-detail";
|
||||
|
||||
@customElement("dialog-zone-detail")
|
||||
class DialogZoneDetail extends LitElement {
|
||||
class DialogZoneDetail extends DirtyStateProviderMixin<ZoneMutableParams>()(
|
||||
LitElement
|
||||
) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _error?: Record<string, string>;
|
||||
@@ -53,6 +56,7 @@ class DialogZoneDetail extends LitElement {
|
||||
radius: 100,
|
||||
};
|
||||
}
|
||||
this._initDirtyTracking({ type: "deep" }, this._data);
|
||||
this._open = true;
|
||||
}
|
||||
|
||||
@@ -93,7 +97,7 @@ class DialogZoneDetail extends LitElement {
|
||||
name: this._params.entry.name,
|
||||
})
|
||||
: this.hass!.localize("ui.panel.config.zone.detail.new_zone")}
|
||||
prevent-scrim-close
|
||||
.preventScrimClose=${this.isDirtyState}
|
||||
@closed=${this._dialogClosed}
|
||||
>
|
||||
<ha-form
|
||||
@@ -189,6 +193,7 @@ class DialogZoneDetail extends LitElement {
|
||||
delete value.icon;
|
||||
}
|
||||
this._data = value;
|
||||
this._updateDirtyState(value);
|
||||
}
|
||||
|
||||
private _computeLabel = (
|
||||
|
||||
Reference in New Issue
Block a user