1
0
mirror of https://github.com/home-assistant/frontend.git synced 2026-02-15 07:25:54 +00:00

Navigation picker: add sections/grouping and related nav paths (#29094)

* Add sections to navigation picker

* Use PANEL_DASHBOARDS to assign system dashboards to the dashboards section

* Clean

* Add context based related section

* Add integration icon for related device

* Add floor and sort

* Consolidate and cleanup

* Reuse type

* Add context check and catch findRelated errors

* Remove floor from set, use area

* Memoize related updates

* Log error

* Remove

* Fix icon path usage
This commit is contained in:
Aidan Timson
2026-01-26 13:10:09 +00:00
committed by GitHub
parent 9ba34869be
commit 37d8273e7c
25 changed files with 474 additions and 27 deletions

View File

@@ -1,13 +1,38 @@
import { html, LitElement, nothing } from "lit";
import Fuse from "fuse.js";
import { mdiDevices, mdiTextureBox } from "@mdi/js";
import { html, LitElement, nothing, type PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event";
import { caseInsensitiveStringCompare } from "../common/string/compare";
import { titleCase } from "../common/string/title-case";
import { getConfigEntries, type ConfigEntry } from "../data/config_entries";
import { fetchConfig } from "../data/lovelace/config/types";
import { getPanelIcon, getPanelTitle } from "../data/panel";
import { findRelated, type RelatedResult } from "../data/search";
import { PANEL_DASHBOARDS } from "../panels/config/lovelace/dashboards/ha-config-lovelace-dashboards";
import { multiTermSortedSearch } from "../resources/fuseMultiTerm";
import type { HomeAssistant, ValueChangedEvent } from "../types";
import type { ActionRelatedContext } from "../panels/lovelace/components/hui-action-editor";
import "./ha-generic-picker";
import "./ha-domain-icon";
import "./ha-icon";
import type { PickerComboBoxItem } from "./ha-picker-combo-box";
import {
DEFAULT_SEARCH_KEYS,
type PickerComboBoxItem,
} from "./ha-picker-combo-box";
type NavigationGroup = "related" | "dashboards" | "views" | "other_routes";
const RELATED_SORT_PREFIX = {
area: "0_area",
device: "1_device",
} as const;
interface NavigationItem extends PickerComboBoxItem {
group: NavigationGroup;
domain?: string;
}
@customElement("ha-navigation-picker")
export class HaNavigationPicker extends LitElement {
@@ -25,13 +50,57 @@ export class HaNavigationPicker extends LitElement {
@state() private _loading = true;
@property({ attribute: false }) public context?: ActionRelatedContext;
protected firstUpdated() {
this._loadNavigationItems();
}
private _navigationItems: PickerComboBoxItem[] = [];
private _navigationItems: NavigationItem[] = [];
private _configEntryLookup: Record<string, ConfigEntry> = {};
private _navigationGroups: Record<NavigationGroup, NavigationItem[]> = {
related: [],
dashboards: [],
views: [],
other_routes: [],
};
private _getRelatedItems = memoizeOne(
async (_cacheKey: string, context: ActionRelatedContext) =>
this._fetchRelatedItems(context),
(newArgs, lastArgs) => newArgs[0] === lastArgs[0]
);
protected render() {
const sections = [
...(this._navigationGroups.related.length
? [
{
id: "related",
label: this.hass.localize(
"ui.components.navigation-picker.related"
),
},
]
: []),
{
id: "dashboards",
label: this.hass.localize("ui.components.navigation-picker.dashboards"),
},
{
id: "views",
label: this.hass.localize("ui.components.navigation-picker.views"),
},
{
id: "other_routes",
label: this.hass.localize(
"ui.components.navigation-picker.other_routes"
),
},
];
return html`
<ha-generic-picker
.hass=${this.hass}
@@ -43,6 +112,8 @@ export class HaNavigationPicker extends LitElement {
.required=${this.required}
.getItems=${this._getItems}
.valueRenderer=${this._valueRenderer}
.rowRenderer=${this._rowRenderer}
.sections=${sections}
.customValueLabel=${this.hass.localize(
"ui.components.navigation-picker.add_custom_path"
)}
@@ -55,9 +126,23 @@ export class HaNavigationPicker extends LitElement {
private _valueRenderer = (itemId: string) => {
const item = this._navigationItems.find((navItem) => navItem.id === itemId);
return html`
${item?.icon
? html`<ha-icon slot="start" .icon=${item.icon}></ha-icon>`
: nothing}
${item?.domain
? html`
<ha-domain-icon
slot="start"
.hass=${this.hass}
.domain=${item.domain}
brand-fallback
></ha-domain-icon>
`
: item?.icon
? html`<ha-icon slot="start" .icon=${item.icon}></ha-icon>`
: item?.icon_path
? html`<ha-svg-icon
slot="start"
.path=${item.icon_path}
></ha-svg-icon>`
: nothing}
<span slot="headline">${item?.primary || itemId}</span>
${item?.primary
? html`<span slot="supporting-text">${itemId}</span>`
@@ -65,9 +150,106 @@ export class HaNavigationPicker extends LitElement {
`;
};
private _getItems = () => this._navigationItems;
private _rowRenderer = (item: NavigationItem) => html`
<ha-combo-box-item type="button" compact>
${item.domain
? html`
<ha-domain-icon
slot="start"
.hass=${this.hass}
.domain=${item.domain}
brand-fallback
></ha-domain-icon>
`
: item.icon
? html`<ha-icon slot="start" .icon=${item.icon}></ha-icon>`
: item.icon_path
? html`<ha-svg-icon
slot="start"
.path=${item.icon_path}
></ha-svg-icon>`
: nothing}
<span slot="headline">${item.primary}</span>
${item.secondary
? html`<span slot="supporting-text">${item.secondary}</span>`
: nothing}
</ha-combo-box-item>
`;
private _fuseIndexes = {
related: memoizeOne((items: NavigationItem[]) =>
Fuse.createIndex(DEFAULT_SEARCH_KEYS, items)
),
dashboards: memoizeOne((items: NavigationItem[]) =>
Fuse.createIndex(DEFAULT_SEARCH_KEYS, items)
),
views: memoizeOne((items: NavigationItem[]) =>
Fuse.createIndex(DEFAULT_SEARCH_KEYS, items)
),
other_routes: memoizeOne((items: NavigationItem[]) =>
Fuse.createIndex(DEFAULT_SEARCH_KEYS, items)
),
};
private _getItems = (searchString?: string, section?: string) => {
const getGroupItems = (group: NavigationGroup) => {
let items = [...this._navigationGroups[group]].sort(
this._sortBySortingLabel
);
if (searchString) {
const fuseIndex = this._fuseIndexes[group](items);
items = multiTermSortedSearch(
items,
searchString,
DEFAULT_SEARCH_KEYS,
(item) => item.id,
fuseIndex
);
}
return items;
};
const items: (NavigationItem | string)[] = [];
const related = getGroupItems("related");
const dashboards = getGroupItems("dashboards");
const views = getGroupItems("views");
const otherRoutes = getGroupItems("other_routes");
const addGroup = (group: NavigationGroup, groupItems: NavigationItem[]) => {
if (section && section !== group) {
return;
}
if (!section && groupItems.length) {
items.push(
this.hass.localize(`ui.components.navigation-picker.${group}`)
);
}
items.push(...groupItems);
};
addGroup("related", related);
addGroup("dashboards", dashboards);
addGroup("views", views);
addGroup("other_routes", otherRoutes);
return items;
};
private _sortBySortingLabel = (
itemA: PickerComboBoxItem,
itemB: PickerComboBoxItem
) =>
caseInsensitiveStringCompare(
itemA.sorting_label!,
itemB.sorting_label!,
this.hass.locale.language
);
private async _loadNavigationItems() {
await this._loadConfigEntries();
const panels = Object.entries(this.hass!.panels).map(([id, panel]) => ({
id,
...panel,
@@ -91,13 +273,19 @@ export class HaNavigationPicker extends LitElement {
const panelViewConfig = new Map(viewConfigs);
this._navigationItems = [];
const related = this._navigationGroups.related;
const dashboards: NavigationItem[] = [];
const views: NavigationItem[] = [];
const otherRoutes: NavigationItem[] = [];
for (const panel of panels) {
const path = `/${panel.url_path}`;
const panelTitle = getPanelTitle(this.hass, panel);
const primary = panelTitle || path;
this._navigationItems.push({
const isDashboardPanel =
panel.component_name === "lovelace" ||
PANEL_DASHBOARDS.includes(panel.id);
const panelItem: NavigationItem = {
id: path,
primary,
secondary: panelTitle ? path : undefined,
@@ -108,7 +296,14 @@ export class HaNavigationPicker extends LitElement {
]
.filter(Boolean)
.join("_"),
});
group: isDashboardPanel ? "dashboards" : "other_routes",
};
if (isDashboardPanel) {
dashboards.push(panelItem);
} else {
otherRoutes.push(panelItem);
}
const config = panelViewConfig.get(panel.id);
@@ -118,7 +313,7 @@ export class HaNavigationPicker extends LitElement {
const viewPath = `/${panel.url_path}/${view.path ?? index}`;
const viewPrimary =
view.title ?? (view.path ? titleCase(view.path) : `${index}`);
this._navigationItems.push({
views.push({
id: viewPath,
secondary: viewPath,
icon: view.icon ?? "mdi:view-compact",
@@ -127,13 +322,156 @@ export class HaNavigationPicker extends LitElement {
viewPrimary.startsWith("/") ? `zzz${viewPrimary}` : viewPrimary,
viewPath,
].join("_"),
group: "views",
});
});
}
this._navigationGroups = {
related,
dashboards,
views,
other_routes: otherRoutes,
};
this._navigationItems = [
...related,
...dashboards,
...views,
...otherRoutes,
];
this._loading = false;
}
protected updated(changedProps: PropertyValues) {
if (changedProps.has("context")) {
this._loadRelatedItems();
}
}
private async _loadRelatedItems() {
const updateRelatedItems = (relatedItems: NavigationItem[]) => {
this._navigationGroups = {
...this._navigationGroups,
related: relatedItems,
};
this._navigationItems = [
...relatedItems,
...this._navigationGroups.dashboards,
...this._navigationGroups.views,
...this._navigationGroups.other_routes,
];
};
if (!this.hass || (!this.context?.entity_id && !this.context?.area_id)) {
updateRelatedItems([]);
return;
}
const context = this.context;
const contextMatches = () =>
this.context?.entity_id === context?.entity_id &&
this.context?.area_id === context?.area_id;
const items = await this._getRelatedItems(
`${context.entity_id ?? ""}|${context.area_id ?? ""}`,
context
);
if (contextMatches()) {
updateRelatedItems(items);
}
}
private async _fetchRelatedItems(
context: ActionRelatedContext
): Promise<NavigationItem[]> {
let relatedResult: RelatedResult | undefined;
try {
relatedResult = context.entity_id
? await findRelated(this.hass, "entity", context.entity_id)
: await findRelated(this.hass, "area", context.area_id!);
} catch (err) {
// eslint-disable-next-line no-console
console.error("Error fetching related items for navigation picker", err);
return [];
}
const relatedDeviceIds = new Set(relatedResult?.device ?? []);
const relatedAreaIds = new Set(relatedResult?.area ?? []);
if (context.area_id) {
relatedAreaIds.add(context.area_id);
}
const createSortingLabel = (
prefix: string,
primary: string,
path: string
) =>
[prefix, primary.startsWith("/") ? `zzz${primary}` : primary, path]
.filter(Boolean)
.join("_");
const relatedItems: NavigationItem[] = [];
for (const deviceId of relatedDeviceIds) {
const device = this.hass.devices[deviceId];
const primary = device?.name_by_user ?? device?.name ?? deviceId;
const path = `/config/devices/device/${deviceId}`;
relatedItems.push({
id: path,
primary,
secondary: path,
icon_path: mdiDevices,
sorting_label: createSortingLabel(
RELATED_SORT_PREFIX.device,
primary,
path
),
group: "related",
domain: device?.primary_config_entry
? this._configEntryLookup[device.primary_config_entry]?.domain
: undefined,
});
}
for (const areaId of relatedAreaIds) {
const area = this.hass.areas[areaId];
const primary = area?.name ?? areaId;
const path = `/config/areas/area/${areaId}`;
relatedItems.push({
id: path,
primary,
secondary: path,
icon: area?.icon ?? undefined,
icon_path: area?.icon ? undefined : mdiTextureBox,
sorting_label: createSortingLabel(
RELATED_SORT_PREFIX.area,
primary,
path
),
group: "related",
});
}
return relatedItems;
}
private async _loadConfigEntries() {
if (Object.keys(this._configEntryLookup).length) {
return;
}
try {
const configEntries = await getConfigEntries(this.hass);
this._configEntryLookup = Object.fromEntries(
configEntries.map((entry) => [entry.entry_id, entry])
);
} catch (err) {
// eslint-disable-next-line no-console
console.error("Error fetching config entries for navigation picker", err);
}
}
private _valueChanged(ev: ValueChangedEvent<string>) {
ev.stopPropagation();
this._setValue(ev.detail.value);

View File

@@ -3,6 +3,7 @@ import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import type { NavigationSelector } from "../../data/selector";
import type { HomeAssistant } from "../../types";
import type { ActionRelatedContext } from "../../panels/lovelace/components/hui-action-editor";
import "../ha-navigation-picker";
@customElement("ha-selector-navigation")
@@ -21,6 +22,8 @@ export class HaNavigationSelector extends LitElement {
@property({ type: Boolean }) public required = true;
@property({ attribute: false }) public context?: ActionRelatedContext;
protected render() {
return html`
<ha-navigation-picker
@@ -30,6 +33,7 @@ export class HaNavigationSelector extends LitElement {
.required=${this.required}
.disabled=${this.disabled}
.helper=${this.helper}
.context=${this.selector.navigation ?? this.context}
@value-changed=${this._valueChanged}
></ha-navigation-picker>
`;

View File

@@ -5,6 +5,7 @@ import type { ActionConfig } from "../../data/lovelace/config/action";
import type { UiActionSelector } from "../../data/selector";
import "../../panels/lovelace/components/hui-action-editor";
import type { HomeAssistant } from "../../types";
import type { ActionRelatedContext } from "../../panels/lovelace/components/hui-action-editor";
@customElement("ha-selector-ui_action")
export class HaSelectorUiAction extends LitElement {
@@ -14,6 +15,8 @@ export class HaSelectorUiAction extends LitElement {
@property({ attribute: false }) public value?: ActionConfig;
@property({ attribute: false }) public context?: ActionRelatedContext;
@property() public label?: string;
@property() public helper?: string;
@@ -24,6 +27,7 @@ export class HaSelectorUiAction extends LitElement {
.label=${this.label}
.hass=${this.hass}
.config=${this.value}
.context=${this.context}
.actions=${this.selector.ui_action?.actions}
.defaultAction=${this.selector.ui_action?.default_action}
.tooltipText=${this.helper}

View File

@@ -7,7 +7,10 @@ import type { EntityNameItem } from "../common/entity/compute_entity_name_displa
import { computeStateDomain } from "../common/entity/compute_state_domain";
import { supportsFeature } from "../common/entity/supports-feature";
import { isHelperDomain } from "../panels/config/helpers/const";
import type { UiAction } from "../panels/lovelace/components/hui-action-editor";
import type {
ActionRelatedContext,
UiAction,
} from "../panels/lovelace/components/hui-action-editor";
import type { HomeAssistant } from "../types";
import {
type DeviceRegistryEntry,
@@ -332,7 +335,7 @@ export interface MediaSelectorValue {
}
export interface NavigationSelector {
navigation: {} | null;
navigation: ActionRelatedContext | null;
}
export interface NumberSelector {

View File

@@ -27,6 +27,16 @@ import type { EditorTarget } from "../editor/types";
export type UiAction = Exclude<ActionConfig["action"], "fire-dom-event">;
export interface ActionRelatedContext {
entity_id?: string;
area_id?: string;
}
export const ACTION_RELATED_CONTEXT = {
entity_id: "entity",
area_id: "area",
} as const satisfies HaFormSchema["context"] & ActionRelatedContext;
const DEFAULT_ACTIONS: UiAction[] = [
"more-info",
"toggle",
@@ -42,15 +52,6 @@ export const supportedActions = (struct: any, supported_actions: UiAction[]) =>
supported_actions.includes(value.action)
);
const NAVIGATE_SCHEMA = [
{
name: "navigation_path",
selector: {
navigation: {},
},
},
] as const satisfies readonly HaFormSchema[];
const ASSIST_SCHEMA = [
{
type: "grid",
@@ -88,6 +89,9 @@ export class HuiActionEditor extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false })
public context?: ActionRelatedContext;
@query("ha-select") private _select!: HaSelect;
get _navigation_path(): string {
@@ -115,6 +119,23 @@ export class HuiActionEditor extends LitElement {
})
);
private _navigateSchema = memoizeOne(
(
relatedEntityId?: string,
relatedAreaId?: string
): readonly HaFormSchema[] => [
{
name: "navigation_path",
selector: {
navigation: {
...(relatedEntityId ? { entity_id: relatedEntityId } : {}),
...(relatedAreaId ? { area_id: relatedAreaId } : {}),
},
},
},
]
);
protected updated(changedProperties: PropertyValues<typeof this>) {
super.updated(changedProperties);
if (changedProperties.has("defaultAction")) {
@@ -178,7 +199,10 @@ export class HuiActionEditor extends LitElement {
? html`
<ha-form
.hass=${this.hass}
.schema=${NAVIGATE_SCHEMA}
.schema=${this._navigateSchema(
this.context?.entity_id,
this.context?.area_id
)}
.data=${this.config}
.computeLabel=${this._computeFormLabel}
@value-changed=${this._formValueChanged}

View File

@@ -8,6 +8,7 @@ import type { SchemaUnion } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types";
import type { IconElementConfig } from "../../../elements/types";
import type { LovelacePictureElementEditor } from "../../../types";
import { ACTION_RELATED_CONTEXT } from "../../../components/hui-action-editor";
import { actionConfigStruct } from "../../structs/action-struct";
const iconElementConfigStruct = object({
@@ -38,6 +39,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "hold_action",
@@ -46,6 +48,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -59,6 +62,7 @@ const SCHEMA = [
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -18,6 +18,7 @@ import type { SchemaUnion } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types";
import type { ImageElementConfig } from "../../../elements/types";
import type { LovelacePictureElementEditor } from "../../../types";
import { ACTION_RELATED_CONTEXT } from "../../../components/hui-action-editor";
import { actionConfigStruct } from "../../structs/action-struct";
const imageElementConfigStruct = object({
@@ -69,6 +70,7 @@ export class HuiImageElementEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "hold_action",
@@ -77,6 +79,7 @@ export class HuiImageElementEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -90,6 +93,7 @@ export class HuiImageElementEditor
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -6,6 +6,7 @@ import { fireEvent } from "../../../../../common/dom/fire_event";
import type { SchemaUnion } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types";
import "../../../../../components/ha-form/ha-form";
import { ACTION_RELATED_CONTEXT } from "../../../components/hui-action-editor";
import type { LovelacePictureElementEditor } from "../../../types";
import type { StateBadgeElementConfig } from "../../../elements/types";
import { actionConfigStruct } from "../../structs/action-struct";
@@ -38,6 +39,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "hold_action",
@@ -46,6 +48,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -59,6 +62,7 @@ const SCHEMA = [
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -16,6 +16,7 @@ import type { SchemaUnion } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types";
import type { StateIconElementConfig } from "../../../elements/types";
import type { LovelacePictureElementEditor } from "../../../types";
import { ACTION_RELATED_CONTEXT } from "../../../components/hui-action-editor";
import { actionConfigStruct } from "../../structs/action-struct";
const stateIconElementConfigStruct = object({
@@ -48,6 +49,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "hold_action",
@@ -56,6 +58,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -69,6 +72,7 @@ const SCHEMA = [
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -8,6 +8,7 @@ import type { SchemaUnion } from "../../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../../types";
import type { StateLabelElementConfig } from "../../../elements/types";
import type { LovelacePictureElementEditor } from "../../../types";
import { ACTION_RELATED_CONTEXT } from "../../../components/hui-action-editor";
import { actionConfigStruct } from "../../structs/action-struct";
const stateLabelElementConfigStruct = object({
@@ -48,6 +49,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "hold_action",
@@ -56,6 +58,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -69,6 +72,7 @@ const SCHEMA = [
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -40,6 +40,7 @@ import {
import type { AreaCardConfig, AreaCardDisplayType } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
import { actionConfigStruct } from "../structs/action-struct";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import type { EditDetailElementEvent, EditSubElementEvent } from "../types";
import { configElementStyle } from "./config-elements-style";
@@ -197,6 +198,7 @@ export class HuiAreaCardEditor
actions: ["navigate", "url", "perform-action", "none"],
},
},
context: ACTION_RELATED_CONTEXT,
},
...(displayType !== "compact"
? ([
@@ -218,6 +220,7 @@ export class HuiAreaCardEditor
: ["navigate", "url", "perform-action", "none"],
},
},
context: ACTION_RELATED_CONTEXT,
},
] as const satisfies readonly HaFormSchema[])
: []),

View File

@@ -14,6 +14,7 @@ import type { HomeAssistant } from "../../../../types";
import { getEntityDefaultButtonAction } from "../../cards/hui-button-card";
import type { ButtonCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { entityNameStruct } from "../structs/entity-name-struct";
@@ -126,6 +127,7 @@ export class HuiButtonCardEditor
default_action: getEntityDefaultButtonAction(entityId),
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "hold_action",
@@ -134,6 +136,7 @@ export class HuiButtonCardEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -147,6 +150,7 @@ export class HuiButtonCardEditor
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -28,6 +28,7 @@ import {
} from "../../badges/hui-entity-badge";
import type { EntityBadgeConfig } from "../../badges/types";
import type { LovelaceBadgeEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import "../hui-sub-element-editor";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceBadgeConfig } from "../structs/base-badge-struct";
@@ -172,6 +173,7 @@ export class HuiEntityBadgeEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -185,6 +187,7 @@ export class HuiEntityBadgeEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -9,6 +9,7 @@ import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { entityNameStruct } from "../structs/entity-name-struct";
import {
type UiAction,
ACTION_RELATED_CONTEXT,
supportedActions,
} from "../../components/hui-action-editor";
@@ -90,6 +91,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -104,6 +106,7 @@ const SCHEMA = [
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -20,7 +20,10 @@ import { NON_NUMERIC_ATTRIBUTES } from "../../../../data/entity/entity_attribute
import type { HomeAssistant } from "../../../../types";
import { DEFAULT_MAX, DEFAULT_MIN } from "../../cards/hui-gauge-card";
import type { GaugeCardConfig } from "../../cards/types";
import type { UiAction } from "../../components/hui-action-editor";
import {
ACTION_RELATED_CONTEXT,
type UiAction,
} from "../../components/hui-action-editor";
import type { LovelaceCardEditor } from "../../types";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
@@ -167,6 +170,7 @@ export class HuiGaugeCardEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -181,6 +185,7 @@ export class HuiGaugeCardEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -20,6 +20,7 @@ import type { ConfigEntity, GlanceCardConfig } from "../../cards/types";
import "../../components/hui-entity-editor";
import type { EntityConfig } from "../../entity-rows/types";
import type { LovelaceCardEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import "../hui-sub-element-editor";
import { processEditorEntities } from "../process-editor-entities";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
@@ -73,6 +74,7 @@ const SUB_SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -85,6 +87,7 @@ const SUB_SCHEMA = [
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})),
},
] as const;

View File

@@ -25,7 +25,10 @@ import "../../../../components/ha-svg-icon";
import type { HomeAssistant } from "../../../../types";
import { migrateHeadingCardConfig } from "../../cards/hui-heading-card";
import type { HeadingCardConfig } from "../../cards/types";
import type { UiAction } from "../../components/hui-action-editor";
import {
ACTION_RELATED_CONTEXT,
type UiAction,
} from "../../components/hui-action-editor";
import type {
EntityHeadingBadgeConfig,
LovelaceHeadingBadgeConfig,
@@ -102,6 +105,7 @@ export class HuiHeadingCardEditor
actions,
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -9,6 +9,7 @@ import type { SchemaUnion } from "../../../../components/ha-form/types";
import type { HomeAssistant } from "../../../../types";
import type { LightCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { entityNameStruct } from "../structs/entity-name-struct";
@@ -69,6 +70,7 @@ const SCHEMA = [
default_action: "toggle",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "hold_action",
@@ -77,6 +79,7 @@ const SCHEMA = [
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -90,6 +93,7 @@ const SCHEMA = [
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},

View File

@@ -8,8 +8,8 @@ import type { SchemaUnion } from "../../../../components/ha-form/types";
import "../../../../components/ha-theme-picker";
import type { HomeAssistant } from "../../../../types";
import type { PictureCardConfig } from "../../cards/types";
import "../../components/hui-action-editor";
import type { LovelaceCardEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import type { LocalizeFunc } from "../../../../common/translations/localize";
@@ -72,6 +72,7 @@ export class HuiPictureCardEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -85,6 +86,7 @@ export class HuiPictureCardEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -25,6 +25,7 @@ import type { HomeAssistant } from "../../../../types";
import { STUB_IMAGE } from "../../cards/hui-picture-entity-card";
import type { PictureEntityCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { entityNameStruct } from "../structs/entity-name-struct";
@@ -154,6 +155,7 @@ export class HuiPictureEntityCardEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -167,6 +169,7 @@ export class HuiPictureEntityCardEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -28,6 +28,7 @@ import type { PictureGlanceCardConfig } from "../../cards/types";
import "../../components/hui-entity-editor";
import type { EntityConfig } from "../../entity-rows/types";
import type { LovelaceCardEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { processEditorEntities } from "../process-editor-entities";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
@@ -143,6 +144,7 @@ export class HuiPictureGlanceCardEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -156,6 +158,7 @@ export class HuiPictureGlanceCardEditor
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "double_tap_action",
@@ -164,6 +167,7 @@ export class HuiPictureGlanceCardEditor
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
],
},
@@ -201,6 +205,7 @@ export class HuiPictureGlanceCardEditor
: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -214,6 +219,7 @@ export class HuiPictureGlanceCardEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -30,6 +30,7 @@ import type {
LovelaceCardFeatureConfig,
LovelaceCardFeatureContext,
} from "../../card-features/types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { getEntityDefaultTileIconAction } from "../../cards/hui-tile-card";
import type { TileCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
@@ -189,6 +190,7 @@ export class HuiTileCardEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "icon_tap_action",
@@ -199,6 +201,7 @@ export class HuiTileCardEditor
: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -218,6 +221,7 @@ export class HuiTileCardEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})),
},
],

View File

@@ -22,6 +22,7 @@ import { WeatherEntityFeature } from "../../../../data/weather";
import type { HomeAssistant } from "../../../../types";
import type { WeatherForecastCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import { actionConfigStruct } from "../structs/action-struct";
import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import { entityNameStruct } from "../structs/entity-name-struct";
@@ -267,6 +268,7 @@ export class HuiWeatherForecastCardEditor
default_action: "more-info",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -280,6 +282,7 @@ export class HuiWeatherForecastCardEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -24,6 +24,7 @@ import type { HomeAssistant } from "../../../../types";
import type { Condition } from "../../common/validate-condition";
import type { EntityHeadingBadgeConfig } from "../../heading-badges/types";
import type { LovelaceGenericElementEditor } from "../../types";
import { ACTION_RELATED_CONTEXT } from "../../components/hui-action-editor";
import "../conditions/ha-card-conditions-editor";
import { configElementStyle } from "../config-elements/config-elements-style";
import { actionConfigStruct } from "../structs/action-struct";
@@ -157,6 +158,7 @@ export class HuiHeadingEntityEditor
default_action: "none",
},
},
context: ACTION_RELATED_CONTEXT,
},
{
name: "",
@@ -170,6 +172,7 @@ export class HuiHeadingEntityEditor
default_action: "none" as const,
},
},
context: ACTION_RELATED_CONTEXT,
})
),
},

View File

@@ -1335,7 +1335,11 @@
"error": "Fail!"
},
"navigation-picker": {
"add_custom_path": "Add custom path"
"add_custom_path": "Add custom path",
"dashboards": "[%key:ui::panel::config::dashboard::dashboards::main%]",
"related": "Related",
"views": "Views",
"other_routes": "Other routes"
}
},
"dialogs": {