Add a geo_location selector to map editor (#22538)

* Add a geo_location selector to map editor

* delete unused
This commit is contained in:
karwosts 2024-10-29 00:36:58 -07:00 committed by GitHub
parent 7a1838ee1a
commit 64e21e185c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 129 deletions

View File

@ -1,123 +0,0 @@
import { mdiClose } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-icon-button";
import "../../../components/ha-textfield";
import { HomeAssistant } from "../../../types";
import { EditorTarget } from "../editor/types";
@customElement("hui-input-list-editor")
export class HuiInputListEditor extends LitElement {
@property({ type: Array }) public value?: string[];
@property({ attribute: false }) public hass?: HomeAssistant;
@property() public inputLabel?: string;
protected render() {
if (!this.value) {
return nothing;
}
return html`
${this.value.map(
(listEntry, index) => html`
<ha-textfield
.label=${this.inputLabel}
.value=${listEntry}
.configValue=${"entry"}
.index=${index}
@input=${this._valueChanged}
@blur=${this._consolidateEntries}
@keydown=${this._handleKeyDown}
iconTrailing
><ha-icon-button
slot="trailingIcon"
class="clear-button"
.path=${mdiClose}
no-ripple
@click=${this._removeEntry}
.label=${this.hass!.localize("ui.common.clear")}
>
</ha-icon-button>
</ha-textfield>
`
)}
<ha-textfield
.label=${this.inputLabel}
@change=${this._addEntry}
></ha-textfield>
`;
}
private _addEntry(ev: Event): void {
const target = ev.target! as EditorTarget;
if (target.value === "") {
return;
}
const newEntries = this.value!.concat(target.value as string);
target.value = "";
fireEvent(this, "value-changed", {
value: newEntries,
});
(ev.target! as LitElement).blur();
}
private _valueChanged(ev: Event): void {
ev.stopPropagation();
const target = ev.target! as EditorTarget;
const newEntries = this.value!.concat();
newEntries[target.index!] = target.value!;
fireEvent(this, "value-changed", {
value: newEntries,
});
}
private _handleKeyDown(ev: KeyboardEvent) {
if (ev.key === "Enter") {
ev.stopPropagation();
this._consolidateEntries(ev);
}
}
private _consolidateEntries(ev: Event): void {
const target = ev.target! as EditorTarget;
if (target.value === "") {
const newEntries = this.value!.concat();
newEntries.splice(target.index!, 1);
fireEvent(this, "value-changed", {
value: newEntries,
});
}
}
private _removeEntry(ev: Event): void {
const parent = (ev.currentTarget as any).parentElement;
const newEntries = this.value!.concat();
newEntries.splice(parent.index!, 1);
fireEvent(this, "value-changed", {
value: newEntries,
});
}
static get styles(): CSSResultGroup {
return css`
ha-icon-button {
margin-right: -24px;
margin-inline-end: -24px;
margin-inline-start: initial;
color: var(--secondary-text-color);
}
ha-textfield {
display: block;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-input-list-editor": HuiInputListEditor;
}
}

View File

@ -15,15 +15,17 @@ import {
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../common/dom/fire_event";
import { hasLocation } from "../../../../common/entity/has_location";
import { computeDomain } from "../../../../common/entity/compute_domain";
import "../../../../components/ha-form/ha-form";
import { SchemaUnion } from "../../../../components/ha-form/types";
import type { SelectSelector } from "../../../../data/selector";
import "../../../../components/ha-formfield";
import "../../../../components/ha-switch";
import "../../../../components/ha-selector/ha-selector-select";
import { HomeAssistant, ValueChangedEvent } from "../../../../types";
import { DEFAULT_HOURS_TO_SHOW, DEFAULT_ZOOM } from "../../cards/hui-map-card";
import { MapCardConfig } from "../../cards/types";
import "../../components/hui-entity-editor";
import "../../components/hui-input-list-editor";
import { EntityConfig } from "../../entity-rows/types";
import { LovelaceCardEditor } from "../../types";
import { processEditorEntities } from "../process-editor-entities";
@ -67,6 +69,8 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
@state() private _configEntities?: EntityConfig[];
@state() private _possibleGeoSources?: { value: string; label?: string }[];
private _schema = memoizeOne(
(localize: LocalizeFunc) =>
[
@ -166,17 +170,40 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
)}
</h3>
<hui-input-list-editor
.inputLabel=${this.hass.localize(
"ui.panel.lovelace.editor.card.map.source"
)}
<ha-selector-select
.label=${this.hass.localize("ui.panel.lovelace.editor.card.map.source")}
.required=${false}
.hass=${this.hass}
.value=${this._geo_location_sources}
@value-changed=${this._geoSourcesChanged}
></hui-input-list-editor>
.selector=${this._selectSchema(
this._possibleGeoSources,
this.hass.localize
)}
></ha-selector-select>
`;
}
private _selectSchema = memoizeOne(
(options, localize: LocalizeFunc): SelectSelector => ({
select: {
sort: true,
multiple: true,
custom_value: true,
options: options.length
? options
: [
{
value: "",
label: localize(
"ui.panel.lovelace.editor.card.map.no_geo_location_sources"
),
},
],
},
})
);
private _entitiesValueChanged(ev: EntitiesEditorEvent): void {
if (ev.detail && ev.detail.entities) {
this._config = { ...this._config!, entities: ev.detail.entities };
@ -213,6 +240,25 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
fireEvent(this, "config-changed", { config: ev.detail.value });
}
protected willUpdate() {
if (this.hass && !this._possibleGeoSources) {
const sources: Record<string, string> = {};
Object.entries(this.hass.states).forEach(([entity_id, stateObj]) => {
const domain = computeDomain(entity_id);
if (domain === "geo_location" && stateObj.attributes.source) {
sources[stateObj.attributes.source] = stateObj.attributes.attribution;
}
});
this._possibleGeoSources = Object.entries(sources).map(
([source, attribution]) => ({
value: source,
label: attribution || source,
})
);
}
}
private _computeLabelCallback = (
schema: SchemaUnion<ReturnType<typeof this._schema>>
) => {

View File

@ -6086,6 +6086,7 @@
"map": {
"name": "Map",
"geo_location_sources": "Geolocation sources",
"no_geo_location_sources": "No geolocation sources available",
"dark_mode": "Dark mode?",
"appearance": "Appearance",
"theme_mode": "Theme Mode",