diff --git a/src/data/integration.ts b/src/data/integration.ts index 1cecc97b75..21aa60965e 100644 --- a/src/data/integration.ts +++ b/src/data/integration.ts @@ -5,6 +5,7 @@ import type { HomeAssistant } from "../types"; import { debounce } from "../common/util/debounce"; export const integrationsWithPanel = { + bluetooth: "config/bluetooth", matter: "config/matter", mqtt: "config/mqtt", thread: "config/thread", diff --git a/src/panels/config/ha-panel-config.ts b/src/panels/config/ha-panel-config.ts index c29b5d9855..b40b01d63c 100644 --- a/src/panels/config/ha-panel-config.ts +++ b/src/panels/config/ha-panel-config.ts @@ -549,10 +549,10 @@ class HaPanelConfig extends SubscribeMixin(HassRouterPage) { ), }, bluetooth: { - tag: "bluetooth-config-panel", + tag: "bluetooth-config-dashboard-router", load: () => import( - "./integrations/integration-panels/bluetooth/bluetooth-config-panel" + "./integrations/integration-panels/bluetooth/bluetooth-config-dashboard-router" ), }, application_credentials: { diff --git a/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-panel.ts b/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-advertisement-monitor.ts similarity index 94% rename from src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-panel.ts rename to src/panels/config/integrations/integration-panels/bluetooth/bluetooth-advertisement-monitor.ts index 978190e8a8..f874bf0fab 100644 --- a/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-panel.ts +++ b/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-advertisement-monitor.ts @@ -19,8 +19,8 @@ import type { BluetoothDeviceData } from "../../../../../data/bluetooth"; import { subscribeBluetoothAdvertisements } from "../../../../../data/bluetooth"; import { showBluetoothDeviceInfoDialog } from "./show-dialog-bluetooth-device-info"; -@customElement("bluetooth-config-panel") -export class BluetoothConfigPanel extends LitElement { +@customElement("bluetooth-advertisement-monitor") +export class BluetoothAdvertisementMonitorPanel extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public route!: Route; @@ -121,6 +121,6 @@ export class BluetoothConfigPanel extends LitElement { declare global { interface HTMLElementTagNameMap { - "bluetooth-config-panel": BluetoothConfigPanel; + "bluetooth-advertisement-monitor": BluetoothAdvertisementMonitorPanel; } } diff --git a/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-dashboard-router.ts b/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-dashboard-router.ts new file mode 100644 index 0000000000..105803910a --- /dev/null +++ b/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-dashboard-router.ts @@ -0,0 +1,46 @@ +import { customElement, property } from "lit/decorators"; +import type { RouterOptions } from "../../../../../layouts/hass-router-page"; +import { HassRouterPage } from "../../../../../layouts/hass-router-page"; +import type { HomeAssistant } from "../../../../../types"; + +@customElement("bluetooth-config-dashboard-router") +class BluetoothConfigDashboardRouter extends HassRouterPage { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: "is-wide", type: Boolean }) public isWide = false; + + @property({ type: Boolean }) public narrow = false; + + private _configEntry = new URLSearchParams(window.location.search).get( + "config_entry" + ); + + protected routerOptions: RouterOptions = { + defaultPage: "dashboard", + showLoading: true, + routes: { + dashboard: { + tag: "bluetooth-config-dashboard", + load: () => import("./bluetooth-config-dashboard"), + }, + "advertisement-monitor": { + tag: "bluetooth-advertisement-monitor", + load: () => import("./bluetooth-advertisement-monitor"), + }, + }, + }; + + protected updatePageEl(el): void { + el.route = this.routeTail; + el.hass = this.hass; + el.isWide = this.isWide; + el.narrow = this.narrow; + el.configEntryId = this._configEntry; + } +} + +declare global { + interface HTMLElementTagNameMap { + "bluetooth-config-dashboard-router": BluetoothConfigDashboardRouter; + } +} diff --git a/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-dashboard.ts b/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-dashboard.ts new file mode 100644 index 0000000000..17a97e7cd8 --- /dev/null +++ b/src/panels/config/integrations/integration-panels/bluetooth/bluetooth-config-dashboard.ts @@ -0,0 +1,107 @@ +import "@material/mwc-button"; +import type { CSSResultGroup, TemplateResult } from "lit"; +import { css, html, LitElement } from "lit"; +import { customElement, property } from "lit/decorators"; +import "../../../../../components/ha-card"; +import "../../../../../components/ha-code-editor"; +import "../../../../../components/ha-formfield"; +import "../../../../../components/ha-switch"; +import { getConfigEntries } from "../../../../../data/config_entries"; +import { showOptionsFlowDialog } from "../../../../../dialogs/config-flow/show-dialog-options-flow"; +import "../../../../../layouts/hass-subpage"; +import { haStyle } from "../../../../../resources/styles"; +import type { HomeAssistant } from "../../../../../types"; + +@customElement("bluetooth-config-dashboard") +export class BluetoothConfigDashboard extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ type: Boolean }) public narrow = false; + + protected render(): TemplateResult { + return html` + +
+ +
+ ${this.hass.localize( + "ui.panel.config.bluetooth.option_flow" + )} +
+
+ +
+

+ ${this.hass.localize( + "ui.panel.config.bluetooth.advertisement_monitor_details" + )} +

+
+ +
+
+
+ `; + } + + private async _openOptionFlow() { + const searchParams = new URLSearchParams(window.location.search); + if (!searchParams.has("config_entry")) { + return; + } + const configEntryId = searchParams.get("config_entry") as string; + const configEntries = await getConfigEntries(this.hass, { + domain: "bluetooth", + }); + const configEntry = configEntries.find( + (entry) => entry.entry_id === configEntryId + ); + showOptionsFlowDialog(this, configEntry!); + } + + static get styles(): CSSResultGroup { + return [ + haStyle, + css` + :host { + -ms-user-select: initial; + -webkit-user-select: initial; + -moz-user-select: initial; + } + .content { + padding: 24px 0 32px; + max-width: 600px; + margin: 0 auto; + direction: ltr; + } + ha-card:first-child { + margin-bottom: 16px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "bluetooth-config-dashboard": BluetoothConfigDashboard; + } +} diff --git a/src/translations/en.json b/src/translations/en.json index 23b24e6f5e..0bcc1d1331 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -5281,6 +5281,10 @@ }, "bluetooth": { "title": "Bluetooth", + "settings_title": "Bluetooth settings", + "option_flow": "Configure Bluetooth options", + "advertisement_monitor": "Advertisement Monitor", + "advertisement_monitor_details": "The advertisement monitor listens for Bluetooth advertisements and displays the data in a structured format.", "address": "Address", "name": "Name", "source": "Source",