mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-25 13:57:21 +00:00
Add UI for new selectors (#7822)
This commit is contained in:
parent
e3293837a8
commit
e1add14453
@ -76,7 +76,7 @@ class HaExpansionPanel extends LitElement {
|
||||
|
||||
.summary {
|
||||
display: flex;
|
||||
padding: 0px 16px;
|
||||
padding: var(--expansion-panel-summary-padding, 0px 16px);
|
||||
min-height: 48px;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
30
src/components/ha-selector/ha-selector-area.ts
Normal file
30
src/components/ha-selector/ha-selector-area.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { customElement, html, LitElement, property } from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { AreaSelector } from "../../data/selector";
|
||||
import "../ha-area-picker";
|
||||
|
||||
@customElement("ha-selector-area")
|
||||
export class HaAreaSelector extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public selector!: AreaSelector;
|
||||
|
||||
@property() public value?: any;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
protected render() {
|
||||
return html`<ha-area-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
no-add
|
||||
></ha-area-picker>`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-area": HaAreaSelector;
|
||||
}
|
||||
}
|
54
src/components/ha-selector/ha-selector-boolean.ts
Normal file
54
src/components/ha-selector/ha-selector-boolean.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import "../ha-formfield";
|
||||
import "../ha-switch";
|
||||
|
||||
@customElement("ha-selector-boolean")
|
||||
export class HaBooleanSelector extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public value?: number;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
protected render() {
|
||||
return html` <ha-formfield alignEnd spaceBetween .label=${this.label}>
|
||||
<ha-switch
|
||||
.checked=${this.value}
|
||||
@change=${this._handleChange}
|
||||
></ha-switch>
|
||||
</ha-formfield>`;
|
||||
}
|
||||
|
||||
private _handleChange(ev) {
|
||||
const value = ev.target.checked;
|
||||
if (this.value === value) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "value-changed", { value });
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
ha-formfield {
|
||||
width: 100%;
|
||||
margin: 16px 0;
|
||||
--mdc-typography-body2-font-size: 1em;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-boolean": HaBooleanSelector;
|
||||
}
|
||||
}
|
@ -38,6 +38,12 @@ export class HaDeviceSelector extends LitElement {
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
.deviceFilter=${(device) => this._filterDevices(device)}
|
||||
.includeDeviceClasses=${this.selector.device.entity?.device_class
|
||||
? [this.selector.device.entity.device_class]
|
||||
: undefined}
|
||||
.includeDomains=${this.selector.device.entity?.domain
|
||||
? [this.selector.device.entity.domain]
|
||||
: undefined}
|
||||
allow-custom-entity
|
||||
></ha-device-picker>`;
|
||||
}
|
||||
|
104
src/components/ha-selector/ha-selector-number.ts
Normal file
104
src/components/ha-selector/ha-selector-number.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { NumberSelector } from "../../data/selector";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "../ha-slider";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
|
||||
@customElement("ha-selector-number")
|
||||
export class HaNumberSelector extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public selector!: NumberSelector;
|
||||
|
||||
@property() public value?: number;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
protected render() {
|
||||
return html`${this.label}
|
||||
${this.selector.number.mode === "slider"
|
||||
? html`<ha-slider
|
||||
.min=${this.selector.number.min}
|
||||
.max=${this.selector.number.max}
|
||||
.value=${this._value}
|
||||
.step=${this.selector.number.step}
|
||||
pin
|
||||
ignore-bar-touch
|
||||
@change=${this._handleSliderChange}
|
||||
>
|
||||
</ha-slider>`
|
||||
: ""}
|
||||
<paper-input
|
||||
pattern="[0-9]+([\\.][0-9]+)?"
|
||||
.label=${this.selector.number.mode === "slider"
|
||||
? undefined
|
||||
: this.label}
|
||||
.noLabelFloat=${this.selector.number.mode === "slider"}
|
||||
class=${classMap({ single: this.selector.number.mode === "box" })}
|
||||
.min=${this.selector.number.min}
|
||||
.max=${this.selector.number.max}
|
||||
.value=${this._value}
|
||||
.step=${this.selector.number.step}
|
||||
type="number"
|
||||
auto-validate
|
||||
@value-changed=${this._handleInputChange}
|
||||
>
|
||||
${this.selector.number.unit_of_measurement
|
||||
? html`<div slot="suffix">
|
||||
${this.selector.number.unit_of_measurement}
|
||||
</div>`
|
||||
: ""}
|
||||
</paper-input>`;
|
||||
}
|
||||
|
||||
private get _value() {
|
||||
return this.value || 0;
|
||||
}
|
||||
|
||||
private _handleInputChange(ev) {
|
||||
const value = ev.detail.value;
|
||||
if (this._value === value) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "value-changed", { value });
|
||||
}
|
||||
|
||||
private _handleSliderChange(ev) {
|
||||
const value = ev.target.value;
|
||||
if (this._value === value) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "value-changed", { value });
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
:host {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
ha-slider {
|
||||
flex: 1;
|
||||
}
|
||||
.single {
|
||||
flex: 1;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-number": HaNumberSelector;
|
||||
}
|
||||
}
|
59
src/components/ha-selector/ha-selector-time.ts
Normal file
59
src/components/ha-selector/ha-selector-time.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { customElement, html, LitElement, property } from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { TimeSelector } from "../../data/selector";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import "../paper-time-input";
|
||||
|
||||
const test = new Date().toLocaleString();
|
||||
const useAMPM = test.includes("AM") || test.includes("PM");
|
||||
|
||||
@customElement("ha-selector-time")
|
||||
export class HaTimeSelector extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public selector!: TimeSelector;
|
||||
|
||||
@property() public value?: string;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
protected render() {
|
||||
const parts = this.value?.split(":") || [];
|
||||
const hours = useAMPM ? parts[0] ?? "12" : parts[0] ?? "0";
|
||||
|
||||
return html`
|
||||
<paper-time-input
|
||||
.label=${this.label}
|
||||
.hour=${useAMPM && Number(hours) > 12 ? Number(hours) - 12 : hours}
|
||||
.min=${parts[1] ?? "00"}
|
||||
.sec=${parts[2] ?? "00"}
|
||||
.format=${useAMPM ? 12 : 24}
|
||||
.amPm=${useAMPM && (Number(hours) > 12 ? "PM" : "AM")}
|
||||
@change=${this._timeChanged}
|
||||
@am-pm-changed=${this._timeChanged}
|
||||
hide-label
|
||||
enable-second
|
||||
></paper-time-input>
|
||||
`;
|
||||
}
|
||||
|
||||
private _timeChanged(ev) {
|
||||
let value = ev.target.value;
|
||||
if (useAMPM) {
|
||||
let hours = Number(ev.target.hour);
|
||||
if (ev.target.amPm === "PM") {
|
||||
hours += 12;
|
||||
}
|
||||
value = `${hours}:${ev.target.min}:${ev.target.sec}`;
|
||||
}
|
||||
fireEvent(this, "value-changed", {
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-time": HaTimeSelector;
|
||||
}
|
||||
}
|
@ -4,6 +4,10 @@ import { HomeAssistant } from "../../types";
|
||||
|
||||
import "./ha-selector-entity";
|
||||
import "./ha-selector-device";
|
||||
import "./ha-selector-area";
|
||||
import "./ha-selector-number";
|
||||
import "./ha-selector-boolean";
|
||||
import "./ha-selector-time";
|
||||
import { Selector } from "../../data/selector";
|
||||
|
||||
@customElement("ha-selector")
|
||||
|
@ -97,6 +97,7 @@ export class PaperTimeInput extends PolymerElement {
|
||||
.time-input-wrap {
|
||||
@apply --layout-horizontal;
|
||||
@apply --layout-no-wrap;
|
||||
justify-content: var(--paper-time-input-justify-content, normal);
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
|
@ -11,18 +11,19 @@ export interface Blueprint {
|
||||
export interface BlueprintMetaData {
|
||||
domain: string;
|
||||
name: string;
|
||||
input?: Record<string, BlueprintInput | null>;
|
||||
description?: string;
|
||||
input: Record<string, BlueprintInput | null>;
|
||||
source_url?: string;
|
||||
}
|
||||
|
||||
export interface BlueprintInput {
|
||||
name?: string;
|
||||
description?: string;
|
||||
selector?: Selector;
|
||||
default?: any;
|
||||
}
|
||||
|
||||
export interface BlueprintImportResult {
|
||||
url: string;
|
||||
suggested_filename: string;
|
||||
raw_data: string;
|
||||
blueprint: Blueprint;
|
||||
|
@ -5,10 +5,10 @@ export interface InputNumber {
|
||||
name: string;
|
||||
min: number;
|
||||
max: number;
|
||||
step: number;
|
||||
mode: "box" | "slider";
|
||||
icon?: string;
|
||||
initial?: number;
|
||||
step?: number;
|
||||
mode?: "box" | "slider";
|
||||
unit_of_measurement?: string;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,10 @@
|
||||
export type Selector = EntitySelector | DeviceSelector;
|
||||
export type Selector =
|
||||
| EntitySelector
|
||||
| DeviceSelector
|
||||
| AreaSelector
|
||||
| NumberSelector
|
||||
| BooleanSelector
|
||||
| TimeSelector;
|
||||
|
||||
export interface EntitySelector {
|
||||
entity: {
|
||||
@ -13,5 +19,31 @@ export interface DeviceSelector {
|
||||
integration?: string;
|
||||
manufacturer?: string;
|
||||
model?: string;
|
||||
entity?: EntitySelector["entity"];
|
||||
};
|
||||
}
|
||||
|
||||
export interface AreaSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
area: {};
|
||||
}
|
||||
|
||||
export interface NumberSelector {
|
||||
number: {
|
||||
min: number;
|
||||
max: number;
|
||||
step: number;
|
||||
mode: "box" | "slider";
|
||||
unit_of_measurement?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface BooleanSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
boolean: {};
|
||||
}
|
||||
|
||||
export interface TimeSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
time: {};
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import {
|
||||
import "../../../components/ha-blueprint-picker";
|
||||
import "../../../components/ha-circular-progress";
|
||||
import "../../../components/ha-selector/ha-selector";
|
||||
import "../../../components/ha-settings-row";
|
||||
|
||||
@customElement("blueprint-automation-editor")
|
||||
export class HaBlueprintAutomationEditor extends LitElement {
|
||||
@ -40,7 +41,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
|
||||
@property() public isWide!: boolean;
|
||||
|
||||
@property() public narrow!: boolean;
|
||||
@property({ reflect: true, type: Boolean }) public narrow!: boolean;
|
||||
|
||||
@property() public config!: BlueprintAutomationConfig;
|
||||
|
||||
@ -125,7 +126,6 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
)}</span
|
||||
>
|
||||
<ha-card>
|
||||
<div class="card-content">
|
||||
<div class="blueprint-picker-container">
|
||||
${this._blueprints
|
||||
? Object.keys(this._blueprints).length
|
||||
@ -153,7 +153,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
|
||||
${this.config.use_blueprint.path
|
||||
? blueprint && "error" in blueprint
|
||||
? html`<p class="warning">
|
||||
? html`<p class="warning padding">
|
||||
There is an error in this Blueprint: ${blueprint.error}
|
||||
</p>`
|
||||
: html`${blueprint?.metadata.description
|
||||
@ -168,32 +168,36 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
</h3>
|
||||
${Object.entries(blueprint.metadata.input).map(
|
||||
([key, value]) =>
|
||||
html`<div>
|
||||
${value?.description}
|
||||
html`<ha-settings-row .narrow=${this.narrow}>
|
||||
<span slot="heading">${value?.name || key}</span>
|
||||
<span slot="description"
|
||||
>${value?.description}</span
|
||||
>
|
||||
${value?.selector
|
||||
? html`<ha-selector
|
||||
.hass=${this.hass}
|
||||
.selector=${value.selector}
|
||||
.key=${key}
|
||||
.label=${value?.name || key}
|
||||
.value=${this.config.use_blueprint.input &&
|
||||
this.config.use_blueprint.input[key]}
|
||||
.value=${(this.config.use_blueprint.input &&
|
||||
this.config.use_blueprint.input[key]) ||
|
||||
value?.default}
|
||||
@value-changed=${this._inputChanged}
|
||||
></ha-selector>`
|
||||
: html`<paper-input
|
||||
.key=${key}
|
||||
.label=${value?.name || key}
|
||||
.value=${this.config.use_blueprint.input &&
|
||||
this.config.use_blueprint.input[key]}
|
||||
@value-changed=${this._inputChanged}
|
||||
no-label-float
|
||||
></paper-input>`}
|
||||
</div>`
|
||||
</ha-settings-row>`
|
||||
)}`
|
||||
: this.hass.localize(
|
||||
: html`<p class="padding">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.blueprint.no_inputs"
|
||||
)}`
|
||||
)}
|
||||
</p>`}`
|
||||
: ""}
|
||||
</div>
|
||||
</ha-card>
|
||||
</ha-config-section>`;
|
||||
}
|
||||
@ -279,16 +283,20 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
font-weight: bold;
|
||||
color: var(--error-color);
|
||||
}
|
||||
.padding {
|
||||
padding: 16px;
|
||||
}
|
||||
.content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.blueprint-picker-container {
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
h3 {
|
||||
margin-top: 16px;
|
||||
margin: 16px;
|
||||
}
|
||||
span[slot="introduction"] a {
|
||||
color: var(--primary-color);
|
||||
@ -299,6 +307,16 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
ha-entity-toggle {
|
||||
margin-right: 8px;
|
||||
}
|
||||
ha-settings-row {
|
||||
--paper-time-input-justify-content: flex-end;
|
||||
border-top: 1px solid var(--divider-color);
|
||||
}
|
||||
:host(:not([narrow])) ha-settings-row paper-input {
|
||||
width: 50%;
|
||||
}
|
||||
:host(:not([narrow])) ha-settings-row ha-selector {
|
||||
width: 50%;
|
||||
}
|
||||
mwc-fab {
|
||||
position: relative;
|
||||
bottom: calc(-80px - env(safe-area-inset-bottom));
|
||||
|
@ -205,12 +205,14 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
${"use_blueprint" in this._config
|
||||
? html`<blueprint-automation-editor
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.stateObj=${stateObj}
|
||||
.config=${this._config}
|
||||
@value-changed=${this._valueChanged}
|
||||
></blueprint-automation-editor>`
|
||||
: html`<manual-automation-editor
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.stateObj=${stateObj}
|
||||
.config=${this._config}
|
||||
@value-changed=${this._valueChanged}
|
||||
|
@ -23,6 +23,7 @@ import {
|
||||
importBlueprint,
|
||||
saveBlueprint,
|
||||
} from "../../../data/blueprint";
|
||||
import "../../../components/ha-expansion-panel";
|
||||
|
||||
@customElement("ha-dialog-import-blueprint")
|
||||
class DialogImportBlueprint extends LitElement {
|
||||
@ -71,7 +72,9 @@ class DialogImportBlueprint extends LitElement {
|
||||
html`<b>${this._result.blueprint.metadata.name}</b>`,
|
||||
"domain",
|
||||
this._result.blueprint.metadata.domain
|
||||
)} <br /><br />
|
||||
)}
|
||||
<br />
|
||||
${this._result.blueprint.metadata.description}
|
||||
${this._result.validation_errors
|
||||
? html`
|
||||
<p class="error">
|
||||
@ -94,7 +97,14 @@ class DialogImportBlueprint extends LitElement {
|
||||
)}
|
||||
></paper-input>
|
||||
`}
|
||||
<pre>${this._result.raw_data}</pre>`
|
||||
<ha-expansion-panel>
|
||||
<span slot="title"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.blueprint.add.raw_blueprint"
|
||||
)}</span
|
||||
>
|
||||
<pre>${this._result.raw_data}</pre>
|
||||
</ha-expansion-panel>`
|
||||
: html`${this.hass.localize(
|
||||
"ui.panel.config.blueprint.add.import_introduction"
|
||||
)}<paper-input
|
||||
@ -180,7 +190,7 @@ class DialogImportBlueprint extends LitElement {
|
||||
this._result!.blueprint.metadata.domain,
|
||||
filename,
|
||||
this._result!.raw_data,
|
||||
this._result!.url
|
||||
this._result!.blueprint.metadata.source_url
|
||||
);
|
||||
this._params.importedCallback();
|
||||
this.closeDialog();
|
||||
@ -192,7 +202,14 @@ class DialogImportBlueprint extends LitElement {
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [haStyleDialog, css``];
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-expansion-panel {
|
||||
--expansion-panel-summary-padding: 0;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,8 +80,7 @@ class HaBlueprintOverview extends LitElement {
|
||||
});
|
||||
|
||||
private _columns = memoizeOne(
|
||||
(narrow, _language): DataTableColumnContainer => {
|
||||
const columns: DataTableColumnContainer = {
|
||||
(narrow, _language): DataTableColumnContainer => ({
|
||||
name: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.blueprint.overview.headers.name"
|
||||
@ -90,25 +89,35 @@ class HaBlueprintOverview extends LitElement {
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
},
|
||||
};
|
||||
|
||||
if (narrow) {
|
||||
columns.name.template = (name, entity: any) => {
|
||||
return html`
|
||||
template: narrow
|
||||
? (name, entity: any) =>
|
||||
html`
|
||||
${name}<br />
|
||||
<div class="secondary">
|
||||
${entity.path}
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
columns.create = {
|
||||
`
|
||||
: undefined,
|
||||
},
|
||||
path: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.blueprint.overview.headers.file_name"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
hidden: narrow,
|
||||
direction: "asc",
|
||||
width: "25%",
|
||||
},
|
||||
create: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
type: narrow ? "icon-button" : undefined,
|
||||
width: narrow ? undefined : "180px",
|
||||
template: (_, blueprint: any) =>
|
||||
blueprint.error
|
||||
? ""
|
||||
: html` <mwc-icon-button
|
||||
: narrow
|
||||
? html`<mwc-icon-button
|
||||
.blueprint=${blueprint}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.blueprint.overview.use_blueprint"
|
||||
@ -118,24 +127,7 @@ class HaBlueprintOverview extends LitElement {
|
||||
)}
|
||||
@click=${(ev) => this._createNew(ev)}
|
||||
><ha-svg-icon .path=${mdiRobot}></ha-svg-icon
|
||||
></mwc-icon-button>`,
|
||||
};
|
||||
} else {
|
||||
columns.path = {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.blueprint.overview.headers.file_name"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
width: "25%",
|
||||
};
|
||||
columns.create = {
|
||||
title: "",
|
||||
width: "180px",
|
||||
template: (_, blueprint: any) =>
|
||||
blueprint.error
|
||||
? ""
|
||||
></mwc-icon-button>`
|
||||
: html`<mwc-button
|
||||
.blueprint=${blueprint}
|
||||
@click=${(ev) => this._createNew(ev)}
|
||||
@ -144,10 +136,8 @@ class HaBlueprintOverview extends LitElement {
|
||||
"ui.panel.config.blueprint.overview.use_blueprint"
|
||||
)}
|
||||
</mwc-button>`,
|
||||
};
|
||||
}
|
||||
|
||||
columns.delete = {
|
||||
},
|
||||
delete: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_, blueprint: any) =>
|
||||
@ -161,10 +151,8 @@ class HaBlueprintOverview extends LitElement {
|
||||
@click=${(ev) => this._delete(ev)}
|
||||
><ha-svg-icon .path=${mdiDelete}></ha-svg-icon
|
||||
></mwc-icon-button>`,
|
||||
};
|
||||
|
||||
return columns;
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
protected render(): TemplateResult {
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
internalProperty,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
query,
|
||||
} from "lit-element";
|
||||
import "../../../components/ha-date-input";
|
||||
import type { HaDateInput } from "../../../components/ha-date-input";
|
||||
@ -25,6 +26,10 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
|
||||
|
||||
@internalProperty() private _config?: EntityConfig;
|
||||
|
||||
@query("paper-time-input") private _timeInputEl?: PaperTimeInput;
|
||||
|
||||
@query("ha-date-input") private _dateInputEl?: HaDateInput;
|
||||
|
||||
public setConfig(config: EntityConfig): void {
|
||||
if (!config) {
|
||||
throw new Error("Invalid configuration");
|
||||
@ -74,11 +79,10 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
|
||||
.min=${stateObj.state === UNKNOWN
|
||||
? ""
|
||||
: ("0" + stateObj.attributes.minute).slice(-2)}
|
||||
.amPm=${false}
|
||||
@change=${this._selectedValueChanged}
|
||||
@click=${this._stopEventPropagation}
|
||||
hide-label
|
||||
format="24"
|
||||
.format=${24}
|
||||
></paper-time-input>
|
||||
`
|
||||
: ``}
|
||||
@ -90,24 +94,14 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
private get _timeInputEl(): PaperTimeInput {
|
||||
return this.shadowRoot!.querySelector("paper-time-input")!;
|
||||
}
|
||||
|
||||
private get _dateInputEl(): HaDateInput {
|
||||
return this.shadowRoot!.querySelector("ha-date-input")!;
|
||||
}
|
||||
|
||||
private _selectedValueChanged(ev): void {
|
||||
const stateObj = this.hass!.states[this._config!.entity];
|
||||
|
||||
const time =
|
||||
this._timeInputEl !== null
|
||||
? this._timeInputEl.value.trim() + ":00"
|
||||
const time = this._timeInputEl
|
||||
? this._timeInputEl.value?.trim()
|
||||
: undefined;
|
||||
|
||||
const date =
|
||||
this._dateInputEl !== null ? this._dateInputEl.value : undefined;
|
||||
const date = this._dateInputEl ? this._dateInputEl.value : undefined;
|
||||
|
||||
if (time !== stateObj.state) {
|
||||
setInputDateTimeValue(this.hass!, stateObj.entity_id, time, date);
|
||||
|
@ -1453,7 +1453,7 @@
|
||||
},
|
||||
"confirm_delete_header": "Delete this blueprint?",
|
||||
"confirm_delete_text": "Are you sure you want to delete this blueprint?",
|
||||
"add_blueprint": "Add blueprint",
|
||||
"add_blueprint": "Import blueprint",
|
||||
"use_blueprint": "Create automation",
|
||||
"delete_blueprint": "Delete blueprint"
|
||||
},
|
||||
@ -1462,6 +1462,7 @@
|
||||
"import_header": "Import \"{name}\" (type: {domain})",
|
||||
"import_introduction": "You can import blueprints of other users from Github and the community forums. Enter the URL of the blueprint below.",
|
||||
"url": "URL of the blueprint",
|
||||
"raw_blueprint": "Blueprint content",
|
||||
"importing": "Importing blueprint...",
|
||||
"import_btn": "Import blueprint",
|
||||
"saving": "Saving blueprint...",
|
||||
|
Loading…
x
Reference in New Issue
Block a user