Geolocation source configurable in map editor (#2755)

* wip

* added input list editor

* input label configurable, variables renamed

* new input field working as expected now

* fix lint issues

* fix lint issues

* fix lint issues and code clean-up

* fix lint issues

* uses property decorator now

* change the way css is included

* moved heading from input list editor to map card editor

* moved styling of input list editor to map card editor

* stopped propagating event

* return new value in event instead of changing the input value

* added button to clear value; consolidate value when leaving input field

* fix lint issues

* fix lint issues

* using customElement decorator

* fix lint issues
This commit is contained in:
Malte Franken 2019-03-08 09:06:40 +11:00 committed by Paulus Schoutsen
parent f5d0162aec
commit ed9dff99d3
2 changed files with 164 additions and 10 deletions

View File

@ -0,0 +1,115 @@
import {
html,
css,
LitElement,
property,
TemplateResult,
CSSResult,
customElement,
} from "lit-element";
import "@polymer/paper-input/paper-input";
import { HomeAssistant } from "../../../types";
import { fireEvent } from "../../../common/dom/fire_event";
import { EditorTarget } from "../editor/types";
@customElement("hui-input-list-editor")
export class HuiInputListEditor extends LitElement {
@property() protected value?: string[];
@property() protected hass?: HomeAssistant;
@property() protected inputLabel?: string;
protected render(): TemplateResult | void {
if (!this.value) {
return html``;
}
return html`
${this.value.map((listEntry, index) => {
return html`
<paper-input
label="${this.inputLabel}"
.value="${listEntry}"
.configValue="${"entry"}"
.index="${index}"
@value-changed="${this._valueChanged}"
@blur="${this._consolidateEntries}"
><paper-icon-button
slot="suffix"
class="clear-button"
icon="hass:close"
no-ripple
@click="${this._removeEntry}"
>Clear</paper-icon-button
></paper-input
>
`;
})}
<paper-input
label="${this.inputLabel}"
@change="${this._addEntry}"
></paper-input>
`;
}
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 _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(): CSSResult {
return css`
paper-input > paper-icon-button {
width: 24px;
height: 24px;
padding: 2px;
color: var(--secondary-text-color);
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-input-list-editor": HuiInputListEditor;
}
}

View File

@ -1,9 +1,11 @@
import { import {
html, html,
css,
LitElement, LitElement,
TemplateResult, TemplateResult,
customElement, customElement,
property, property,
CSSResult,
} from "lit-element"; } from "lit-element";
import "@polymer/paper-input/paper-input"; import "@polymer/paper-input/paper-input";
@ -16,8 +18,10 @@ import { MapCardConfig } from "../../cards/hui-map-card";
import { configElementStyle } from "./config-elements-style"; import { configElementStyle } from "./config-elements-style";
import { processEditorEntities } from "../process-editor-entities"; import { processEditorEntities } from "../process-editor-entities";
import { EntityConfig } from "../../entity-rows/types"; import { EntityConfig } from "../../entity-rows/types";
import { PolymerChangedEvent } from "../../../../polymer-types";
import "../../components/hui-entity-editor"; import "../../components/hui-entity-editor";
import "../../components/hui-input-list-editor";
const entitiesConfigStruct = struct.union([ const entitiesConfigStruct = struct.union([
{ {
@ -34,6 +38,7 @@ const cardConfigStruct = struct({
aspect_ratio: "string?", aspect_ratio: "string?",
default_zoom: "number?", default_zoom: "number?",
entities: [entitiesConfigStruct], entities: [entitiesConfigStruct],
geo_location_sources: "array?",
}); });
@customElement("hui-map-card-editor") @customElement("hui-map-card-editor")
@ -62,6 +67,10 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
return this._config!.default_zoom || NaN; return this._config!.default_zoom || NaN;
} }
get _geo_location_sources(): string[] {
return this._config!.geo_location_sources || [];
}
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { if (!this.hass) {
return html``; return html``;
@ -94,31 +103,53 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
<hui-entity-editor <hui-entity-editor
.hass="${this.hass}" .hass="${this.hass}"
.entities="${this._configEntities}" .entities="${this._configEntities}"
@entities-changed="${this._valueChanged}" @entities-changed="${this._entitiesValueChanged}"
></hui-entity-editor> ></hui-entity-editor>
<h3>Geolocation Sources</h3>
<div class="geo_location_sources">
<hui-input-list-editor
inputLabel="Source"
.hass="${this.hass}"
.value="${this._geo_location_sources}"
.configValue="${"geo_location_sources"}"
@value-changed="${this._valueChanged}"
></hui-input-list-editor>
</div>
</div> </div>
`; `;
} }
private _valueChanged(ev: EntitiesEditorEvent): void { private _entitiesValueChanged(ev: EntitiesEditorEvent): void {
if (!this._config || !this.hass) { if (!this._config || !this.hass) {
return; return;
} }
const target = ev.target! as EditorTarget;
if (target.configValue && this[`_${target.configValue}`] === target.value) {
return;
}
if (ev.detail && ev.detail.entities) { if (ev.detail && ev.detail.entities) {
this._config.entities = ev.detail.entities; this._config.entities = ev.detail.entities;
this._configEntities = processEditorEntities(this._config.entities); this._configEntities = processEditorEntities(this._config.entities);
} else if (target.configValue) { fireEvent(this, "config-changed", { config: this._config });
}
}
private _valueChanged(ev: PolymerChangedEvent<any>): void {
if (!this._config || !this.hass) {
return;
}
const target = ev.target! as EditorTarget;
if ( if (
target.value === "" || target.configValue &&
(target.type === "number" && isNaN(Number(target.value))) ev.detail &&
this[`_${target.configValue}`] === ev.detail.value
) {
return;
}
if (target.configValue && ev.detail) {
if (
ev.detail.value === "" ||
(target.type === "number" && isNaN(Number(ev.detail.value)))
) { ) {
delete this._config[target.configValue!]; delete this._config[target.configValue!];
} else { } else {
let value: any = target.value; let value: any = ev.detail.value;
if (target.type === "number") { if (target.type === "number") {
value = Number(value); value = Number(value);
} }
@ -130,6 +161,14 @@ export class HuiMapCardEditor extends LitElement implements LovelaceCardEditor {
} }
fireEvent(this, "config-changed", { config: this._config }); fireEvent(this, "config-changed", { config: this._config });
} }
static get styles(): CSSResult {
return css`
.geo_location_sources {
padding-left: 20px;
}
`;
}
} }
declare global { declare global {