CountrySelector (#18035)

This commit is contained in:
G Johansson 2023-10-12 16:47:28 +02:00 committed by GitHub
parent 6d1e923b83
commit 4c94ac5dda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 18 deletions

View File

@ -269,37 +269,61 @@ export class HaCountryPicker extends LitElement {
@property() public label?: string; @property() public label?: string;
@property() public countries?: string[];
@property() public helper?: string;
@property({ type: Boolean }) public required = false; @property({ type: Boolean }) public required = false;
@property({ type: Boolean, reflect: true }) public disabled = false; @property({ type: Boolean, reflect: true }) public disabled = false;
private _getOptions = memoizeOne((language?: string) => { @property({ type: Boolean }) public noSort = false;
const countryDisplayNames =
Intl && "DisplayNames" in Intl
? new Intl.DisplayNames(language, {
type: "region",
fallback: "code",
})
: undefined;
const options = COUNTRIES.map((country) => ({ private _getOptions = memoizeOne(
value: country, (language?: string, countries?: string[]) => {
label: countryDisplayNames ? countryDisplayNames.of(country)! : country, let options: { label: string; value: string }[] = [];
})); const countryDisplayNames =
options.sort((a, b) => Intl && "DisplayNames" in Intl
caseInsensitiveStringCompare(a.label, b.label, language) ? new Intl.DisplayNames(language, {
); type: "region",
return options; fallback: "code",
}); })
: undefined;
if (countries) {
options = countries.map((country) => ({
value: country,
label: countryDisplayNames
? countryDisplayNames.of(country)!
: country,
}));
} else {
options = COUNTRIES.map((country) => ({
value: country,
label: countryDisplayNames
? countryDisplayNames.of(country)!
: country,
}));
}
if (!this.noSort) {
options.sort((a, b) =>
caseInsensitiveStringCompare(a.label, b.label, language)
);
}
return options;
}
);
protected render() { protected render() {
const options = this._getOptions(this.language); const options = this._getOptions(this.language, this.countries);
return html` return html`
<ha-select <ha-select
.label=${this.label} .label=${this.label}
.value=${this.value} .value=${this.value}
.required=${this.required} .required=${this.required}
.helper=${this.helper}
.disabled=${this.disabled} .disabled=${this.disabled}
@selected=${this._changed} @selected=${this._changed}
@closed=${stopPropagation} @closed=${stopPropagation}

View File

@ -66,6 +66,10 @@ export const computeInitialHaFormData = (
typeof firstOption === "string" ? firstOption : firstOption.value; typeof firstOption === "string" ? firstOption : firstOption.value;
data[field.name] = selector.select.multiple ? [val] : val; data[field.name] = selector.select.multiple ? [val] : val;
} }
} else if ("country" in selector) {
if (selector.country?.countries?.length) {
data[field.name] = selector.country.countries[0];
}
} else if ("duration" in selector) { } else if ("duration" in selector) {
data[field.name] = { data[field.name] = {
hours: 0, hours: 0,

View File

@ -0,0 +1,49 @@
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { CountrySelector } from "../../data/selector";
import { HomeAssistant } from "../../types";
import "../ha-country-picker";
@customElement("ha-selector-country")
export class HaCountrySelector extends LitElement {
@property() public hass!: HomeAssistant;
@property() public selector!: CountrySelector;
@property() public value?: any;
@property() public label?: string;
@property() public helper?: string;
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public required = true;
protected render() {
return html`
<ha-country-picker
.hass=${this.hass}
.value=${this.value}
.label=${this.label}
.helper=${this.helper}
.countries=${this.selector.country?.countries}
.noSort=${this.selector.country?.no_sort}
.disabled=${this.disabled}
.required=${this.required}
></ha-country-picker>
`;
}
static styles = css`
ha-country-picker {
width: 100%;
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"ha-selector-country": HaCountrySelector;
}
}

View File

@ -21,6 +21,7 @@ const LOAD_ELEMENTS = {
config_entry: () => import("./ha-selector-config-entry"), config_entry: () => import("./ha-selector-config-entry"),
conversation_agent: () => import("./ha-selector-conversation-agent"), conversation_agent: () => import("./ha-selector-conversation-agent"),
constant: () => import("./ha-selector-constant"), constant: () => import("./ha-selector-constant"),
country: () => import("./ha-selector-country"),
date: () => import("./ha-selector-date"), date: () => import("./ha-selector-date"),
datetime: () => import("./ha-selector-datetime"), datetime: () => import("./ha-selector-datetime"),
device: () => import("./ha-selector-device"), device: () => import("./ha-selector-device"),

View File

@ -23,6 +23,7 @@ export type Selector =
| ConversationAgentSelector | ConversationAgentSelector
| ConfigEntrySelector | ConfigEntrySelector
| ConstantSelector | ConstantSelector
| CountrySelector
| DateSelector | DateSelector
| DateTimeSelector | DateTimeSelector
| DeviceSelector | DeviceSelector
@ -124,6 +125,13 @@ export interface ConstantSelector {
} | null; } | null;
} }
export interface CountrySelector {
country: {
countries: string[];
no_sort?: boolean;
} | null;
}
export interface DateSelector { export interface DateSelector {
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types
date: {} | null; date: {} | null;

View File

@ -418,6 +418,9 @@
"conversation_agent": "Conversation agent", "conversation_agent": "Conversation agent",
"none": "None" "none": "None"
}, },
"country-picker": {
"country": "Country"
},
"pipeline-picker": { "pipeline-picker": {
"pipeline": "Assistant", "pipeline": "Assistant",
"preferred": "Preferred assistant ({preferred})", "preferred": "Preferred assistant ({preferred})",