mirror of
https://github.com/home-assistant/frontend.git
synced 2025-12-20 02:38:53 +00:00
Generic picker warn unknown selected item (#28372)
* Add unknown item text localization to various pickers * Review
This commit is contained in:
@@ -216,6 +216,9 @@ export class HaDevicePicker extends LitElement {
|
||||
.getItems=${this._getItems}
|
||||
.hideClearIcon=${this.hideClearIcon}
|
||||
.valueRenderer=${valueRenderer}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.device-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
|
||||
@@ -288,10 +288,13 @@ export class HaEntityPicker extends LitElement {
|
||||
.hideClearIcon=${this.hideClearIcon}
|
||||
.searchFn=${this._searchFn}
|
||||
.valueRenderer=${this._valueRenderer}
|
||||
@value-changed=${this._valueChanged}
|
||||
.addButtonLabel=${this.addButton
|
||||
? this.hass.localize("ui.components.entity.entity-picker.add")
|
||||
: undefined}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.entity.entity-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
`;
|
||||
|
||||
@@ -475,6 +475,9 @@ export class HaStatisticPicker extends LitElement {
|
||||
.searchFn=${this._searchFn}
|
||||
.valueRenderer=${this._valueRenderer}
|
||||
.helper=${this.helper}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.statistic-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
|
||||
@@ -379,6 +379,9 @@ export class HaAreaPicker extends LitElement {
|
||||
.getAdditionalItems=${this._getAdditionalItems}
|
||||
.valueRenderer=${valueRenderer}
|
||||
.addButtonLabel=${this.addButtonLabel}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.area-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
|
||||
@@ -393,6 +393,9 @@ export class HaFloorPicker extends LitElement {
|
||||
.getAdditionalItems=${this._getAdditionalItems}
|
||||
.valueRenderer=${valueRenderer}
|
||||
.rowRenderer=${this._rowRenderer}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.floor-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { mdiPlaylistPlus } from "@mdi/js";
|
||||
import { css, html, LitElement, nothing, type CSSResultGroup } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { tinykeys } from "tinykeys";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { HomeAssistant } from "../types";
|
||||
@@ -46,8 +47,9 @@ export class HaGenericPicker extends LitElement {
|
||||
@property({ attribute: "hide-clear-icon", type: Boolean })
|
||||
public hideClearIcon = false;
|
||||
|
||||
/** To prevent lags, getItems needs to be memoized */
|
||||
@property({ attribute: false })
|
||||
public getItems?: (
|
||||
public getItems!: (
|
||||
searchString?: string,
|
||||
section?: string
|
||||
) => (PickerComboBoxItem | string)[];
|
||||
@@ -107,6 +109,8 @@ export class HaGenericPicker extends LitElement {
|
||||
|
||||
@property({ attribute: "selected-section" }) public selectedSection?: string;
|
||||
|
||||
@property({ attribute: "unknown-item-text" }) public unknownItemText?: string;
|
||||
|
||||
@query(".container") private _containerElement?: HTMLDivElement;
|
||||
|
||||
@query("ha-picker-combo-box") private _comboBox?: HaPickerComboBox;
|
||||
@@ -156,6 +160,8 @@ export class HaGenericPicker extends LitElement {
|
||||
type="button"
|
||||
class=${this._opened ? "opened" : ""}
|
||||
compact
|
||||
.unknown=${this._unknownValue(this.value, this.getItems())}
|
||||
.unknownItemText=${this.unknownItemText}
|
||||
aria-label=${ifDefined(this.label)}
|
||||
@click=${this.open}
|
||||
@clear=${this._clear}
|
||||
@@ -233,6 +239,18 @@ export class HaGenericPicker extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private _unknownValue = memoizeOne(
|
||||
(value?: string, items?: (PickerComboBoxItem | string)[]) => {
|
||||
if (value === undefined || !items) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !items.some(
|
||||
(item) => typeof item !== "string" && item.id === value
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
private _renderHelper() {
|
||||
return this.helper
|
||||
? html`<ha-input-helper-text .disabled=${this.disabled}
|
||||
|
||||
@@ -80,7 +80,7 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
|
||||
@state() private _listScrolled = false;
|
||||
|
||||
@property({ attribute: false })
|
||||
public getItems?: (
|
||||
public getItems!: (
|
||||
searchString?: string,
|
||||
section?: string
|
||||
) => (PickerComboBoxItem | string)[];
|
||||
@@ -264,11 +264,7 @@ export class HaPickerComboBox extends ScrollableFadeMixin(LitElement) {
|
||||
this.getAdditionalItems?.(searchString) || [];
|
||||
|
||||
private _getItems = () => {
|
||||
let items = [
|
||||
...(this.getItems
|
||||
? this.getItems(this._search, this.selectedSection)
|
||||
: []),
|
||||
];
|
||||
let items = [...this.getItems(this._search, this.selectedSection)];
|
||||
|
||||
if (!this.sections?.length) {
|
||||
items = items.sort((entityA, entityB) =>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { consume } from "@lit/context";
|
||||
import { mdiClose, mdiMenuDown } from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
@@ -7,8 +8,10 @@ import {
|
||||
type CSSResultGroup,
|
||||
type TemplateResult,
|
||||
} from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { localizeContext } from "../data/context";
|
||||
import type { HomeAssistant } from "../types";
|
||||
import "./ha-combo-box-item";
|
||||
import type { HaComboBoxItem } from "./ha-combo-box-item";
|
||||
import "./ha-icon-button";
|
||||
@@ -33,6 +36,10 @@ export class HaPickerField extends LitElement {
|
||||
|
||||
@property() public placeholder?: string;
|
||||
|
||||
@property({ type: Boolean, reflect: true }) public unknown = false;
|
||||
|
||||
@property({ attribute: "unknown-item-text" }) public unknownItemText?: string;
|
||||
|
||||
@property({ attribute: "hide-clear-icon", type: Boolean })
|
||||
public hideClearIcon = false;
|
||||
|
||||
@@ -41,6 +48,10 @@ export class HaPickerField extends LitElement {
|
||||
|
||||
@query("ha-combo-box-item", true) public item!: HaComboBoxItem;
|
||||
|
||||
@state()
|
||||
@consume({ context: localizeContext, subscribe: true })
|
||||
private localize!: HomeAssistant["localize"];
|
||||
|
||||
public async focus() {
|
||||
await this.updateComplete;
|
||||
await this.item?.focus();
|
||||
@@ -61,6 +72,12 @@ export class HaPickerField extends LitElement {
|
||||
${this.placeholder}
|
||||
</span>
|
||||
`}
|
||||
${this.unknown
|
||||
? html`<div slot="supporting-text" class="unknown">
|
||||
${this.unknownItemText ||
|
||||
this.localize("ui.components.combo-box.unknown_item")}
|
||||
</div>`
|
||||
: nothing}
|
||||
${showClearIcon
|
||||
? html`
|
||||
<ha-icon-button
|
||||
@@ -142,6 +159,10 @@ export class HaPickerField extends LitElement {
|
||||
background-color: var(--mdc-theme-primary);
|
||||
}
|
||||
|
||||
:host([unknown]) ha-combo-box-item {
|
||||
background-color: var(--ha-color-fill-warning-quiet-resting);
|
||||
}
|
||||
|
||||
.clear {
|
||||
margin: 0 -8px;
|
||||
--mdc-icon-button-size: 32px;
|
||||
@@ -156,6 +177,10 @@ export class HaPickerField extends LitElement {
|
||||
color: var(--secondary-text-color);
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.unknown {
|
||||
color: var(--ha-color-on-warning-normal);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -141,6 +141,9 @@ class HaServicePicker extends LitElement {
|
||||
this.hass.localize,
|
||||
this.hass.services
|
||||
)}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.service-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
|
||||
@@ -134,6 +134,9 @@ class HaUserPicker extends LitElement {
|
||||
.getItems=${this._getItems}
|
||||
.valueRenderer=${this._valueRenderer}
|
||||
.rowRenderer=${this._rowRenderer}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.user-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
|
||||
@@ -203,6 +203,9 @@ export class HaCategoryPicker extends SubscribeMixin(LitElement) {
|
||||
.getItems=${this._getItems}
|
||||
.getAdditionalItems=${this._getAdditionalItems}
|
||||
.valueRenderer=${valueRenderer}
|
||||
.unknownItemText=${this.hass.localize(
|
||||
"ui.components.category-picker.unknown"
|
||||
)}
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-generic-picker>
|
||||
|
||||
@@ -658,7 +658,8 @@
|
||||
"show_entities": "Show entities",
|
||||
"new_entity": "Create a new entity",
|
||||
"placeholder": "Select an entity",
|
||||
"create_helper": "Create a new {domain, select, \n undefined {} \n other {{domain} }\n } helper."
|
||||
"create_helper": "Create a new {domain, select, \n undefined {} \n other {{domain} }\n } helper.",
|
||||
"unknown": "Unknown entity selected"
|
||||
},
|
||||
"entity-name-picker": {
|
||||
"types": {
|
||||
@@ -779,7 +780,8 @@
|
||||
"user-picker": {
|
||||
"no_match": "No users found for {term}",
|
||||
"user": "User",
|
||||
"add_user": "Add user"
|
||||
"add_user": "Add user",
|
||||
"unknown": "Unknown user selected"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
"select_blueprint": "Select a blueprint"
|
||||
@@ -793,7 +795,8 @@
|
||||
"device": "Device",
|
||||
"unnamed_device": "Unnamed device",
|
||||
"no_area": "No area",
|
||||
"placeholder": "Select a device"
|
||||
"placeholder": "Select a device",
|
||||
"unknown": "Unknown device selected"
|
||||
},
|
||||
"category-picker": {
|
||||
"clear": "Clear",
|
||||
@@ -805,6 +808,7 @@
|
||||
"add_new": "Add new category…",
|
||||
"no_categories": "No categories available",
|
||||
"no_match": "No categories found for {term}",
|
||||
"unknown": "Unknown category selected",
|
||||
"add_dialog": {
|
||||
"title": "Add new category",
|
||||
"text": "Enter the name of the new category.",
|
||||
@@ -831,7 +835,8 @@
|
||||
"add_new": "Add new area…",
|
||||
"no_areas": "No areas available",
|
||||
"no_match": "No areas found for {term}",
|
||||
"failed_create_area": "Failed to create area."
|
||||
"failed_create_area": "Failed to create area.",
|
||||
"unknown": "Unknown area selected"
|
||||
},
|
||||
"floor-picker": {
|
||||
"clear": "Clear",
|
||||
@@ -841,7 +846,8 @@
|
||||
"add_new": "Add new floor…",
|
||||
"no_floors": "No floors available",
|
||||
"no_match": "No floors found for {term}",
|
||||
"failed_create_floor": "Failed to create floor."
|
||||
"failed_create_floor": "Failed to create floor.",
|
||||
"unknown": "Unknown floor selected"
|
||||
},
|
||||
"area-filter": {
|
||||
"title": "Areas",
|
||||
@@ -858,7 +864,8 @@
|
||||
"no_match": "No statistics found for {term}",
|
||||
"no_state": "Entity without state",
|
||||
"missing_entity": "Why is my entity not listed?",
|
||||
"learn_more": "Learn more about statistics"
|
||||
"learn_more": "Learn more about statistics",
|
||||
"unknown": "Unknown statistic selected"
|
||||
},
|
||||
"addon-picker": {
|
||||
"addon": "Add-on",
|
||||
@@ -998,7 +1005,8 @@
|
||||
},
|
||||
"service-picker": {
|
||||
"action": "Action",
|
||||
"no_match": "No matching actions found"
|
||||
"no_match": "No matching actions found",
|
||||
"unknown": "Unknown action selected"
|
||||
},
|
||||
"service-control": {
|
||||
"required": "This field is required",
|
||||
@@ -1296,7 +1304,8 @@
|
||||
},
|
||||
"combo-box": {
|
||||
"no_match": "No matching items found",
|
||||
"no_items": "No items available"
|
||||
"no_items": "No items available",
|
||||
"unknown_item": "Unknown item"
|
||||
},
|
||||
"suggest_with_ai": {
|
||||
"label": "Suggest",
|
||||
|
||||
Reference in New Issue
Block a user