Show number of exposed entities (#16321)

This commit is contained in:
Bram Kragten 2023-04-26 16:23:23 +02:00 committed by GitHub
parent ff4c01e15c
commit 8cf8c41698
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 45 deletions

View File

@ -92,7 +92,7 @@ export class HaDialog extends DialogBase {
padding: 24px 24px 0 24px;
}
.mdc-dialog__actions {
padding: 0 24px 24px 24px;
padding: 12px 24px 12px 24px;
}
.mdc-dialog__title::before {
display: block;

View File

@ -90,6 +90,9 @@ export interface EntityRegistryOptions {
number?: NumberEntityOptions;
sensor?: SensorEntityOptions;
weather?: WeatherEntityOptions;
conversation?: Record<string, unknown>;
"cloud.alexa"?: Record<string, unknown>;
"cloud.google_assistant"?: Record<string, unknown>;
}
export interface EntityRegistryEntryUpdateParams {

View File

@ -2,36 +2,40 @@ import "@material/mwc-list/mwc-list";
import { mdiHelpCircle, mdiPlus, mdiStar } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import { property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { formatLanguageCode } from "../../../common/language/format_language";
import "../../../components/ha-alert";
import "../../../components/ha-button";
import "../../../components/ha-card";
import "../../../components/ha-icon-next";
import "../../../components/ha-svg-icon";
import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon";
import "../../../components/ha-switch";
import "../../../components/ha-button";
import {
AssistPipeline,
createAssistPipeline,
deleteAssistPipeline,
listAssistPipelines,
updateAssistPipeline,
AssistPipeline,
setAssistPipelinePreferred,
updateAssistPipeline,
} from "../../../data/assist_pipeline";
import { CloudStatus } from "../../../data/cloud";
import { ExtEntityRegistryEntry } from "../../../data/entity_registry";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../types";
import { showVoiceAssistantPipelineDetailDialog } from "./show-dialog-voice-assistant-pipeline-detail";
import { brandsUrl } from "../../../util/brands-url";
import { formatLanguageCode } from "../../../common/language/format_language";
import { CloudStatusLoggedIn } from "../../../data/cloud";
import { showVoiceAssistantPipelineDetailDialog } from "./show-dialog-voice-assistant-pipeline-detail";
export class AssistPref extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() private extEntities?: Record<string, ExtEntityRegistryEntry>;
@state() private _pipelines: AssistPipeline[] = [];
@state() private _preferred: string | null = null;
@property() public cloudStatus?: CloudStatusLoggedIn;
@property() public cloudStatus?: CloudStatus;
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
@ -42,6 +46,13 @@ export class AssistPref extends LitElement {
});
}
private _exposedEntities = memoizeOne(
(extEntities: Record<string, ExtEntityRegistryEntry>) =>
Object.values(extEntities).filter(
(entity) => entity.options?.conversation?.should_expose
).length
);
protected render() {
return html`
<ha-card outlined>
@ -106,7 +117,12 @@ export class AssistPref extends LitElement {
>
<ha-button>
${this.hass.localize(
"ui.panel.config.voice_assistants.assistants.pipeline.manage_entities"
"ui.panel.config.voice_assistants.assistants.pipeline.exposed_entities",
{
number: this.extEntities
? this._exposedEntities(this.extEntities)
: 0,
}
)}
</ha-button>
</a>
@ -128,7 +144,8 @@ export class AssistPref extends LitElement {
private async _openDialog(pipeline?: AssistPipeline): Promise<void> {
showVoiceAssistantPipelineDetailDialog(this, {
cloudActiveSubscription: this.cloudStatus?.active_subscription,
cloudActiveSubscription:
this.cloudStatus?.logged_in && this.cloudStatus.active_subscription,
pipeline,
preferred: pipeline?.id === this._preferred,
createPipeline: async (values) => {

View File

@ -2,6 +2,7 @@ import "@material/mwc-button";
import { mdiHelpCircle } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event";
import { isEmptyFilter } from "../../../common/entity/entity_filter";
import "../../../components/ha-alert";
@ -10,6 +11,7 @@ import "../../../components/ha-settings-row";
import "../../../components/ha-switch";
import type { HaSwitch } from "../../../components/ha-switch";
import { CloudStatusLoggedIn, updateCloudPref } from "../../../data/cloud";
import { ExtEntityRegistryEntry } from "../../../data/entity_registry";
import {
getExposeNewEntities,
setExposeNewEntities,
@ -20,10 +22,19 @@ import { brandsUrl } from "../../../util/brands-url";
export class CloudAlexaPref extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() private extEntities?: Record<string, ExtEntityRegistryEntry>;
@property() public cloudStatus?: CloudStatusLoggedIn;
@state() private _exposeNew?: boolean;
private _exposedEntities = memoizeOne(
(extEntities: Record<string, ExtEntityRegistryEntry>) =>
Object.values(extEntities).filter(
(entity) => entity.options?.["cloud.alexa"]?.should_expose
).length
);
protected willUpdate() {
if (!this.hasUpdated) {
getExposeNewEntities(this.hass, "cloud.alexa").then((value) => {
@ -159,17 +170,28 @@ export class CloudAlexaPref extends LitElement {
`
: ""}`}
</div>
<div class="card-actions">
<a
href="/config/voice-assistants/expose?assistants=cloud.alexa&historyBack"
>
<mwc-button
>${this.hass!.localize(
"ui.panel.config.cloud.account.alexa.manage_entities"
)}</mwc-button
>
</a>
</div>
${alexa_enabled
? html`<div class="card-actions">
<a
href="/config/voice-assistants/expose?assistants=cloud.alexa&historyBack"
>
<mwc-button>
${manualConfig
? this.hass!.localize(
"ui.panel.config.cloud.account.alexa.show_entities"
)
: this.hass.localize(
"ui.panel.config.cloud.account.alexa.exposed_entities",
{
number: this.extEntities
? this._exposedEntities(this.extEntities)
: 0,
}
)}
</mwc-button>
</a>
</div>`
: nothing}
</ha-card>
`;
}

View File

@ -2,6 +2,7 @@ import "@material/mwc-button";
import { mdiHelpCircle } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-alert";
import "../../../components/ha-card";
@ -18,10 +19,13 @@ import {
getExposeNewEntities,
setExposeNewEntities,
} from "../../../data/voice";
import { ExtEntityRegistryEntry } from "../../../data/entity_registry";
export class CloudGooglePref extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property() private extEntities?: Record<string, ExtEntityRegistryEntry>;
@property({ attribute: false }) public cloudStatus?: CloudStatusLoggedIn;
@state() private _exposeNew?: boolean;
@ -36,6 +40,13 @@ export class CloudGooglePref extends LitElement {
}
}
private _exposedEntities = memoizeOne(
(extEntities: Record<string, ExtEntityRegistryEntry>) =>
Object.values(extEntities).filter(
(entity) => entity.options?.["cloud.google_assistant"]?.should_expose
).length
);
protected render() {
if (!this.cloudStatus) {
return nothing;
@ -215,17 +226,28 @@ export class CloudGooglePref extends LitElement {
`
: ""}`}
</div>
<div class="card-actions">
<a
href="/config/voice-assistants/expose?assistants=cloud.google_assistant&historyBack"
>
<mwc-button>
${this.hass.localize(
"ui.panel.config.cloud.account.google.manage_entities"
)}
</mwc-button>
</a>
</div>
${google_enabled
? html`<div class="card-actions">
<a
href="/config/voice-assistants/expose?assistants=cloud.google_assistant&historyBack"
>
<mwc-button>
${manualConfig
? this.hass!.localize(
"ui.panel.config.cloud.account.google.show_entities"
)
: this.hass.localize(
"ui.panel.config.cloud.account.google.exposed_entities",
{
number: this.extEntities
? this._exposedEntities(this.extEntities)
: 0,
}
)}
</mwc-button>
</a>
</div>`
: nothing}
</ha-card>
`;
}

View File

@ -1,17 +1,23 @@
import { consume } from "@lit-labs/context";
import "@polymer/paper-item/paper-item";
import "@polymer/paper-item/paper-item-body";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { css, html, LitElement, nothing, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { computeRTLDirection } from "../../../common/util/compute_rtl";
import { CloudStatus } from "../../../data/cloud";
import { entitiesContext } from "../../../data/context";
import {
ExtEntityRegistryEntry,
getExtendedEntityRegistryEntries,
} from "../../../data/entity_registry";
import "../../../layouts/hass-tabs-subpage";
import { HomeAssistant, Route } from "../../../types";
import "./assist-pref";
import "./cloud-alexa-pref";
import "./cloud-discover";
import "./cloud-google-pref";
import { voiceAssistantTabs } from "./ha-config-voice-assistants";
import "./cloud-discover";
@customElement("ha-config-voice-assistants-assistants")
export class HaConfigVoiceAssistantsAssistants extends LitElement {
@ -25,6 +31,12 @@ export class HaConfigVoiceAssistantsAssistants extends LitElement {
@property() public route!: Route;
@state()
@consume({ context: entitiesContext, subscribe: true })
_entities!: HomeAssistant["entities"];
@state() private _extEntities?: Record<string, ExtEntityRegistryEntry>;
protected render() {
if (!this.hass) {
return html`<hass-loading-screen></hass-loading-screen>`;
@ -40,20 +52,25 @@ export class HaConfigVoiceAssistantsAssistants extends LitElement {
>
<div class="content">
${isComponentLoaded(this.hass, "assist_pipeline")
? html`<assist-pref
.hass=${this.hass}
.cloudStatus=${this.cloudStatus}
></assist-pref>`
? html`
<assist-pref
.hass=${this.hass}
.cloudStatus=${this.cloudStatus}
.extEntities=${this._extEntities}
></assist-pref>
`
: nothing}
${this.cloudStatus?.logged_in
? html`
<cloud-alexa-pref
.hass=${this.hass}
.extEntities=${this._extEntities}
.cloudStatus=${this.cloudStatus}
dir=${computeRTLDirection(this.hass)}
></cloud-alexa-pref>
<cloud-google-pref
.hass=${this.hass}
.extEntities=${this._extEntities}
.cloudStatus=${this.cloudStatus}
dir=${computeRTLDirection(this.hass)}
></cloud-google-pref>
@ -64,6 +81,19 @@ export class HaConfigVoiceAssistantsAssistants extends LitElement {
`;
}
public willUpdate(changedProperties: PropertyValues): void {
if (changedProperties.has("_entities")) {
this._fetchExtendedEntities();
}
}
private async _fetchExtendedEntities() {
this._extEntities = await getExtendedEntityRegistryEntries(
this.hass,
Object.keys(this._entities)
);
}
static styles = css`
.content {
padding: 28px 20px 0;

View File

@ -44,7 +44,6 @@ import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box
import "../../../layouts/hass-loading-screen";
import "../../../layouts/hass-tabs-subpage-data-table";
import type { HaTabsSubpageDataTable } from "../../../layouts/hass-tabs-subpage-data-table";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant, Route } from "../../../types";
import { brandsUrl } from "../../../util/brands-url";
@ -53,7 +52,7 @@ import { showExposeEntityDialog } from "./show-dialog-expose-entity";
import { showVoiceSettingsDialog } from "./show-dialog-voice-settings";
@customElement("ha-config-voice-assistants-expose")
export class VoiceAssistantsExpose extends SubscribeMixin(LitElement) {
export class VoiceAssistantsExpose extends LitElement {
@property() public hass!: HomeAssistant;
@property({ attribute: false }) public cloudStatus?: CloudStatus;

View File

@ -2030,7 +2030,7 @@
"caption": "Assistants",
"pipeline": {
"add_assistant": "Add assistant",
"manage_entities": "[%key:ui::panel::config::cloud::account::google::manage_entities%]",
"exposed_entities": "[%key:ui::panel::config::cloud::account::google::exposed_entities%]",
"delete": {
"confirm_title": "Delete {name}?",
"confirm_text": "{name} will be permanently deleted."
@ -2845,7 +2845,8 @@
"enable_state_reporting": "Enable State Reporting",
"info_state_reporting": "If you enable state reporting, Home Assistant will send all state changes of exposed entities to Amazon. This allows you to always see the latest states in the Alexa app and use the state changes to create routines.",
"state_reporting_error": "Unable to {enable_disable} report state.",
"manage_entities": "[%key:ui::panel::config::cloud::account::google::manage_entities%]",
"show_entities": "[%key:ui::panel::config::cloud::account::google::show_entities%]",
"exposed_entities": "[%key:ui::panel::config::cloud::account::google::exposed_entities%]",
"manual_config": "[%key:ui::panel::config::cloud::account::google::manual_config%]",
"enable": "enable",
"disable": "disable",
@ -2868,7 +2869,8 @@
"enter_pin_info": "Please enter a PIN to interact with security devices. Security devices are doors, garage doors and locks. You will be asked to say/enter this PIN when interacting with such devices via Google Assistant.",
"devices_pin": "Security Devices PIN",
"enter_pin_hint": "Enter a PIN to use security devices",
"manage_entities": "Manage Entities",
"show_entities": "Show Entities",
"exposed_entities": "{number} {number, plural,\n one {entity}\n other {entities}\n} exposed",
"manual_config": "Editing which entities are exposed via the UI is disabled because you have configured entity filters in configuration.yaml.",
"enter_pin_error": "Unable to store PIN:",
"not_configured_title": "Continue setting up Google Assistant",