mirror of
https://github.com/home-assistant/frontend.git
synced 2026-06-16 13:21:48 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 608cdf168e |
+48
-48
@@ -94,55 +94,55 @@ class HaGallery extends LitElement {
|
||||
<div slot="title">
|
||||
${PAGES[this._page].metadata.title || this._page.split("/")[1]}
|
||||
</div>
|
||||
<div class="content">
|
||||
${PAGES[this._page].description
|
||||
? html`
|
||||
<page-description .page=${this._page}></page-description>
|
||||
`
|
||||
: ""}
|
||||
${dynamicElement(`demo-${this._page.replace("/", "-")}`)}
|
||||
</div>
|
||||
<div class="page-footer">
|
||||
<div class="edit-docs">
|
||||
<div class="header">Help us to improve our documentation</div>
|
||||
<div class="secondary">
|
||||
Suggest an edit to this page, or provide/view feedback for
|
||||
this page.
|
||||
</div>
|
||||
<div>
|
||||
${PAGES[this._page].description ||
|
||||
Object.keys(PAGES[this._page].metadata).length > 0
|
||||
? html`
|
||||
<a
|
||||
href=${`${GITHUB_DEMO_URL}${this._page}.markdown`}
|
||||
target="_blank"
|
||||
>
|
||||
Edit text
|
||||
</a>
|
||||
`
|
||||
: ""}
|
||||
${PAGES[this._page].demo
|
||||
? html`
|
||||
<a
|
||||
href=${`${GITHUB_DEMO_URL}${this._page}.ts`}
|
||||
target="_blank"
|
||||
>
|
||||
Edit demo
|
||||
</a>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
</div>
|
||||
<div class="rtl-toggle">
|
||||
<ha-icon-button
|
||||
@click=${this._toggleRtl}
|
||||
.label=${this._rtl ? "Switch to LTR" : "Switch to RTL"}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiSwapHorizontal}></ha-svg-icon>
|
||||
</ha-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</ha-top-app-bar-fixed>
|
||||
<div class="content">
|
||||
${PAGES[this._page].description
|
||||
? html`
|
||||
<page-description .page=${this._page}></page-description>
|
||||
`
|
||||
: ""}
|
||||
${dynamicElement(`demo-${this._page.replace("/", "-")}`)}
|
||||
</div>
|
||||
<div class="page-footer">
|
||||
<div class="edit-docs">
|
||||
<div class="header">Help us to improve our documentation</div>
|
||||
<div class="secondary">
|
||||
Suggest an edit to this page, or provide/view feedback for this
|
||||
page.
|
||||
</div>
|
||||
<div>
|
||||
${PAGES[this._page].description ||
|
||||
Object.keys(PAGES[this._page].metadata).length > 0
|
||||
? html`
|
||||
<a
|
||||
href=${`${GITHUB_DEMO_URL}${this._page}.markdown`}
|
||||
target="_blank"
|
||||
>
|
||||
Edit text
|
||||
</a>
|
||||
`
|
||||
: ""}
|
||||
${PAGES[this._page].demo
|
||||
? html`
|
||||
<a
|
||||
href=${`${GITHUB_DEMO_URL}${this._page}.ts`}
|
||||
target="_blank"
|
||||
>
|
||||
Edit demo
|
||||
</a>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
</div>
|
||||
<div class="rtl-toggle">
|
||||
<ha-icon-button
|
||||
@click=${this._toggleRtl}
|
||||
.label=${this._rtl ? "Switch to LTR" : "Switch to RTL"}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiSwapHorizontal}></ha-svg-icon>
|
||||
</ha-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ha-drawer>
|
||||
<notification-manager
|
||||
|
||||
@@ -5,7 +5,7 @@ import { isComponentLoaded } from "./is_component_loaded";
|
||||
|
||||
export const canShowPage = (hass: HomeAssistant, page: PageNavigation) =>
|
||||
(isCore(page) || isLoadedIntegration(hass, page)) &&
|
||||
(!page.filter || page.filter(hass));
|
||||
isNotLoadedIntegration(hass, page);
|
||||
|
||||
export const isLoadedIntegration = (
|
||||
hass: HomeAssistant,
|
||||
@@ -16,4 +16,13 @@ export const isLoadedIntegration = (
|
||||
isComponentLoaded(hass.config, integration)
|
||||
);
|
||||
|
||||
export const isNotLoadedIntegration = (
|
||||
hass: HomeAssistant,
|
||||
page: PageNavigation
|
||||
) =>
|
||||
!page.not_component ||
|
||||
!ensureArray(page.not_component).some((integration) =>
|
||||
isComponentLoaded(hass.config, integration)
|
||||
);
|
||||
|
||||
export const isCore = (page: PageNavigation) => page.core;
|
||||
|
||||
@@ -32,10 +32,10 @@ export class HaAutomationRowLiveTest extends LitElement {
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
inset-inline-end: -6px;
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
margin-inline-start: var(--ha-space-1);
|
||||
}
|
||||
#indicator {
|
||||
width: 10px;
|
||||
|
||||
+2
-2
@@ -39,7 +39,6 @@ import {
|
||||
mdiMicrophoneMessage,
|
||||
mdiMotionSensor,
|
||||
mdiPalette,
|
||||
mdiRadioTower,
|
||||
mdiRayVertex,
|
||||
mdiRemote,
|
||||
mdiRobot,
|
||||
@@ -53,6 +52,7 @@ import {
|
||||
mdiThermostat,
|
||||
mdiTimerOutline,
|
||||
mdiToggleSwitch,
|
||||
mdiVideoInputAntenna,
|
||||
mdiWater,
|
||||
mdiWaterPercent,
|
||||
mdiWeatherPartlyCloudy,
|
||||
@@ -129,7 +129,7 @@ export const FALLBACK_DOMAIN_ICONS = {
|
||||
plant: mdiFlower,
|
||||
power: mdiFlash,
|
||||
proximity: mdiAppleSafari,
|
||||
radio_frequency: mdiRadioTower,
|
||||
radio_frequency: mdiVideoInputAntenna,
|
||||
remote: mdiRemote,
|
||||
scene: mdiPalette,
|
||||
schedule: mdiCalendarClock,
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { HomeAssistant } from "../types";
|
||||
|
||||
export const DOMAIN = "radio_frequency";
|
||||
|
||||
export interface RadioFrequencyTransmitter {
|
||||
entity_id: string;
|
||||
device_id: string | null;
|
||||
config_entry_id: string | null;
|
||||
supported_frequency_ranges: [number, number][];
|
||||
supported_modulations: string[];
|
||||
}
|
||||
|
||||
interface RadioFrequencyTransmitterList {
|
||||
transmitters: RadioFrequencyTransmitter[];
|
||||
}
|
||||
|
||||
export const fetchRadioFrequencyTransmitters = (
|
||||
hass: HomeAssistant
|
||||
): Promise<RadioFrequencyTransmitterList> =>
|
||||
hass.callWS({
|
||||
type: "radio_frequency/list",
|
||||
});
|
||||
@@ -33,10 +33,10 @@ export interface PageNavigation {
|
||||
translationKey?: string;
|
||||
component?: string | string[];
|
||||
name?: string;
|
||||
not_component?: string | string[];
|
||||
core?: boolean;
|
||||
/** Hide from non-admin users in filtered navigation and quick bar. */
|
||||
adminOnly?: boolean;
|
||||
filter?: (hass: HomeAssistant) => boolean;
|
||||
iconPath?: string;
|
||||
iconSecondaryPath?: string;
|
||||
iconViewBox?: string;
|
||||
|
||||
@@ -217,19 +217,11 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.condition=${this.condition.condition}
|
||||
></ha-condition-icon>
|
||||
${this.optionsInSidebar && this.condition.condition !== "trigger"
|
||||
? html`<ha-automation-row-live-test
|
||||
.state=${this._liveTestResult.state}
|
||||
.label=${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.conditions.live_test_state.${this._liveTestResult.state}`
|
||||
)}
|
||||
></ha-automation-row-live-test>`
|
||||
: nothing}
|
||||
</div>
|
||||
${this.optionsInSidebar &&
|
||||
this.condition.condition !== "trigger" &&
|
||||
this._liveTestResult.message
|
||||
? html`<ha-tooltip for="condition-icon" slot="leading-icon"
|
||||
? html`<ha-tooltip for="condition-live-test" slot="leading-icon"
|
||||
>${this._liveTestResult.message}</ha-tooltip
|
||||
>`
|
||||
: nothing}
|
||||
@@ -245,6 +237,15 @@ export default class HaAutomationConditionRow extends LitElement {
|
||||
this.condition.condition !== "device"
|
||||
)
|
||||
: nothing}
|
||||
${this.optionsInSidebar && this.condition.condition !== "trigger"
|
||||
? html`<ha-automation-row-live-test
|
||||
id="condition-live-test"
|
||||
.state=${this._liveTestResult.state}
|
||||
.label=${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.conditions.live_test_state.${this._liveTestResult.state}`
|
||||
)}
|
||||
></ha-automation-row-live-test>`
|
||||
: nothing}
|
||||
${this.condition.note?.trim()
|
||||
? html`
|
||||
<ha-svg-icon
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
mdiPalette,
|
||||
mdiPaletteSwatch,
|
||||
mdiPuzzle,
|
||||
mdiRadioTower,
|
||||
mdiRobot,
|
||||
mdiScrewdriver,
|
||||
mdiScriptText,
|
||||
@@ -36,7 +35,6 @@ import {
|
||||
} from "@mdi/js";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { listenMediaQuery } from "../../common/dom/media_query";
|
||||
import type { CloudStatus } from "../../data/cloud";
|
||||
@@ -57,14 +55,6 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
const getHasDomainCheck = (domain: string) => {
|
||||
const prefix = `${domain}.`;
|
||||
const checkRegistry = memoizeOne((entries: HomeAssistant["entities"]) =>
|
||||
Object.values(entries).some((entry) => entry.entity_id.startsWith(prefix))
|
||||
);
|
||||
return (hass: HomeAssistant) => checkRegistry(hass.entities);
|
||||
};
|
||||
|
||||
export const configSections: Record<string, PageNavigation[]> = {
|
||||
dashboard: [
|
||||
{
|
||||
@@ -176,15 +166,6 @@ export const configSections: Record<string, PageNavigation[]> = {
|
||||
translationKey: "bluetooth",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
path: "/config/radio-frequency",
|
||||
iconPath: mdiRadioTower,
|
||||
iconColor: "#E74011",
|
||||
component: "radio_frequency",
|
||||
translationKey: "radio_frequency",
|
||||
adminOnly: true,
|
||||
filter: getHasDomainCheck("radio_frequency"),
|
||||
},
|
||||
{
|
||||
path: "/insteon",
|
||||
iconPath:
|
||||
@@ -686,11 +667,6 @@ class HaPanelConfig extends HassRouterPage {
|
||||
tag: "ha-config-section-updates",
|
||||
load: () => import("./core/ha-config-section-updates"),
|
||||
},
|
||||
"radio-frequency": {
|
||||
tag: "radio-frequency-config-dashboard-router",
|
||||
load: () =>
|
||||
import("./integrations/integration-panels/radio_frequency/radio-frequency-config-dashboard-router"),
|
||||
},
|
||||
repairs: {
|
||||
tag: "ha-config-repairs-dashboard",
|
||||
load: () => import("./repairs/ha-config-repairs-dashboard"),
|
||||
|
||||
@@ -1003,10 +1003,10 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
|
||||
if (!entityReg) {
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.helpers.picker.no_category_support"
|
||||
"ui.panel.config.automation.picker.no_category_support"
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.helpers.picker.no_category_entity_reg"
|
||||
"ui.panel.config.automation.picker.no_category_entity_reg"
|
||||
),
|
||||
});
|
||||
return;
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
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("radio-frequency-config-dashboard-router")
|
||||
class RadioFrequencyConfigDashboardRouter extends HassRouterPage {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
protected routerOptions: RouterOptions = {
|
||||
defaultPage: "dashboard",
|
||||
showLoading: true,
|
||||
routes: {
|
||||
dashboard: {
|
||||
tag: "radio-frequency-config-dashboard",
|
||||
load: () => import("./radio-frequency-config-dashboard"),
|
||||
},
|
||||
transmitters: {
|
||||
tag: "radio-frequency-transmitters",
|
||||
load: () => import("./radio-frequency-transmitters"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
protected updatePageEl(el): void {
|
||||
el.route = this.routeTail;
|
||||
el.hass = this.hass;
|
||||
el.isWide = this.isWide;
|
||||
el.narrow = this.narrow;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"radio-frequency-config-dashboard-router": RadioFrequencyConfigDashboardRouter;
|
||||
}
|
||||
}
|
||||
-211
@@ -1,211 +0,0 @@
|
||||
import { mdiCheck, mdiCloseCircleOutline } from "@mdi/js";
|
||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import "../../../../../components/ha-card";
|
||||
import "../../../../../components/ha-icon-next";
|
||||
import "../../../../../components/ha-md-list";
|
||||
import "../../../../../components/ha-md-list-item";
|
||||
import "../../../../../components/ha-svg-icon";
|
||||
import { UNAVAILABLE } from "../../../../../data/entity/entity";
|
||||
import { FALLBACK_DOMAIN_ICONS } from "../../../../../data/icons";
|
||||
import type { RadioFrequencyTransmitter } from "../../../../../data/radio_frequency";
|
||||
import {
|
||||
DOMAIN,
|
||||
fetchRadioFrequencyTransmitters,
|
||||
} from "../../../../../data/radio_frequency";
|
||||
import "../../../../../layouts/hass-subpage";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../../../types";
|
||||
|
||||
@customElement("radio-frequency-config-dashboard")
|
||||
export class RadioFrequencyConfigDashboard extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
|
||||
|
||||
@state() private _transmitters: RadioFrequencyTransmitter[] = [];
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (this.hass) {
|
||||
this._fetchTransmitters();
|
||||
}
|
||||
}
|
||||
|
||||
private async _fetchTransmitters(): Promise<void> {
|
||||
const result = await fetchRadioFrequencyTransmitters(this.hass);
|
||||
this._transmitters = result.transmitters;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const total = this._transmitters.length;
|
||||
const online = this._transmitters.filter((transmitter) => {
|
||||
const stateObj = this.hass.states[transmitter.entity_id];
|
||||
return stateObj && stateObj.state !== UNAVAILABLE;
|
||||
}).length;
|
||||
const isOffline = online === 0;
|
||||
const status = isOffline ? "offline" : "online";
|
||||
const statusIcon = isOffline ? mdiCloseCircleOutline : mdiCheck;
|
||||
|
||||
return html`
|
||||
<hass-subpage
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.header=${this.hass.localize("ui.panel.config.radio_frequency.title")}
|
||||
back-path="/config"
|
||||
>
|
||||
<div class="container">
|
||||
<ha-card class="network-status">
|
||||
<div class="card-content">
|
||||
<div class="heading">
|
||||
<div class="icon ${status}">
|
||||
<ha-svg-icon .path=${statusIcon}></ha-svg-icon>
|
||||
</div>
|
||||
<div class="details">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.radio_frequency.status_${status}`
|
||||
)}<br />
|
||||
<small>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.radio_frequency.transmitters_summary",
|
||||
{ online, total }
|
||||
)}
|
||||
</small>
|
||||
</div>
|
||||
<ha-svg-icon
|
||||
class="logo"
|
||||
.path=${FALLBACK_DOMAIN_ICONS[DOMAIN]}
|
||||
></ha-svg-icon>
|
||||
</div>
|
||||
</div>
|
||||
</ha-card>
|
||||
|
||||
<ha-card class="network-card">
|
||||
<div class="card-content">
|
||||
<ha-md-list>
|
||||
<ha-md-list-item
|
||||
type="link"
|
||||
href="/config/radio-frequency/transmitters"
|
||||
>
|
||||
<ha-svg-icon
|
||||
slot="start"
|
||||
.path=${FALLBACK_DOMAIN_ICONS[DOMAIN]}
|
||||
></ha-svg-icon>
|
||||
<div slot="headline">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.radio_frequency.devices_count",
|
||||
{ count: total }
|
||||
)}
|
||||
</div>
|
||||
<ha-icon-next slot="end"></ha-icon-next>
|
||||
</ha-md-list-item>
|
||||
</ha-md-list>
|
||||
</div>
|
||||
</ha-card>
|
||||
</div>
|
||||
</hass-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.container {
|
||||
padding: var(--ha-space-2) var(--ha-space-4) var(--ha-space-4);
|
||||
}
|
||||
|
||||
ha-card {
|
||||
margin: 0px auto var(--ha-space-4);
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
ha-md-list {
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.network-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.network-card .card-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.network-status div.heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: var(--ha-space-4);
|
||||
}
|
||||
|
||||
.network-status div.heading .logo {
|
||||
margin-inline-start: auto;
|
||||
--mdc-icon-size: 40px;
|
||||
}
|
||||
|
||||
.network-status div.heading .icon {
|
||||
position: relative;
|
||||
border-radius: var(--ha-border-radius-2xl);
|
||||
width: var(--ha-space-10);
|
||||
height: var(--ha-space-10);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
--icon-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.network-status div.heading .icon.online {
|
||||
--icon-color: var(--success-color);
|
||||
}
|
||||
|
||||
.network-status div.heading .icon.offline {
|
||||
--icon-color: var(--error-color);
|
||||
}
|
||||
|
||||
.network-status div.heading .icon::before {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-color: var(--icon-color, var(--primary-color));
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.network-status div.heading .icon ha-svg-icon {
|
||||
color: var(--icon-color, var(--primary-color));
|
||||
width: var(--ha-space-6);
|
||||
height: var(--ha-space-6);
|
||||
}
|
||||
|
||||
.network-status div.heading .details {
|
||||
font-size: var(--ha-font-size-xl);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: var(--ha-line-height-condensed);
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.network-status small {
|
||||
font-size: var(--ha-font-size-m);
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
line-height: var(--ha-line-height-condensed);
|
||||
letter-spacing: 0.25px;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"radio-frequency-config-dashboard": RadioFrequencyConfigDashboard;
|
||||
}
|
||||
}
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
import type { CSSResultGroup, TemplateResult } from "lit";
|
||||
import { html, LitElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { navigate } from "../../../../../common/navigate";
|
||||
import { computeStateName } from "../../../../../common/entity/compute_state_name";
|
||||
import type { HASSDomEvent } from "../../../../../common/dom/fire_event";
|
||||
import type { LocalizeFunc } from "../../../../../common/translations/localize";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
RowClickedEvent,
|
||||
} from "../../../../../components/data-table/ha-data-table";
|
||||
import "../../../../../components/ha-icon-button";
|
||||
import type { RadioFrequencyTransmitter } from "../../../../../data/radio_frequency";
|
||||
import { fetchRadioFrequencyTransmitters } from "../../../../../data/radio_frequency";
|
||||
import "../../../../../layouts/hass-tabs-subpage-data-table";
|
||||
import type { PageNavigation } from "../../../../../layouts/hass-tabs-subpage";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../../../types";
|
||||
|
||||
interface RadioFrequencyTransmitterRow {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
last_used: string;
|
||||
device_id: string | null;
|
||||
}
|
||||
|
||||
@customElement("radio-frequency-transmitters")
|
||||
export class RadioFrequencyTransmitters extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@property({ type: Boolean }) public narrow = false;
|
||||
|
||||
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
|
||||
|
||||
@state() private _transmitters: RadioFrequencyTransmitter[] = [];
|
||||
|
||||
private _tabs: PageNavigation[] = [
|
||||
{
|
||||
translationKey: "ui.panel.config.radio_frequency.navigation.transmitters",
|
||||
path: "/config/radio-frequency/transmitters",
|
||||
},
|
||||
];
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (this.hass) {
|
||||
this._fetchTransmitters();
|
||||
}
|
||||
}
|
||||
|
||||
private async _fetchTransmitters(): Promise<void> {
|
||||
const result = await fetchRadioFrequencyTransmitters(this.hass);
|
||||
this._transmitters = result.transmitters;
|
||||
}
|
||||
|
||||
private _columns = memoizeOne(
|
||||
(localize: LocalizeFunc): DataTableColumnContainer => {
|
||||
const columns: DataTableColumnContainer<RadioFrequencyTransmitterRow> = {
|
||||
name: {
|
||||
title: localize("ui.panel.config.radio_frequency.name"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
showNarrow: true,
|
||||
main: true,
|
||||
flex: 2,
|
||||
direction: "asc",
|
||||
},
|
||||
type: {
|
||||
title: localize("ui.panel.config.radio_frequency.type"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
groupable: true,
|
||||
},
|
||||
last_used: {
|
||||
title: localize("ui.panel.config.radio_frequency.last_used"),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
},
|
||||
};
|
||||
|
||||
return columns;
|
||||
}
|
||||
);
|
||||
|
||||
private _data = memoizeOne(
|
||||
(
|
||||
transmitters: RadioFrequencyTransmitter[],
|
||||
states: HomeAssistant["states"],
|
||||
localize: LocalizeFunc
|
||||
): RadioFrequencyTransmitterRow[] =>
|
||||
transmitters.map((transmitter) => {
|
||||
const stateObj = states[transmitter.entity_id];
|
||||
return {
|
||||
id: transmitter.entity_id,
|
||||
name: stateObj ? computeStateName(stateObj) : transmitter.entity_id,
|
||||
type: localize("ui.panel.config.radio_frequency.type_transmitter"),
|
||||
last_used: stateObj ? this.hass.formatEntityState(stateObj) : "—",
|
||||
device_id: transmitter.device_id,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<hass-tabs-subpage-data-table
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
.tabs=${this._tabs}
|
||||
back-path="/config/radio-frequency/dashboard"
|
||||
.columns=${this._columns(this.hass.localize)}
|
||||
.data=${this._data(
|
||||
this._transmitters,
|
||||
this.hass.states,
|
||||
this.hass.localize
|
||||
)}
|
||||
.noDataText=${this.hass.localize(
|
||||
"ui.panel.config.radio_frequency.no_transmitters"
|
||||
)}
|
||||
@row-click=${this._handleRowClicked}
|
||||
clickable
|
||||
></hass-tabs-subpage-data-table>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
|
||||
const transmitter = this._transmitters.find(
|
||||
(t) => t.entity_id === ev.detail.id
|
||||
);
|
||||
if (transmitter?.device_id) {
|
||||
navigate(`/config/devices/device/${transmitter.device_id}`);
|
||||
}
|
||||
}
|
||||
|
||||
static styles: CSSResultGroup = haStyle;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"radio-frequency-transmitters": RadioFrequencyTransmitters;
|
||||
}
|
||||
}
|
||||
@@ -239,17 +239,9 @@ export class HaCardConditionEditor extends LitElement {
|
||||
<ha-svg-icon
|
||||
.path=${ICON_CONDITION[condition.condition]}
|
||||
></ha-svg-icon>
|
||||
${hideLiveTest
|
||||
? nothing
|
||||
: html`<ha-automation-row-live-test
|
||||
.state=${this._liveTestResult.state}
|
||||
.label=${this.hass.localize(
|
||||
`ui.panel.lovelace.editor.condition-editor.live_test_state.${this._liveTestResult.state}`
|
||||
)}
|
||||
></ha-automation-row-live-test>`}
|
||||
</div>
|
||||
${!hideLiveTest && this._liveTestResult.message
|
||||
? html`<ha-tooltip for="condition-icon" slot="leading-icon"
|
||||
? html`<ha-tooltip for="condition-live-test" slot="leading-icon"
|
||||
>${this._liveTestResult.message}</ha-tooltip
|
||||
>`
|
||||
: nothing}
|
||||
@@ -257,6 +249,15 @@ export class HaCardConditionEditor extends LitElement {
|
||||
${this.hass.localize(
|
||||
`ui.panel.lovelace.editor.condition-editor.condition.${condition.condition}.label`
|
||||
) || condition.condition}
|
||||
${!hideLiveTest
|
||||
? html`<ha-automation-row-live-test
|
||||
id="condition-live-test"
|
||||
.state=${this._liveTestResult.state}
|
||||
.label=${this.hass.localize(
|
||||
`ui.panel.lovelace.editor.condition-editor.live_test_state.${this._liveTestResult.state}`
|
||||
)}
|
||||
></ha-automation-row-live-test>`
|
||||
: nothing}
|
||||
</h3>
|
||||
<ha-automation-row-event-chip
|
||||
.show=${this._testingResult !== undefined}
|
||||
|
||||
@@ -1616,7 +1616,6 @@
|
||||
"zwave_js": "[%key:ui::panel::config::dashboard::zwave_js::main%]",
|
||||
"thread": "[%key:ui::panel::config::dashboard::thread::main%]",
|
||||
"bluetooth": "[%key:ui::panel::config::dashboard::bluetooth::main%]",
|
||||
"radio_frequency": "[%key:ui::panel::config::dashboard::radio_frequency::main%]",
|
||||
"knx": "[%key:ui::panel::config::dashboard::knx::main%]",
|
||||
"insteon": "[%key:ui::panel::config::dashboard::insteon::main%]",
|
||||
"voice-assistants": "[%key:ui::panel::config::dashboard::voice_assistants::main%]",
|
||||
@@ -2719,10 +2718,6 @@
|
||||
"main": "Bluetooth",
|
||||
"secondary": "Local device connectivity"
|
||||
},
|
||||
"radio_frequency": {
|
||||
"main": "Radio frequency",
|
||||
"secondary": "Control radio-based devices."
|
||||
},
|
||||
"knx": {
|
||||
"main": "KNX",
|
||||
"secondary": "Building automation standard"
|
||||
@@ -4394,9 +4389,7 @@
|
||||
"error_information": "Error information",
|
||||
"delete_confirm_title": "Delete helper?",
|
||||
"delete_confirm_text": "Are you sure you want to delete {name}?",
|
||||
"delete_failed": "Failed to delete helper",
|
||||
"no_category_support": "You can't assign a category to this helper",
|
||||
"no_category_entity_reg": "To assign a category to a helper it needs to have a unique ID."
|
||||
"delete_failed": "Failed to delete helper"
|
||||
},
|
||||
"dialog": {
|
||||
"create": "Create",
|
||||
@@ -7192,21 +7185,6 @@
|
||||
"known_devices": "Known devices",
|
||||
"unknown_devices": "Unknown devices"
|
||||
},
|
||||
"radio_frequency": {
|
||||
"title": "Radio frequency",
|
||||
"status_online": "Online",
|
||||
"status_offline": "Offline",
|
||||
"transmitters_summary": "{online}/{total} transmitters online",
|
||||
"devices_count": "{count} {count, plural,\n one {device}\n other {devices}\n}",
|
||||
"no_transmitters": "No radio frequency transmitters found",
|
||||
"name": "Name",
|
||||
"type": "Type",
|
||||
"type_transmitter": "Transmitter",
|
||||
"last_used": "Last used",
|
||||
"navigation": {
|
||||
"transmitters": "Transmitters"
|
||||
}
|
||||
},
|
||||
"dhcp": {
|
||||
"title": "DHCP discovery",
|
||||
"mac_address": "MAC address",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
canShowPage,
|
||||
isLoadedIntegration,
|
||||
isNotLoadedIntegration,
|
||||
isCore,
|
||||
} from "../../../src/common/config/can_show_page";
|
||||
import type { PageNavigation } from "../../../src/layouts/hass-tabs-subpage";
|
||||
@@ -49,6 +50,28 @@ describe("isLoadedIntegration", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("isNotLoadedIntegration", () => {
|
||||
it("should return true if the integration is not loaded", () => {
|
||||
const hass = {
|
||||
config: { components: ["test_component"] },
|
||||
} as unknown as HomeAssistant;
|
||||
const page = {
|
||||
not_component: "other_component",
|
||||
} as unknown as PageNavigation;
|
||||
expect(isNotLoadedIntegration(hass, page)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false if the integration is loaded", () => {
|
||||
const hass = {
|
||||
config: { components: ["test_component"] },
|
||||
} as unknown as HomeAssistant;
|
||||
const page = {
|
||||
not_component: "test_component",
|
||||
} as unknown as PageNavigation;
|
||||
expect(isNotLoadedIntegration(hass, page)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isCore", () => {
|
||||
it("should return true if the page is core", () => {
|
||||
const page = { core: true } as unknown as PageNavigation;
|
||||
|
||||
Reference in New Issue
Block a user