Add page to list assist devices (#19301)

* Add page to list assist devices

* Translate title too
This commit is contained in:
Paulus Schoutsen 2024-01-10 06:22:59 -08:00 committed by GitHub
parent de35e89c58
commit a136fa687f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 190 additions and 1 deletions

View File

@ -18,6 +18,11 @@ export interface AssistPipeline {
wake_word_id: string | null;
}
export interface AssistDevice {
device_id: string;
pipeline_entity: string;
}
export interface AssistPipelineMutableParams {
name: string;
language: string;
@ -366,3 +371,8 @@ export const fetchAssistPipelineLanguages = (hass: HomeAssistant) =>
hass.callWS<{ languages: string[] }>({
type: "assist_pipeline/language/list",
});
export const listAssistDevices = (hass: HomeAssistant) =>
hass.callWS<AssistDevice[]>({
type: "assist_pipeline/device/list",
});

View File

@ -12,9 +12,11 @@ import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon";
import "../../../components/ha-switch";
import {
AssistDevice,
AssistPipeline,
createAssistPipeline,
deleteAssistPipeline,
listAssistDevices,
listAssistPipelines,
setAssistPipelinePreferred,
updateAssistPipeline,
@ -39,6 +41,8 @@ export class AssistPref extends LitElement {
@state() private _preferred: string | null = null;
@state() private _devices: AssistDevice[] = [];
@property() public cloudStatus?: CloudStatus;
protected firstUpdated(changedProps: PropertyValues) {
@ -48,6 +52,9 @@ export class AssistPref extends LitElement {
this._pipelines = pipelines.pipelines;
this._preferred = pipelines.preferred_pipeline;
});
listAssistDevices(this.hass).then((devices) => {
this._devices = devices;
});
}
private _exposedEntitiesCount = memoizeOne(
@ -132,6 +139,18 @@ export class AssistPref extends LitElement {
)}
</ha-button>
</a>
${this._devices?.length
? html`
<a href="/config/voice-assistants/assist/devices">
<ha-button>
${this.hass.localize(
"ui.panel.config.voice_assistants.assistants.pipeline.assist_devices",
{ number: this._devices.length }
)}
</ha-button>
</a>
`
: ""}
</div>
</ha-card>
`;

View File

@ -0,0 +1,148 @@
import { LitElement, PropertyValues, html } from "lit";
import memoizeOne from "memoize-one";
import { customElement, property, state } from "lit/decorators";
import "../../../../layouts/hass-subpage";
import "../../../../components/data-table/ha-data-table";
import type { DataTableColumnContainer } from "../../../../components/data-table/ha-data-table";
import { HomeAssistant } from "../../../../types";
import {
AssistDevice,
AssistPipeline,
listAssistDevices,
listAssistPipelines,
} from "../../../../data/assist_pipeline";
import { computeDeviceName } from "../../../../data/device_registry";
import { navigate } from "../../../../common/navigate";
interface AssistDeviceExtra {
pipeline: string | undefined;
last_used: string | undefined;
}
@customElement("ha-config-voice-assistants-assist-devices")
class AssistDevicesPage extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public narrow!: boolean;
@state() private _pipelines: Record<string, AssistPipeline> = {};
@state() private _preferred: string | null = null;
@state() private _devices?: (AssistDevice | AssistDeviceExtra)[];
private _columns = memoizeOne(
(
hass: HomeAssistant,
pipelines: Record<string, AssistPipeline>,
preferred: string | null
): DataTableColumnContainer => {
const columns: DataTableColumnContainer<AssistDevice> = {
name: {
title: hass.localize(
"ui.panel.config.voice_assistants.assistants.pipeline.devices.device"
),
width: "50%",
filterable: true,
sortable: true,
template: (assistDevice) =>
computeDeviceName(hass.devices[assistDevice.device_id], hass),
},
pipeline: {
title: hass.localize(
"ui.panel.config.voice_assistants.assistants.pipeline.devices.pipeline"
),
width: "30%",
filterable: true,
sortable: true,
template: (assistDevice) => {
let selected = hass.states[assistDevice.pipeline_entity].state;
if (!pipelines) {
return selected;
}
let isPreferred = false;
if (selected === "preferred") {
isPreferred = true;
selected = preferred!;
}
const name = pipelines[selected].name;
return isPreferred
? hass.localize("ui.components.pipeline-picker.preferred", {
preferred: name,
})
: name;
},
},
area: {
title: hass.localize(
"ui.panel.config.voice_assistants.assistants.pipeline.devices.area"
),
width: "20%",
template: (assistDevice) => {
const device = hass.devices[assistDevice.device_id];
return (
(device && device.area_id && hass.areas[device.area_id]?.name) ||
""
);
},
},
};
return columns;
}
);
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
listAssistPipelines(this.hass).then((pipelines) => {
const lookup: Record<string, AssistPipeline> = {};
for (const pipeline of pipelines.pipelines) {
lookup[pipeline.id] = pipeline;
}
this._pipelines = lookup;
this._preferred = pipelines.preferred_pipeline;
});
listAssistDevices(this.hass).then((devices) => {
this._devices = devices;
});
}
render() {
return html`
<hass-subpage
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass.localize(
"ui.panel.config.voice_assistants.assistants.pipeline.devices.title"
)}
>
<ha-data-table
clickable
id="device_id"
.hass=${this.hass}
.columns=${this._columns(this.hass, this._pipelines, this._preferred)}
.data=${this._devices || []}
auto-height
@row-click=${this._handleRowClicked}
></ha-data-table>
</hass-subpage>
`;
}
private _handleRowClicked(ev: CustomEvent) {
const device: AssistDevice = ev.detail.id;
navigate(`/config/devices/device/${device}`);
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-config-voice-assistants-assist-devices": AssistDevicesPage;
}
}

View File

@ -75,6 +75,11 @@ class HaConfigVoiceAssistants extends HassRouterPage {
tag: "assist-debug",
load: () => import("./debug/assist-debug"),
},
assist: {
tag: "ha-config-voice-assistants-assist-devices",
load: () =>
import("./assist/ha-config-voice-assistants-assist-devices"),
},
},
};

View File

@ -2257,10 +2257,17 @@
"pipeline": {
"add_assistant": "Add assistant",
"exposed_entities": "[%key:ui::panel::config::cloud::account::google::exposed_entities%]",
"assist_devices": "{number} Assist {number, plural,\n one {device}\n other {devices}\n}",
"delete": {
"confirm_title": "Delete {name}?",
"confirm_text": "{name} will be permanently deleted."
},
"devices": {
"title": "Assist devices",
"device": "Device",
"pipeline": "Assistant",
"area": "Area"
},
"detail": {
"update_assistant_action": "Update",
"add_assistant_title": "Add assistant",
@ -2269,7 +2276,7 @@
"debug": "Debug",
"set_as_preferred": "Set as preferred",
"form": {
"name": "Name",
"name": "[%key:ui::common::name%]",
"conversation_engine": "Conversation agent",
"conversation_language": "[%key:ui::panel::config::voice_assistants::assistants::pipeline::detail::form::language%]",
"language": "Language",