mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-25 22:07:20 +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 {
|
.summary {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0px 16px;
|
padding: var(--expansion-panel-summary-padding, 0px 16px);
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
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}
|
.value=${this.value}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
.deviceFilter=${(device) => this._filterDevices(device)}
|
.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
|
allow-custom-entity
|
||||||
></ha-device-picker>`;
|
></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-entity";
|
||||||
import "./ha-selector-device";
|
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";
|
import { Selector } from "../../data/selector";
|
||||||
|
|
||||||
@customElement("ha-selector")
|
@customElement("ha-selector")
|
||||||
|
@ -97,6 +97,7 @@ export class PaperTimeInput extends PolymerElement {
|
|||||||
.time-input-wrap {
|
.time-input-wrap {
|
||||||
@apply --layout-horizontal;
|
@apply --layout-horizontal;
|
||||||
@apply --layout-no-wrap;
|
@apply --layout-no-wrap;
|
||||||
|
justify-content: var(--paper-time-input-justify-content, normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
[hidden] {
|
[hidden] {
|
||||||
|
@ -11,18 +11,19 @@ export interface Blueprint {
|
|||||||
export interface BlueprintMetaData {
|
export interface BlueprintMetaData {
|
||||||
domain: string;
|
domain: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
input?: Record<string, BlueprintInput | null>;
|
||||||
description?: string;
|
description?: string;
|
||||||
input: Record<string, BlueprintInput | null>;
|
source_url?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BlueprintInput {
|
export interface BlueprintInput {
|
||||||
name?: string;
|
name?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
selector?: Selector;
|
selector?: Selector;
|
||||||
|
default?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BlueprintImportResult {
|
export interface BlueprintImportResult {
|
||||||
url: string;
|
|
||||||
suggested_filename: string;
|
suggested_filename: string;
|
||||||
raw_data: string;
|
raw_data: string;
|
||||||
blueprint: Blueprint;
|
blueprint: Blueprint;
|
||||||
|
@ -5,10 +5,10 @@ export interface InputNumber {
|
|||||||
name: string;
|
name: string;
|
||||||
min: number;
|
min: number;
|
||||||
max: number;
|
max: number;
|
||||||
|
step: number;
|
||||||
|
mode: "box" | "slider";
|
||||||
icon?: string;
|
icon?: string;
|
||||||
initial?: number;
|
initial?: number;
|
||||||
step?: number;
|
|
||||||
mode?: "box" | "slider";
|
|
||||||
unit_of_measurement?: string;
|
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 {
|
export interface EntitySelector {
|
||||||
entity: {
|
entity: {
|
||||||
@ -13,5 +19,31 @@ export interface DeviceSelector {
|
|||||||
integration?: string;
|
integration?: string;
|
||||||
manufacturer?: string;
|
manufacturer?: string;
|
||||||
model?: 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-blueprint-picker";
|
||||||
import "../../../components/ha-circular-progress";
|
import "../../../components/ha-circular-progress";
|
||||||
import "../../../components/ha-selector/ha-selector";
|
import "../../../components/ha-selector/ha-selector";
|
||||||
|
import "../../../components/ha-settings-row";
|
||||||
|
|
||||||
@customElement("blueprint-automation-editor")
|
@customElement("blueprint-automation-editor")
|
||||||
export class HaBlueprintAutomationEditor extends LitElement {
|
export class HaBlueprintAutomationEditor extends LitElement {
|
||||||
@ -40,7 +41,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
|
|
||||||
@property() public isWide!: boolean;
|
@property() public isWide!: boolean;
|
||||||
|
|
||||||
@property() public narrow!: boolean;
|
@property({ reflect: true, type: Boolean }) public narrow!: boolean;
|
||||||
|
|
||||||
@property() public config!: BlueprintAutomationConfig;
|
@property() public config!: BlueprintAutomationConfig;
|
||||||
|
|
||||||
@ -125,7 +126,6 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
)}</span
|
)}</span
|
||||||
>
|
>
|
||||||
<ha-card>
|
<ha-card>
|
||||||
<div class="card-content">
|
|
||||||
<div class="blueprint-picker-container">
|
<div class="blueprint-picker-container">
|
||||||
${this._blueprints
|
${this._blueprints
|
||||||
? Object.keys(this._blueprints).length
|
? Object.keys(this._blueprints).length
|
||||||
@ -153,7 +153,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
|
|
||||||
${this.config.use_blueprint.path
|
${this.config.use_blueprint.path
|
||||||
? blueprint && "error" in blueprint
|
? blueprint && "error" in blueprint
|
||||||
? html`<p class="warning">
|
? html`<p class="warning padding">
|
||||||
There is an error in this Blueprint: ${blueprint.error}
|
There is an error in this Blueprint: ${blueprint.error}
|
||||||
</p>`
|
</p>`
|
||||||
: html`${blueprint?.metadata.description
|
: html`${blueprint?.metadata.description
|
||||||
@ -168,32 +168,36 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
</h3>
|
</h3>
|
||||||
${Object.entries(blueprint.metadata.input).map(
|
${Object.entries(blueprint.metadata.input).map(
|
||||||
([key, value]) =>
|
([key, value]) =>
|
||||||
html`<div>
|
html`<ha-settings-row .narrow=${this.narrow}>
|
||||||
${value?.description}
|
<span slot="heading">${value?.name || key}</span>
|
||||||
|
<span slot="description"
|
||||||
|
>${value?.description}</span
|
||||||
|
>
|
||||||
${value?.selector
|
${value?.selector
|
||||||
? html`<ha-selector
|
? html`<ha-selector
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.selector=${value.selector}
|
.selector=${value.selector}
|
||||||
.key=${key}
|
.key=${key}
|
||||||
.label=${value?.name || key}
|
.value=${(this.config.use_blueprint.input &&
|
||||||
.value=${this.config.use_blueprint.input &&
|
this.config.use_blueprint.input[key]) ||
|
||||||
this.config.use_blueprint.input[key]}
|
value?.default}
|
||||||
@value-changed=${this._inputChanged}
|
@value-changed=${this._inputChanged}
|
||||||
></ha-selector>`
|
></ha-selector>`
|
||||||
: html`<paper-input
|
: html`<paper-input
|
||||||
.key=${key}
|
.key=${key}
|
||||||
.label=${value?.name || key}
|
|
||||||
.value=${this.config.use_blueprint.input &&
|
.value=${this.config.use_blueprint.input &&
|
||||||
this.config.use_blueprint.input[key]}
|
this.config.use_blueprint.input[key]}
|
||||||
@value-changed=${this._inputChanged}
|
@value-changed=${this._inputChanged}
|
||||||
|
no-label-float
|
||||||
></paper-input>`}
|
></paper-input>`}
|
||||||
</div>`
|
</ha-settings-row>`
|
||||||
)}`
|
)}`
|
||||||
: this.hass.localize(
|
: html`<p class="padding">
|
||||||
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.blueprint.no_inputs"
|
"ui.panel.config.automation.editor.blueprint.no_inputs"
|
||||||
)}`
|
)}
|
||||||
|
</p>`}`
|
||||||
: ""}
|
: ""}
|
||||||
</div>
|
|
||||||
</ha-card>
|
</ha-card>
|
||||||
</ha-config-section>`;
|
</ha-config-section>`;
|
||||||
}
|
}
|
||||||
@ -279,16 +283,20 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
|
.padding {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
.content {
|
.content {
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
.blueprint-picker-container {
|
.blueprint-picker-container {
|
||||||
|
padding: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
margin-top: 16px;
|
margin: 16px;
|
||||||
}
|
}
|
||||||
span[slot="introduction"] a {
|
span[slot="introduction"] a {
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
@ -299,6 +307,16 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
ha-entity-toggle {
|
ha-entity-toggle {
|
||||||
margin-right: 8px;
|
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 {
|
mwc-fab {
|
||||||
position: relative;
|
position: relative;
|
||||||
bottom: calc(-80px - env(safe-area-inset-bottom));
|
bottom: calc(-80px - env(safe-area-inset-bottom));
|
||||||
|
@ -205,12 +205,14 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
|||||||
${"use_blueprint" in this._config
|
${"use_blueprint" in this._config
|
||||||
? html`<blueprint-automation-editor
|
? html`<blueprint-automation-editor
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.stateObj=${stateObj}
|
.stateObj=${stateObj}
|
||||||
.config=${this._config}
|
.config=${this._config}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></blueprint-automation-editor>`
|
></blueprint-automation-editor>`
|
||||||
: html`<manual-automation-editor
|
: html`<manual-automation-editor
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.stateObj=${stateObj}
|
.stateObj=${stateObj}
|
||||||
.config=${this._config}
|
.config=${this._config}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
|
@ -23,6 +23,7 @@ import {
|
|||||||
importBlueprint,
|
importBlueprint,
|
||||||
saveBlueprint,
|
saveBlueprint,
|
||||||
} from "../../../data/blueprint";
|
} from "../../../data/blueprint";
|
||||||
|
import "../../../components/ha-expansion-panel";
|
||||||
|
|
||||||
@customElement("ha-dialog-import-blueprint")
|
@customElement("ha-dialog-import-blueprint")
|
||||||
class DialogImportBlueprint extends LitElement {
|
class DialogImportBlueprint extends LitElement {
|
||||||
@ -71,7 +72,9 @@ class DialogImportBlueprint extends LitElement {
|
|||||||
html`<b>${this._result.blueprint.metadata.name}</b>`,
|
html`<b>${this._result.blueprint.metadata.name}</b>`,
|
||||||
"domain",
|
"domain",
|
||||||
this._result.blueprint.metadata.domain
|
this._result.blueprint.metadata.domain
|
||||||
)} <br /><br />
|
)}
|
||||||
|
<br />
|
||||||
|
${this._result.blueprint.metadata.description}
|
||||||
${this._result.validation_errors
|
${this._result.validation_errors
|
||||||
? html`
|
? html`
|
||||||
<p class="error">
|
<p class="error">
|
||||||
@ -94,7 +97,14 @@ class DialogImportBlueprint extends LitElement {
|
|||||||
)}
|
)}
|
||||||
></paper-input>
|
></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(
|
: html`${this.hass.localize(
|
||||||
"ui.panel.config.blueprint.add.import_introduction"
|
"ui.panel.config.blueprint.add.import_introduction"
|
||||||
)}<paper-input
|
)}<paper-input
|
||||||
@ -180,7 +190,7 @@ class DialogImportBlueprint extends LitElement {
|
|||||||
this._result!.blueprint.metadata.domain,
|
this._result!.blueprint.metadata.domain,
|
||||||
filename,
|
filename,
|
||||||
this._result!.raw_data,
|
this._result!.raw_data,
|
||||||
this._result!.url
|
this._result!.blueprint.metadata.source_url
|
||||||
);
|
);
|
||||||
this._params.importedCallback();
|
this._params.importedCallback();
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
@ -192,7 +202,14 @@ class DialogImportBlueprint extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
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(
|
private _columns = memoizeOne(
|
||||||
(narrow, _language): DataTableColumnContainer => {
|
(narrow, _language): DataTableColumnContainer => ({
|
||||||
const columns: DataTableColumnContainer = {
|
|
||||||
name: {
|
name: {
|
||||||
title: this.hass.localize(
|
title: this.hass.localize(
|
||||||
"ui.panel.config.blueprint.overview.headers.name"
|
"ui.panel.config.blueprint.overview.headers.name"
|
||||||
@ -90,25 +89,35 @@ class HaBlueprintOverview extends LitElement {
|
|||||||
filterable: true,
|
filterable: true,
|
||||||
direction: "asc",
|
direction: "asc",
|
||||||
grows: true,
|
grows: true,
|
||||||
},
|
template: narrow
|
||||||
};
|
? (name, entity: any) =>
|
||||||
|
html`
|
||||||
if (narrow) {
|
|
||||||
columns.name.template = (name, entity: any) => {
|
|
||||||
return html`
|
|
||||||
${name}<br />
|
${name}<br />
|
||||||
<div class="secondary">
|
<div class="secondary">
|
||||||
${entity.path}
|
${entity.path}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`
|
||||||
};
|
: undefined,
|
||||||
columns.create = {
|
},
|
||||||
|
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: "",
|
title: "",
|
||||||
type: "icon-button",
|
type: narrow ? "icon-button" : undefined,
|
||||||
|
width: narrow ? undefined : "180px",
|
||||||
template: (_, blueprint: any) =>
|
template: (_, blueprint: any) =>
|
||||||
blueprint.error
|
blueprint.error
|
||||||
? ""
|
? ""
|
||||||
: html` <mwc-icon-button
|
: narrow
|
||||||
|
? html`<mwc-icon-button
|
||||||
.blueprint=${blueprint}
|
.blueprint=${blueprint}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.blueprint.overview.use_blueprint"
|
"ui.panel.config.blueprint.overview.use_blueprint"
|
||||||
@ -118,24 +127,7 @@ class HaBlueprintOverview extends LitElement {
|
|||||||
)}
|
)}
|
||||||
@click=${(ev) => this._createNew(ev)}
|
@click=${(ev) => this._createNew(ev)}
|
||||||
><ha-svg-icon .path=${mdiRobot}></ha-svg-icon
|
><ha-svg-icon .path=${mdiRobot}></ha-svg-icon
|
||||||
></mwc-icon-button>`,
|
></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
|
|
||||||
? ""
|
|
||||||
: html`<mwc-button
|
: html`<mwc-button
|
||||||
.blueprint=${blueprint}
|
.blueprint=${blueprint}
|
||||||
@click=${(ev) => this._createNew(ev)}
|
@click=${(ev) => this._createNew(ev)}
|
||||||
@ -144,10 +136,8 @@ class HaBlueprintOverview extends LitElement {
|
|||||||
"ui.panel.config.blueprint.overview.use_blueprint"
|
"ui.panel.config.blueprint.overview.use_blueprint"
|
||||||
)}
|
)}
|
||||||
</mwc-button>`,
|
</mwc-button>`,
|
||||||
};
|
},
|
||||||
}
|
delete: {
|
||||||
|
|
||||||
columns.delete = {
|
|
||||||
title: "",
|
title: "",
|
||||||
type: "icon-button",
|
type: "icon-button",
|
||||||
template: (_, blueprint: any) =>
|
template: (_, blueprint: any) =>
|
||||||
@ -161,10 +151,8 @@ class HaBlueprintOverview extends LitElement {
|
|||||||
@click=${(ev) => this._delete(ev)}
|
@click=${(ev) => this._delete(ev)}
|
||||||
><ha-svg-icon .path=${mdiDelete}></ha-svg-icon
|
><ha-svg-icon .path=${mdiDelete}></ha-svg-icon
|
||||||
></mwc-icon-button>`,
|
></mwc-icon-button>`,
|
||||||
};
|
},
|
||||||
|
})
|
||||||
return columns;
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
internalProperty,
|
internalProperty,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
query,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import "../../../components/ha-date-input";
|
import "../../../components/ha-date-input";
|
||||||
import type { HaDateInput } from "../../../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;
|
@internalProperty() private _config?: EntityConfig;
|
||||||
|
|
||||||
|
@query("paper-time-input") private _timeInputEl?: PaperTimeInput;
|
||||||
|
|
||||||
|
@query("ha-date-input") private _dateInputEl?: HaDateInput;
|
||||||
|
|
||||||
public setConfig(config: EntityConfig): void {
|
public setConfig(config: EntityConfig): void {
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new Error("Invalid configuration");
|
throw new Error("Invalid configuration");
|
||||||
@ -74,11 +79,10 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
|
|||||||
.min=${stateObj.state === UNKNOWN
|
.min=${stateObj.state === UNKNOWN
|
||||||
? ""
|
? ""
|
||||||
: ("0" + stateObj.attributes.minute).slice(-2)}
|
: ("0" + stateObj.attributes.minute).slice(-2)}
|
||||||
.amPm=${false}
|
|
||||||
@change=${this._selectedValueChanged}
|
@change=${this._selectedValueChanged}
|
||||||
@click=${this._stopEventPropagation}
|
@click=${this._stopEventPropagation}
|
||||||
hide-label
|
hide-label
|
||||||
format="24"
|
.format=${24}
|
||||||
></paper-time-input>
|
></paper-time-input>
|
||||||
`
|
`
|
||||||
: ``}
|
: ``}
|
||||||
@ -90,24 +94,14 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
|
|||||||
ev.stopPropagation();
|
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 {
|
private _selectedValueChanged(ev): void {
|
||||||
const stateObj = this.hass!.states[this._config!.entity];
|
const stateObj = this.hass!.states[this._config!.entity];
|
||||||
|
|
||||||
const time =
|
const time = this._timeInputEl
|
||||||
this._timeInputEl !== null
|
? this._timeInputEl.value?.trim()
|
||||||
? this._timeInputEl.value.trim() + ":00"
|
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const date =
|
const date = this._dateInputEl ? this._dateInputEl.value : undefined;
|
||||||
this._dateInputEl !== null ? this._dateInputEl.value : undefined;
|
|
||||||
|
|
||||||
if (time !== stateObj.state) {
|
if (time !== stateObj.state) {
|
||||||
setInputDateTimeValue(this.hass!, stateObj.entity_id, time, date);
|
setInputDateTimeValue(this.hass!, stateObj.entity_id, time, date);
|
||||||
|
@ -1453,7 +1453,7 @@
|
|||||||
},
|
},
|
||||||
"confirm_delete_header": "Delete this blueprint?",
|
"confirm_delete_header": "Delete this blueprint?",
|
||||||
"confirm_delete_text": "Are you sure you want to 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",
|
"use_blueprint": "Create automation",
|
||||||
"delete_blueprint": "Delete blueprint"
|
"delete_blueprint": "Delete blueprint"
|
||||||
},
|
},
|
||||||
@ -1462,6 +1462,7 @@
|
|||||||
"import_header": "Import \"{name}\" (type: {domain})",
|
"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.",
|
"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",
|
"url": "URL of the blueprint",
|
||||||
|
"raw_blueprint": "Blueprint content",
|
||||||
"importing": "Importing blueprint...",
|
"importing": "Importing blueprint...",
|
||||||
"import_btn": "Import blueprint",
|
"import_btn": "Import blueprint",
|
||||||
"saving": "Saving blueprint...",
|
"saving": "Saving blueprint...",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user