Compare commits

...

6 Commits

Author SHA1 Message Date
Aidan Timson
ca2344eb10 Show url in label 2025-12-09 16:55:23 +00:00
Aidan Timson
6c9f51071c Reuse device page logic 2025-12-09 16:21:32 +00:00
Aidan Timson
0c1f57e2ce Follow device page link handling 2025-12-09 16:19:32 +00:00
Aidan Timson
e573f2012e Add configuration url link to config entry row 2025-12-09 16:17:55 +00:00
Aidan Timson
05ca8253f0 Update HaGenericPicker unknown value check to handle null and empty strings (#28462) 2025-12-09 15:53:28 +01:00
Aidan Timson
071161e82d Add area to helpers table (#28460) 2025-12-09 14:05:54 +00:00
7 changed files with 101 additions and 39 deletions

View File

@@ -0,0 +1,29 @@
export interface ProcessedConfigurationUrl {
url: string;
isLocal: boolean;
}
/**
* Get a processed configuration URL, converting homeassistant:// URLs to local paths
* and determining if it should be opened locally or in a new tab.
*
* @param configurationUrl - The configuration URL to process
* @returns Processed URL and whether it's a local link, or null if URL is empty
*/
export const getConfigurationUrl = (
configurationUrl: string | null | undefined
): ProcessedConfigurationUrl | null => {
if (!configurationUrl) {
return null;
}
const isHomeAssistant = configurationUrl.startsWith("homeassistant://");
const url = isHomeAssistant
? configurationUrl.replace("homeassistant://", "/")
: configurationUrl;
return {
url,
isLocal: isHomeAssistant,
};
};

View File

@@ -246,7 +246,7 @@ export class HaGenericPicker extends LitElement {
private _unknownValue = memoizeOne(
(value?: string, items?: (PickerComboBoxItem | string)[]) => {
if (value === undefined || !items) {
if (value === undefined || value === null || value === "" || !items) {
return false;
}

View File

@@ -27,6 +27,7 @@ export interface ConfigEntry {
reason: string | null;
error_reason_translation_key: string | null;
error_reason_translation_placeholders: Record<string, string> | null;
configuration_url?: string | null;
}
export interface SubEntry {

View File

@@ -26,6 +26,7 @@ import { computeStateName } from "../../../common/entity/compute_state_name";
import { stringCompare } from "../../../common/string/compare";
import { slugify } from "../../../common/string/slugify";
import { groupBy } from "../../../common/util/group-by";
import { getConfigurationUrl } from "../../../common/util/configuration-url";
import "../../../components/entity/ha-battery-icon";
import "../../../components/ha-alert";
import "../../../components/ha-button";
@@ -1090,17 +1091,12 @@ export class HaConfigDevicePage extends LitElement {
const deviceActions: DeviceAction[] = [];
const configurationUrlIsHomeAssistant =
device.configuration_url?.startsWith("homeassistant://") || false;
const processedUrl = getConfigurationUrl(device.configuration_url);
const configurationUrl = configurationUrlIsHomeAssistant
? device.configuration_url!.replace("homeassistant://", "/")
: device.configuration_url;
if (configurationUrl) {
if (processedUrl) {
deviceActions.push({
href: configurationUrl,
target: configurationUrlIsHomeAssistant ? undefined : "_blank",
href: processedUrl.url,
target: processedUrl.isLocal ? undefined : "_blank",
icon: mdiCog,
label: this.hass.localize(
"ui.panel.config.devices.open_configuration_url"

View File

@@ -25,6 +25,7 @@ import { computeCssColor } from "../../../common/color/compute-color";
import { storage } from "../../../common/decorators/storage";
import type { HASSDomEvent } from "../../../common/dom/fire_event";
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeAreaName } from "../../../common/entity/compute_area_name";
import { navigate } from "../../../common/navigate";
import type {
LocalizeFunc,
@@ -132,6 +133,7 @@ interface HelperItem {
configEntry?: ConfigEntry;
entity?: HassEntity;
category: string | undefined;
area?: string;
label_entries: LabelRegistryEntry[];
disabled?: boolean;
}
@@ -347,6 +349,12 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
filterable: true,
sortable: true,
},
area: {
title: localize("ui.panel.config.helpers.picker.headers.area"),
sortable: true,
filterable: true,
groupable: true,
},
labels: {
title: "",
hidden: true,
@@ -565,6 +573,11 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
entityRegistryByEntityId(entityReg)[item.entity_id];
const labels = labelReg && entityRegEntry?.labels;
const category = entityRegEntry?.categories.helpers;
const areaId = entityRegEntry?.area_id;
const area =
areaId && this.hass.areas?.[areaId]
? computeAreaName(this.hass.areas[areaId])
: undefined;
return {
...item,
localized_type:
@@ -579,6 +592,7 @@ export class HaConfigHelpers extends SubscribeMixin(LitElement) {
category: category
? categoryReg?.find((cat) => cat.category_id === category)?.name
: undefined,
area,
};
});
}

View File

@@ -8,6 +8,7 @@ import {
mdiDotsVertical,
mdiDownload,
mdiHandExtendedOutline,
mdiOpenInNew,
mdiPlayCircleOutline,
mdiPlus,
mdiProgressHelper,
@@ -73,6 +74,7 @@ import "./ha-config-entry-device-row";
import { renderConfigEntryError } from "./ha-config-integration-page";
import "./ha-config-sub-entry-row";
import { copyToClipboard } from "../../../common/util/copy-clipboard";
import { getConfigurationUrl } from "../../../common/util/configuration-url";
import { showToast } from "../../../util/toast";
@customElement("ha-config-entry-row")
@@ -213,34 +215,53 @@ class HaConfigEntryRow extends LitElement {
? html`<ha-button slot="end" @click=${this._handleEnable}>
${this.hass.localize("ui.common.enable")}
</ha-button>`
: configPanel &&
(item.domain !== "matter" ||
isDevVersion(this.hass.config.version)) &&
!stateText
? html`<a
slot="end"
href=${`/${configPanel}?config_entry=${item.entry_id}`}
><ha-icon-button
.path=${mdiCogOutline}
.label=${this.hass.localize(
"ui.panel.config.integrations.config_entry.configure"
)}
>
</ha-icon-button
></a>`
: item.supports_options
? html`
<ha-icon-button
slot="end"
@click=${this._showOptions}
.path=${mdiCogOutline}
.label=${this.hass.localize(
"ui.panel.config.integrations.config_entry.configure"
)}
>
</ha-icon-button>
`
: nothing}
: (() => {
const processedUrl = getConfigurationUrl(item.configuration_url);
return html`
${processedUrl
? html`<a
slot="end"
href=${processedUrl.url}
target=${processedUrl.isLocal ? undefined : "_blank"}
rel=${processedUrl.isLocal ? undefined : "noreferrer"}
>
<ha-icon-button
.path=${mdiOpenInNew}
.label=${processedUrl.url}
></ha-icon-button>
</a>`
: nothing}
${configPanel &&
(item.domain !== "matter" ||
isDevVersion(this.hass.config.version)) &&
!stateText
? html`<a
slot="end"
href=${`/${configPanel}?config_entry=${item.entry_id}`}
><ha-icon-button
.path=${mdiCogOutline}
.label=${this.hass.localize(
"ui.panel.config.integrations.config_entry.configure"
)}
>
</ha-icon-button
></a>`
: item.supports_options
? html`
<ha-icon-button
slot="end"
@click=${this._showOptions}
.path=${mdiCogOutline}
.label=${this.hass.localize(
"ui.panel.config.integrations.config_entry.configure"
)}
>
</ha-icon-button>
`
: nothing}
`;
})()}
<ha-md-button-menu positioning="popover" slot="end">
<ha-icon-button
slot="trigger"

View File

@@ -3304,7 +3304,8 @@
"entity_id": "Entity ID",
"type": "Type",
"editable": "Editable",
"category": "Category"
"category": "Category",
"area": "Area"
},
"create_helper": "Create helper",
"no_helpers": "Looks like you don't have any helpers yet!",