Update entity settings, combine basic editor with normal editor (#16297)

This commit is contained in:
Bram Kragten 2023-04-26 12:23:53 +02:00 committed by GitHub
parent 8c06712ab7
commit 19c9486351
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1267 additions and 1571 deletions

View File

@ -14,8 +14,9 @@ import { customElement, property, query } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { fireEvent } from "../common/dom/fire_event";
import { HomeAssistant } from "../types";
import "./ha-list-item";
import "./ha-icon-button";
import "./ha-list-item";
import "./ha-textfield";
import type { HaTextField } from "./ha-textfield";
registerStyles(

View File

@ -52,18 +52,17 @@ export class HaSettingsRow extends LitElement {
white-space: nowrap;
}
.body > .secondary {
font-family: var(--paper-font-body1_-_font-family);
-webkit-font-smoothing: var(
--paper-font-body1_-_-webkit-font-smoothing
);
font-size: var(--paper-font-body1_-_font-size);
font-weight: var(--paper-font-body1_-_font-weight);
line-height: var(--paper-font-body1_-_line-height);
color: var(
--paper-item-body-secondary-color,
var(--secondary-text-color)
display: block;
padding-top: 4px;
font-family: var(
--mdc-typography-body2-font-family,
var(--mdc-typography-font-family, Roboto, sans-serif)
);
-webkit-font-smoothing: antialiased;
font-size: var(--mdc-typography-body2-font-size, 0.875rem);
font-weight: var(--mdc-typography-body2-font-weight, 400);
line-height: normal;
color: var(--secondary-text-color);
}
.body[two-line] {
min-height: calc(

View File

@ -3,8 +3,8 @@ import {
CSSResultGroup,
html,
LitElement,
PropertyValues,
nothing,
PropertyValues,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { isComponentLoaded } from "../../../../../common/config/is_component_loaded";
@ -28,8 +28,9 @@ import "../../../helpers/forms/ha-input_select-form";
import "../../../helpers/forms/ha-input_text-form";
import "../../../helpers/forms/ha-schedule-form";
import "../../../helpers/forms/ha-timer-form";
import "../../entity-registry-basic-editor";
import type { HaEntityRegistryBasicEditor } from "../../entity-registry-basic-editor";
import "../../../voice-assistants/entity-voice-settings";
import "../../entity-registry-settings-editor";
import type { EntityRegistrySettingsEditor } from "../../entity-registry-settings-editor";
@customElement("entity-settings-helper-tab")
export class EntityRegistrySettingsHelper extends LitElement {
@ -45,8 +46,8 @@ export class EntityRegistrySettingsHelper extends LitElement {
@state() private _componentLoaded?: boolean;
@query("ha-registry-basic-editor")
private _registryEditor?: HaEntityRegistryBasicEditor;
@query("entity-registry-settings-editor")
private _registryEditor?: EntityRegistrySettingsEditor;
protected firstUpdated(changedProperties: PropertyValues) {
super.firstUpdated(changedProperties);
@ -75,7 +76,9 @@ export class EntityRegistrySettingsHelper extends LitElement {
const stateObj = this.hass.states[this.entry.entity_id];
return html`
<div class="form">
${this._error ? html` <div class="error">${this._error}</div> ` : ""}
${this._error
? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
: ""}
${!this._componentLoaded
? this.hass.localize(
"ui.dialogs.helper_settings.platform_not_loaded",
@ -93,10 +96,14 @@ export class EntityRegistrySettingsHelper extends LitElement {
})}
</span>
`}
<ha-registry-basic-editor
<entity-registry-settings-editor
.hass=${this.hass}
.entry=${this.entry}
></ha-registry-basic-editor>
.disabled=${this._submitting}
@change=${this._entityRegistryChanged}
hideName
hideIcon
></entity-registry-settings-editor>
</div>
<div class="buttons">
<mwc-button
@ -117,6 +124,10 @@ export class EntityRegistrySettingsHelper extends LitElement {
`;
}
private _entityRegistryChanged() {
this._error = undefined;
}
private _valueChanged(ev: CustomEvent): void {
this._error = undefined;
this._item = ev.detail.value;
@ -137,7 +148,7 @@ export class EntityRegistrySettingsHelper extends LitElement {
this._item
);
}
await this._registryEditor?.updateEntry();
await this._registryEditor!.updateEntry();
fireEvent(this, "close-dialog");
} catch (err: any) {
this._error = err.message || "Unknown error";

View File

@ -1,376 +0,0 @@
import "@material/mwc-formfield/mwc-formfield";
import "@material/mwc-list/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiPencil } from "@mdi/js";
import { UnsubscribeFunc } from "home-assistant-js-websocket";
import { css, html, LitElement, PropertyValues, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { stringCompare } from "../../../common/string/compare";
import "../../../components/ha-area-picker";
import "../../../components/ha-expansion-panel";
import "../../../components/ha-radio";
import "../../../components/ha-switch";
import "../../../components/ha-textfield";
import {
DeviceRegistryEntry,
subscribeDeviceRegistry,
} from "../../../data/device_registry";
import {
EntityRegistryEntry,
EntityRegistryEntryUpdateParams,
ExtEntityRegistryEntry,
updateEntityRegistryEntry,
} from "../../../data/entity_registry";
import { showAliasesDialog } from "../../../dialogs/aliases/show-dialog-aliases";
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import type { HomeAssistant } from "../../../types";
@customElement("ha-registry-basic-editor")
export class HaEntityRegistryBasicEditor extends SubscribeMixin(LitElement) {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public entry!: ExtEntityRegistryEntry;
@state() private _origEntityId!: string;
@state() private _entityId!: string;
@state() private _areaId?: string | null;
@state() private _disabledBy!: EntityRegistryEntry["disabled_by"];
@state() private _hiddenBy!: string | null;
private _deviceLookup?: Record<string, DeviceRegistryEntry>;
@state() private _device?: DeviceRegistryEntry;
@state() private _submitting = false;
private _handleAliasesClicked(ev: CustomEvent) {
if (ev.detail.index !== 0) return;
const stateObj = this.hass.states[this.entry.entity_id];
const name =
(stateObj && computeStateName(stateObj)) || this.entry.entity_id;
showAliasesDialog(this, {
name,
aliases: this.entry!.aliases,
updateAliases: async (aliases: string[]) => {
const result = await updateEntityRegistryEntry(
this.hass,
this.entry.entity_id,
{ aliases }
);
fireEvent(this, "entity-entry-updated", result.entity_entry);
},
});
}
public async updateEntry(): Promise<void> {
this._submitting = true;
const params: Partial<EntityRegistryEntryUpdateParams> = {
new_entity_id: this._entityId.trim(),
area_id: this._areaId || null,
};
if (
this.entry.disabled_by !== this._disabledBy &&
(this._disabledBy === null || this._disabledBy === "user")
) {
params.disabled_by = this._disabledBy;
}
if (
this.entry.hidden_by !== this._hiddenBy &&
(this._hiddenBy === null || this._hiddenBy === "user")
) {
params.hidden_by = this._hiddenBy;
}
try {
const result = await updateEntityRegistryEntry(
this.hass!,
this._origEntityId,
params
);
if (result.require_restart) {
showAlertDialog(this, {
text: this.hass.localize(
"ui.dialogs.entity_registry.editor.enabled_restart_confirm"
),
});
}
if (result.reload_delay) {
showAlertDialog(this, {
text: this.hass.localize(
"ui.dialogs.entity_registry.editor.enabled_delay_confirm",
"delay",
result.reload_delay
),
});
}
} finally {
this._submitting = false;
}
}
public hassSubscribe(): UnsubscribeFunc[] {
return [
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
this._deviceLookup = {};
for (const device of devices) {
this._deviceLookup[device.id] = device;
}
if (!this._device && this.entry.device_id) {
this._device = this._deviceLookup[this.entry.device_id];
}
}),
];
}
protected updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
if (!changedProperties.has("entry")) {
return;
}
if (this.entry) {
this._origEntityId = this.entry.entity_id;
this._entityId = this.entry.entity_id;
this._disabledBy = this.entry.disabled_by;
this._hiddenBy = this.entry.hidden_by;
this._areaId = this.entry.area_id;
this._device =
this.entry.device_id && this._deviceLookup
? this._deviceLookup[this.entry.device_id]
: undefined;
}
}
protected render() {
if (
!this.hass ||
!this.entry ||
this.entry.entity_id !== this._origEntityId
) {
return nothing;
}
const invalidDomainUpdate =
computeDomain(this._entityId.trim()) !==
computeDomain(this.entry.entity_id);
return html`
<ha-textfield
error-message="Domain needs to stay the same"
.value=${this._entityId}
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.entity_id"
)}
.invalid=${invalidDomainUpdate}
.disabled=${this._submitting}
@input=${this._entityIdChanged}
></ha-textfield>
<ha-area-picker
.hass=${this.hass}
.value=${this._areaId || undefined}
.placeholder=${this._device?.area_id || undefined}
@value-changed=${this._areaPicked}
></ha-area-picker>
<ha-expansion-panel
.header=${this.hass.localize(
"ui.dialogs.entity_registry.editor.advanced"
)}
outlined
>
<div class="label">
${this.hass.localize(
"ui.dialogs.entity_registry.editor.entity_status"
)}:
</div>
<div class="secondary">
${this._disabledBy && this._disabledBy !== "user"
? this.hass.localize(
"ui.dialogs.entity_registry.editor.enabled_cause",
"cause",
this.hass.localize(
`config_entry.disabled_by.${this._disabledBy}`
)
)
: ""}
</div>
<div class="row">
<mwc-formfield
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.enabled_label"
)}
>
<ha-radio
name="hiddendisabled"
value="enabled"
.checked=${!this._hiddenBy && !this._disabledBy}
.disabled=${!!this._device?.disabled_by ||
(this._disabledBy !== null &&
!(
this._disabledBy === "user" ||
this._disabledBy === "integration"
))}
@change=${this._viewStatusChanged}
></ha-radio>
</mwc-formfield>
<mwc-formfield
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.hidden_label"
)}
>
<ha-radio
name="hiddendisabled"
value="hidden"
.checked=${this._hiddenBy !== null}
.disabled=${!!this._device?.disabled_by ||
(this._disabledBy !== null &&
!(
this._disabledBy === "user" ||
this._disabledBy === "integration"
))}
@change=${this._viewStatusChanged}
></ha-radio>
</mwc-formfield>
<mwc-formfield
.label=${this.hass.localize(
"ui.dialogs.entity_registry.editor.disabled_label"
)}
>
<ha-radio
name="hiddendisabled"
value="disabled"
.checked=${this._disabledBy !== null}
.disabled=${!!this._device?.disabled_by ||
(this._disabledBy !== null &&
!(
this._disabledBy === "user" ||
this._disabledBy === "integration"
))}
@change=${this._viewStatusChanged}
></ha-radio>
</mwc-formfield>
</div>
${this._disabledBy !== null
? html`
<div class="secondary">
${this.hass.localize(
"ui.dialogs.entity_registry.editor.enabled_description"
)}
</div>
`
: this._hiddenBy !== null
? html`
<div class="secondary">
${this.hass.localize(
"ui.dialogs.entity_registry.editor.hidden_description"
)}
</div>
`
: ""}
<div class="label">
${this.hass.localize(
"ui.dialogs.entity_registry.editor.aliases_section"
)}
</div>
<mwc-list class="aliases" @action=${this._handleAliasesClicked}>
<mwc-list-item .twoline=${this.entry.aliases.length > 0} hasMeta>
<span>
${this.entry.aliases.length > 0
? this.hass.localize(
"ui.dialogs.entity_registry.editor.configured_aliases",
{ count: this.entry.aliases.length }
)
: this.hass.localize(
"ui.dialogs.entity_registry.editor.no_aliases"
)}
</span>
<span slot="secondary">
${[...this.entry.aliases]
.sort((a, b) => stringCompare(a, b, this.hass.locale.language))
.join(", ")}
</span>
<ha-svg-icon slot="meta" .path=${mdiPencil}></ha-svg-icon>
</mwc-list-item>
</mwc-list>
<div class="secondary">
${this.hass.localize(
"ui.dialogs.entity_registry.editor.aliases_description"
)}
</div>
</ha-expansion-panel>
`;
}
private _areaPicked(ev: CustomEvent) {
this._areaId = ev.detail.value;
}
private _entityIdChanged(ev): void {
this._entityId = ev.target.value;
}
private _viewStatusChanged(ev: CustomEvent): void {
switch ((ev.target as any).value) {
case "enabled":
this._disabledBy = null;
this._hiddenBy = null;
break;
case "disabled":
this._disabledBy = "user";
this._hiddenBy = null;
break;
case "hidden":
this._hiddenBy = "user";
this._disabledBy = null;
break;
}
}
static get styles() {
return css`
ha-switch {
margin-right: 16px;
}
.row {
margin-top: 8px;
color: var(--primary-text-color);
display: flex;
align-items: center;
}
.secondary {
color: var(--secondary-text-color);
}
ha-textfield {
display: block;
margin-bottom: 8px;
}
ha-expansion-panel {
margin-top: 8px;
}
.label {
margin-top: 16px;
}
.aliases {
border-radius: 4px;
margin-top: 4px;
margin-bottom: 4px;
--mdc-icon-button-size: 24px;
overflow: hidden;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-registry-basic-editor": HaEntityRegistryBasicEditor;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1041,7 +1041,7 @@
"enabled_label": "Enabled",
"disabled_label": "Disabled",
"enabled_cause": "Cannot change status. Disabled by {cause}.",
"hidden_label": "Hidden",
"visible_label": "Visible",
"hidden_cause": "Hidden by {cause}.",
"device_disabled": "The device of this entity is disabled.",
"entity_disabled": "This entity is disabled.",
@ -1056,12 +1056,11 @@
"confirm_delete": "Are you sure you want to delete this entity?",
"update": "Update",
"note": "Note: This might not work yet with all integrations.",
"advanced": "Advanced settings",
"area": "Set entity area only",
"area_note": "By default the entities of a device are in the same area as the device. If you change the area of this entity, it will no longer follow the area of the device.",
"follow_device_area": "Follow device area",
"change_device_area": "Change device area",
"use_device_area": "Use device area",
"change_device_settings": "You can {link} in the device settings",
"change_device_area_link": "change the device area",
"configure_state": "{integration} options",
"configure_state_secondary": "Specific options for {integration}",
"stream": {
"preload_stream": "Preload camera stream",
"preload_stream_description": "This keeps the camera stream open in the background so it shows quicker. Warning! This is device intensive.",
@ -1076,10 +1075,7 @@
"stream_orientation_7": "Rotate right and flip",
"stream_orientation_8": "Rotate right"
},
"aliases_section": "Aliases",
"no_aliases": "No configured aliases",
"configured_aliases": "{count} configured {count, plural,\n one {alias}\n other {aliases}\n}",
"aliases_description": "Aliases are alternative names used in voice assistants to refer to this entity."
"no_aliases": "Configure aliases and expose settings for voice assistants"
}
},
"voice-settings": {