Compare commits

...

13 Commits

Author SHA1 Message Date
Thomas Lovén
9fbfdec546 Add some more card helpers. 2020-03-31 19:56:25 +02:00
Ian Richardson
6692fa439a hold/double actions for light-card (#5361)
* hold/double actions for light-card

* lint
2020-03-31 17:52:20 +02:00
imgbot[bot]
0535247bb3 [ImgBot] Optimize images (#5378)
*Total -- 1,745.75kb -> 1,539.81kb (11.8%)

/demo/public/assets/teachingbirds/meteogram.png -- 66.71kb -> 24.48kb (63.31%)
/demo/public/assets/teachingbirds/background_square.png -- 0.76kb -> 0.37kb (51.98%)
/demo/public/assets/arsaboo/icons/security_armed_red.png -- 6.38kb -> 3.67kb (42.5%)
/demo/public/assets/jimpower/background-15.jpg -- 231.78kb -> 159.68kb (31.11%)
/public/static/images/image-broken.svg -- 0.56kb -> 0.42kb (23.99%)
/demo/public/assets/arsaboo/icons/security_disarmed.png -- 4.21kb -> 3.25kb (22.7%)
/demo/public/assets/arsaboo/icons/automation_enabled.png -- 3.96kb -> 3.08kb (22.32%)
/demo/public/assets/jimpower/cardbackK.png -- 10.56kb -> 8.21kb (22.22%)
/demo/public/assets/arsaboo/icons/abode_enabled.png -- 3.98kb -> 3.16kb (20.62%)
/demo/public/assets/arsaboo/icons/ecobee_blank.png -- 2.18kb -> 1.78kb (18.22%)
/demo/public/assets/arsaboo/floorplans/ecobee_blank.png -- 2.17kb -> 1.78kb (17.87%)
/demo/public/assets/arsaboo/icons/automation_disabled.png -- 6.89kb -> 5.73kb (16.82%)
/demo/public/assets/jimpower/home/james_10.jpg -- 73.21kb -> 61.89kb (15.46%)
/demo/public/assets/arsaboo/icons/camera_patio_streaming.png -- 11.63kb -> 9.88kb (14.98%)
/demo/public/assets/arsaboo/icons/Harmony.png -- 3.83kb -> 3.25kb (14.95%)
/demo/public/assets/arsaboo/icons/light_off.png -- 9.53kb -> 8.51kb (10.77%)
/demo/public/assets/arsaboo/icons/tv_enabled.png -- 5.48kb -> 4.90kb (10.69%)
/demo/public/assets/jimpower/home/bus_10.jpg -- 36.36kb -> 32.58kb (10.4%)
/demo/public/assets/kernehed/bella.jpg -- 33.09kb -> 30.29kb (8.44%)
/demo/public/assets/arsaboo/images/camera.backyard.jpg -- 81.15kb -> 74.80kb (7.82%)
/demo/public/assets/kernehed/oscar.jpg -- 25.32kb -> 23.34kb (7.81%)
/demo/public/assets/arsaboo/images/camera.patio.jpg -- 63.13kb -> 58.52kb (7.29%)
/demo/public/assets/arsaboo/images/camera.porch.jpg -- 76.49kb -> 70.95kb (7.25%)
/demo/public/assets/arsaboo/icons/light_on.png -- 12.03kb -> 11.19kb (6.97%)
/demo/public/assets/jimpower/home/tina_4.jpg -- 59.69kb -> 55.92kb (6.31%)
/gallery/public/images/album_cover.jpg -- 26.11kb -> 24.46kb (6.31%)
/demo/public/assets/teachingbirds/clothes_drying_square.jpg -- 31.93kb -> 29.98kb (6.11%)
/demo/public/assets/arsaboo/images/camera.driveway.jpg -- 59.47kb -> 55.84kb (6.1%)
/demo/public/assets/teachingbirds/laundry_running_square.jpg -- 58.68kb -> 55.61kb (5.22%)
/demo/public/assets/kernehed/camera.entre.jpg -- 65.84kb -> 62.49kb (5.09%)
/demo/public/assets/teachingbirds/Stefan_square.jpg -- 11.25kb -> 10.68kb (5.06%)
/demo/public/assets/teachingbirds/isa_square.jpg -- 18.90kb -> 17.98kb (4.88%)
/demo/public/assets/jimpower/security/motion_3.jpg -- 87.09kb -> 82.99kb (4.71%)
/demo/public/assets/teachingbirds/roomba_square.jpg -- 32.23kb -> 30.82kb (4.39%)
/demo/public/assets/teachingbirds/laundry_clean_2_square.jpg -- 31.87kb -> 30.48kb (4.34%)
/demo/public/assets/teachingbirds/folded_clothes_square.jpg -- 28.60kb -> 27.41kb (4.16%)
/demo/public/assets/arsaboo/icons/abode_disabled.png -- 8.74kb -> 8.38kb (4.06%)
/gallery/public/images/netflix.jpg -- 20.19kb -> 19.39kb (4%)
/demo/public/assets/teachingbirds/roomba_bw_square.jpg -- 15.97kb -> 15.34kb (3.97%)
/demo/public/assets/teachingbirds/trash_square.jpg -- 29.50kb -> 28.39kb (3.76%)
/demo/public/assets/teachingbirds/cleaning_square.jpg -- 38.57kb -> 37.19kb (3.59%)
/demo/public/assets/teachingbirds/dryer_square.jpg -- 18.78kb -> 18.16kb (3.32%)
/gallery/public/images/album_cover_2.jpg -- 129.79kb -> 125.62kb (3.21%)
/demo/public/assets/teachingbirds/House_square.jpg -- 40.59kb -> 39.31kb (3.15%)
/demo/public/assets/arsaboo/icons/tv_disabled.png -- 10.24kb -> 9.93kb (3.08%)
/demo/public/assets/teachingbirds/washer_square.jpg -- 20.52kb -> 20.00kb (2.52%)
/demo/public/assets/teachingbirds/mailbox_square.jpg -- 42.97kb -> 41.98kb (2.3%)
/demo/public/assets/teachingbirds/trash_bear_bw_square.jpg -- 17.60kb -> 17.35kb (1.46%)
/demo/public/assets/teachingbirds/guests_square.jpg -- 49.05kb -> 48.38kb (1.38%)
/demo/public/assets/teachingbirds/mailbox_bw_square.jpg -- 19.44kb -> 19.25kb (0.98%)
/demo/public/assets/arsaboo/icons/tv_on2.png -- 0.79kb -> 0.78kb (0.25%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>

Co-authored-by: ImgBotApp <ImgBotHelp@gmail.com>
2020-03-31 16:50:20 +02:00
Thomas Lovén
a0a4fcaf5f Allow custom cards in card picker (#5122)
* Allow custom cards in card picker

* Lint. "Custom:" prefix to card names

* Address review comments

* Simplifications. Translation fixes.

* Less magic

* Move CUSTOM_TYPE_PREFIX

* Update hui-card-picker.ts

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
2020-03-31 16:20:09 +02:00
Zack Arnett
454d81facc View Editor: Badge Preview (#5335)
* Badge Preview

* Move Badge preview

* Clean

* Error card + clean

* remove try catch
2020-03-31 13:30:52 +02:00
Bram Kragten
0bfa8260fa Merge pull request #5372 from dmulcahey/dm/zha-tables-clear-selections
Clear selections in ZHA data tables
2020-03-31 13:25:50 +02:00
Bram Kragten
f2124f1c95 Merge pull request #5373 from zsarnett/entity-card-fix
Entity Card: Fix Value clipping in editor
2020-03-31 13:24:34 +02:00
HomeAssistant Azure
451bc2370a [ci skip] Translation update 2020-03-31 00:32:48 +00:00
Zack Arnett
0b17642c31 Fix editor value clipping 2020-03-30 20:19:18 -04:00
David Mulcahey
214dc25576 clear selections 2020-03-30 20:01:04 -04:00
Zack Arnett
158eddfd44 Entity Card: Card Addition (#4971)
* Review to changed Src translations

* Reviews

* side by side theme

* Allow user to specify unit

* Add unit back update for headerfooter and editor

* Clean

* Unavailable for attribute that doesn't exist

* fix merge

* Fix from rebasing

* reviews

* Localize State

* fix for localize

* css

* reviews

* Break the rules
2020-03-30 19:49:02 -04:00
Pascal Vizeli
5daa6dbd25 [skip ci] Simplify release pipeline 2020-03-30 22:52:27 +02:00
Pascal Vizeli
645ef3e61f [skip ci] Simplify release pipeline 2020-03-30 22:51:42 +02:00
73 changed files with 814 additions and 58 deletions

View File

@@ -50,15 +50,8 @@ stages:
- template: templates/azp-job-wheels.yaml@azure
parameters:
builderVersion: '$(versionWheels)'
builderApk: 'build-base'
wheelsLocal: true
wheelsRequirement: 'requirement.txt'
preBuild:
- task: NodeTool@0
displayName: "Use Node $(versionNode)"
inputs:
versionSpec: "$(versionNode)"
- script: |
set -e
yarn install
script/build_frontend
sleep 240
echo "home-assistant-frontend==$(Build.SourceBranchName)" > requirement.txt

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 805 B

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 781 B

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="36" height="36" viewBox="0 0 24 24"><path fill="#505050" d="M19,3A2,2 0 0,1 21,5V11H19V13H19L17,13V15H15V17H13V19H11V21H5C3.89,21 3,20.1 3,19V5A2,2 0 0,1 5,3H19M21,15V19A2,2 0 0,1 19,21H19L15,21V19H17V17H19V15H21M19,8.5A0.5,0.5 0 0,0 18.5,8H5.5A0.5,0.5 0 0,0 5,8.5V15.5A0.5,0.5 0 0,0 5.5,16H11V15H13V13H15V11H17V9H19V8.5Z" /></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="36" height="36" version="1.1" viewBox="0 0 24 24"><path fill="#505050" d="M19,3A2,2 0 0,1 21,5V11H19V13H19L17,13V15H15V17H13V19H11V21H5C3.89,21 3,20.1 3,19V5A2,2 0 0,1 5,3H19M21,15V19A2,2 0 0,1 19,21H19L15,21V19H17V17H19V15H21M19,8.5A0.5,0.5 0 0,0 18.5,8H5.5A0.5,0.5 0 0,0 5,8.5V15.5A0.5,0.5 0 0,0 5.5,16H11V15H13V13H15V11H17V9H19V8.5Z"/></svg>

Before

Width:  |  Height:  |  Size: 571 B

After

Width:  |  Height:  |  Size: 434 B

View File

@@ -0,0 +1,23 @@
export interface CustomCardEntry {
type: string;
name?: string;
description?: string;
preview?: boolean;
}
export interface CustomCardsWindow {
customCards?: CustomCardEntry[];
}
export const CUSTOM_TYPE_PREFIX = "custom:";
const customCardsWindow = window as CustomCardsWindow;
if (!("customCards" in customCardsWindow)) {
customCardsWindow.customCards = [];
}
export const customCards = customCardsWindow.customCards!;
export const getCustomCardEntry = (type: string) =>
customCards.find((card) => card.type === type);

View File

@@ -6,6 +6,7 @@ import {
css,
CSSResult,
PropertyValues,
query,
} from "lit-element";
import "../../../layouts/hass-subpage";
@@ -18,7 +19,7 @@ import {
addGroup,
ZHAGroup,
} from "../../../data/zha";
import "./zha-devices-data-table";
import { ZHADevicesDataTable } from "./zha-devices-data-table";
import { SelectionChangedEvent } from "../../../components/data-table/ha-data-table";
import { navigate } from "../../../common/navigate";
import { PolymerChangedEvent } from "../../../polymer-types";
@@ -34,6 +35,8 @@ export class ZHAAddGroupPage extends LitElement {
@property() public devices: ZHADevice[] = [];
@property() private _processingAdd: boolean = false;
@property() private _groupName: string = "";
@query("zha-devices-data-table")
private _zhaDevicesDataTable!: ZHADevicesDataTable;
private _firstUpdatedCalled: boolean = false;
private _selectedDevicesToAdd: string[] = [];
@@ -130,6 +133,7 @@ export class ZHAAddGroupPage extends LitElement {
this._selectedDevicesToAdd = [];
this._processingAdd = false;
this._groupName = "";
this._zhaDevicesDataTable.clearSelection();
navigate(this, `/config/zha/group/${group.group_id}`, true);
}

View File

@@ -9,10 +9,14 @@ import {
TemplateResult,
property,
customElement,
query,
} from "lit-element";
import { HomeAssistant } from "../../../types";
// tslint:disable-next-line
import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table";
import {
DataTableColumnContainer,
HaDataTable,
} from "../../../components/data-table/ha-data-table";
// tslint:disable-next-line
import { Cluster } from "../../../data/zha";
import { formatAsPaddedHex } from "./functions";
@@ -27,6 +31,7 @@ export class ZHAClustersDataTable extends LitElement {
@property() public hass!: HomeAssistant;
@property() public narrow = false;
@property() public clusters: Cluster[] = [];
@query("ha-data-table") private _dataTable!: HaDataTable;
private _clusters = memoizeOne((clusters: Cluster[]) => {
let outputClusters: ClusterRowData[] = clusters;
@@ -77,6 +82,10 @@ export class ZHAClustersDataTable extends LitElement {
}
);
public clearSelection() {
this._dataTable.clearSelection();
}
protected render(): TemplateResult {
return html`
<ha-data-table

View File

@@ -9,10 +9,14 @@ import {
TemplateResult,
property,
customElement,
query,
} from "lit-element";
import { HomeAssistant } from "../../../types";
// tslint:disable-next-line
import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table";
import {
DataTableColumnContainer,
HaDataTable,
} from "../../../components/data-table/ha-data-table";
// tslint:disable-next-line
import { ZHADevice } from "../../../data/zha";
import { showZHADeviceInfoDialog } from "../../../dialogs/zha-device-info-dialog/show-dialog-zha-device-info";
@@ -27,6 +31,7 @@ export class ZHADevicesDataTable extends LitElement {
@property() public narrow = false;
@property({ type: Boolean }) public selectable = false;
@property() public devices: ZHADevice[] = [];
@query("ha-data-table") private _dataTable!: HaDataTable;
private _devices = memoizeOne((devices: ZHADevice[]) => {
let outputDevices: DeviceRowData[] = devices;
@@ -89,6 +94,10 @@ export class ZHADevicesDataTable extends LitElement {
}
);
public clearSelection() {
this._dataTable.clearSelection();
}
protected render(): TemplateResult {
return html`
<ha-data-table

View File

@@ -16,6 +16,7 @@ import {
property,
PropertyValues,
TemplateResult,
query,
} from "lit-element";
import {
@@ -26,7 +27,7 @@ import {
Cluster,
fetchClustersForZhaNode,
} from "../../../data/zha";
import "./zha-clusters-data-table";
import { ZHAClustersDataTable } from "./zha-clusters-data-table";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types";
import { ItemSelectedEvent } from "./types";
@@ -47,6 +48,8 @@ export class ZHAGroupBindingControl extends LitElement {
@property() private _clusters: Cluster[] = [];
private _groupToBind?: ZHAGroup;
private _clustersToBind?: Cluster[];
@query("zha-devices-data-table")
private _zhaClustersDataTable!: ZHAClustersDataTable;
protected updated(changedProperties: PropertyValues): void {
if (changedProperties.has("selectedDevice")) {
@@ -187,6 +190,7 @@ export class ZHAGroupBindingControl extends LitElement {
this._groupToBind!.group_id,
this._clustersToBind!
);
this._zhaClustersDataTable.clearSelection();
}
}
@@ -198,6 +202,7 @@ export class ZHAGroupBindingControl extends LitElement {
this._groupToBind!.group_id,
this._clustersToBind!
);
this._zhaClustersDataTable.clearSelection();
}
}

View File

@@ -9,10 +9,14 @@ import {
TemplateResult,
property,
customElement,
query,
} from "lit-element";
import { HomeAssistant } from "../../../types";
// tslint:disable-next-line
import { DataTableColumnContainer } from "../../../components/data-table/ha-data-table";
import {
DataTableColumnContainer,
HaDataTable,
} from "../../../components/data-table/ha-data-table";
// tslint:disable-next-line
import { ZHAGroup, ZHADevice } from "../../../data/zha";
import { formatAsPaddedHex } from "./functions";
@@ -29,6 +33,7 @@ export class ZHAGroupsDataTable extends LitElement {
@property() public narrow = false;
@property() public groups: ZHAGroup[] = [];
@property() public selectable = false;
@query("ha-data-table") private _dataTable!: HaDataTable;
private _groups = memoizeOne((groups: ZHAGroup[]) => {
let outputGroups: GroupRowData[] = groups;
@@ -98,6 +103,10 @@ export class ZHAGroupsDataTable extends LitElement {
}
);
public clearSelection() {
this._dataTable.clearSelection();
}
protected render(): TemplateResult {
return html`
<ha-data-table

View File

@@ -0,0 +1,243 @@
import {
html,
LitElement,
PropertyValues,
TemplateResult,
customElement,
property,
css,
CSSResult,
} from "lit-element";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { stateIcon } from "../../../common/entity/state_icon";
import "../../../components/ha-card";
import "../../../components/ha-icon";
import "../components/hui-warning";
import {
LovelaceCard,
LovelaceCardEditor,
LovelaceHeaderFooter,
} from "../types";
import { HomeAssistant } from "../../../types";
import { fireEvent } from "../../../common/dom/fire_event";
import { EntityCardConfig } from "./types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { actionHandler } from "../common/directives/action-handler-directive";
import { isValidEntityId } from "../../../common/entity/valid_entity_id";
import { findEntities } from "../common/find-entites";
import { createHeaderFooterElement } from "../create-element/create-header-footer-element";
import { UNKNOWN, UNAVAILABLE } from "../../../data/entity";
import { HuiErrorCard } from "./hui-error-card";
@customElement("hui-entity-card")
class HuiEntityCard extends LitElement implements LovelaceCard {
public static async getConfigElement(): Promise<LovelaceCardEditor> {
await import(
/* webpackChunkName: "hui-entity-card-editor" */ "../editor/config-elements/hui-entity-card-editor"
);
return document.createElement("hui-entity-card-editor");
}
public static getStubConfig(
hass: HomeAssistant,
entities: string[],
entitiesFill: string[]
) {
const includeDomains = ["sensor", "light", "switch"];
const maxEntities = 1;
const foundEntities = findEntities(
hass,
maxEntities,
entities,
entitiesFill,
includeDomains
);
return {
entity: foundEntities[0] || "",
};
}
@property() public hass?: HomeAssistant;
@property() private _config?: EntityCardConfig;
private _footerElement?: HuiErrorCard | LovelaceHeaderFooter;
public setConfig(config: EntityCardConfig): void {
if (config.entity && !isValidEntityId(config.entity)) {
throw new Error("Invalid Entity");
}
this._config = config;
if (this._config.footer) {
this._footerElement = createHeaderFooterElement(this._config.footer);
} else if (this._footerElement) {
this._footerElement = undefined;
}
}
public getCardSize(): number {
return 1 + (this._config?.footer ? 1 : 0);
}
protected render(): TemplateResult {
if (!this._config || !this.hass) {
return html``;
}
const stateObj = this.hass.states[this._config.entity];
if (!stateObj) {
return html`
<hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`;
}
const showUnit = this._config.attribute
? this._config.attribute in stateObj.attributes
: stateObj.state !== UNKNOWN && stateObj.state !== UNAVAILABLE;
return html`
<ha-card>
<div
@action=${this._handleClick}
.actionHandler=${actionHandler()}
tabindex="0"
>
<div class="header">
<div class="name">
${this._config.name || computeStateName(stateObj)}
</div>
<div class="icon">
<ha-icon
.icon=${this._config.icon || stateIcon(stateObj)}
></ha-icon>
</div>
</div>
<div class="info">
<span class="value"
>${"attribute" in this._config
? stateObj.attributes[this._config.attribute!] ||
this.hass.localize("state.default.unknown")
: this.hass.localize(`state.default.${stateObj.state}`) ||
this.hass.localize(
`state.${this._config.entity.split(".")[0]}.${
stateObj.state
}`
) ||
stateObj.state}</span
>${showUnit
? html`
<span class="measurement"
>${this._config.unit ||
(this._config.attribute
? ""
: stateObj.attributes.unit_of_measurement)}</span
>
`
: ""}
</div>
</div>
${this._footerElement}
</ha-card>
`;
}
protected shouldUpdate(changedProps: PropertyValues): boolean {
// Side Effect used to update footer hass while keeping optimizations
if (this._footerElement) {
this._footerElement.hass = this.hass;
}
return hasConfigOrEntityChanged(this, changedProps);
}
protected updated(changedProps: PropertyValues) {
super.updated(changedProps);
if (!this._config || !this.hass) {
return;
}
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
const oldConfig = changedProps.get("_config") as
| EntityCardConfig
| undefined;
if (
!oldHass ||
!oldConfig ||
oldHass.themes !== this.hass.themes ||
oldConfig.theme !== this._config.theme
) {
applyThemesOnElement(this, this.hass.themes, this._config!.theme);
}
}
private _handleClick(): void {
fireEvent(this, "hass-more-info", { entityId: this._config!.entity });
}
static get styles(): CSSResult {
return css`
ha-card > div {
cursor: pointer;
}
.header {
display: flex;
padding: 8px 16px 0;
justify-content: space-between;
}
.name {
color: var(--secondary-text-color);
line-height: 40px;
font-weight: 500;
font-size: 16px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.icon {
color: var(--state-icon-color, #44739e);
line-height: 40px;
}
.info {
padding: 0px 16px 16px;
margin-top: -4px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
line-height: 28px;
}
.value {
font-size: 28px;
margin-right: 4px;
}
.measurement {
font-size: 18px;
color: var(--secondary-text-color);
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-entity-card": HuiEntityCard;
}
}

View File

@@ -25,12 +25,15 @@ import { fireEvent } from "../../../common/dom/fire_event";
import { HomeAssistant, LightEntity } from "../../../types";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { toggleEntity } from "../common/entity/toggle-entity";
import { LightCardConfig } from "./types";
import { supportsFeature } from "../../../common/entity/supports-feature";
import { SUPPORT_BRIGHTNESS } from "../../../data/light";
import { findEntities } from "../common/find-entites";
import { UNAVAILABLE } from "../../../data/entity";
import { actionHandler } from "../common/directives/action-handler-directive";
import { hasAction } from "../common/has-action";
import { ActionHandlerEvent } from "../../../data/lovelace";
import { handleAction } from "../common/handle-action";
@customElement("hui-light-card")
export class HuiLightCard extends LitElement implements LovelaceCard {
@@ -74,7 +77,11 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
throw new Error("Specify an entity from within the light domain.");
}
this._config = { theme: "default", ...config };
this._config = {
theme: "default",
...config,
tap_action: { action: "toggle" },
};
}
protected render(): TemplateResult {
@@ -143,7 +150,11 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
filter: this._computeBrightness(stateObj),
color: this._computeColor(stateObj),
})}
@click=${this._handleClick}
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config!.hold_action),
hasDoubleClick: hasAction(this._config!.double_tap_action),
})}
tabindex="0"
></paper-icon-button>
</div>
@@ -240,8 +251,8 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
return `hsl(${hue}, 100%, ${100 - sat / 2}%)`;
}
private _handleClick() {
toggleEntity(this.hass!, this._config!.entity!);
private _handleAction(ev: ActionHandlerEvent) {
handleAction(this, this.hass!, this._config!, ev.detail.action!);
}
private _handleMoreInfo() {

View File

@@ -22,6 +22,11 @@ export interface EmptyStateCardConfig extends LovelaceCardConfig {
title?: string;
}
export interface EntityCardConfig extends LovelaceCardConfig {
attribute?: string;
unit?: string;
}
export interface EntitiesCardEntityConfig extends EntityConfig {
type?: string;
secondary_info?: "entity-id" | "last-changed";
@@ -133,6 +138,9 @@ export interface LightCardConfig extends LovelaceCardConfig {
name?: string;
theme?: string;
icon?: string;
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
}
export interface MapCardConfig extends LovelaceCardConfig {

View File

@@ -1,4 +1,5 @@
import "../cards/hui-entities-card";
import "../cards/hui-entity-card";
import "../cards/hui-button-card";
import "../cards/hui-entity-button-card";
import "../cards/hui-glance-card";
@@ -16,6 +17,7 @@ import {
} from "./create-element-base";
const ALWAYS_LOADED_TYPES = new Set([
"entity",
"entities",
"button",
"entity-button",

View File

@@ -17,8 +17,8 @@ import { fireEvent } from "../../../common/dom/fire_event";
import { LovelaceElementConfig, LovelaceElement } from "../elements/types";
import { LovelaceRow, LovelaceRowConfig } from "../entity-rows/types";
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
import { CUSTOM_TYPE_PREFIX } from "../../../data/lovelace_custom_cards";
const CUSTOM_TYPE_PREFIX = "custom:";
const TIMEOUT = 2000;
interface CreateElementConfigTypes {

View File

@@ -3,3 +3,9 @@ export { createCardElement } from "./create-element/create-card-element";
export { createBadgeElement } from "./create-element/create-badge-element";
export { createHeaderFooterElement } from "./create-element/create-header-footer-element";
export { createHuiElement } from "./create-element/create-hui-element";
export { actionHandlerBind } from "./common/directives/action-handler-directive";
export { handleAction } from "./common/handle-action";
export const loadElements = {
entityEditor: () => import("./components/hui-entity-editor"),
};

View File

@@ -23,11 +23,17 @@ import {
calcUnusedEntities,
} from "../../common/compute-unused-entities";
import { UNKNOWN, UNAVAILABLE } from "../../../../data/entity";
import {
customCards,
getCustomCardEntry,
CUSTOM_TYPE_PREFIX,
} from "../../../../data/lovelace_custom_cards";
const previewCards: string[] = [
"alarm-panel",
"button",
"entities",
"entity",
"gauge",
"glance",
"history-graph",
@@ -99,6 +105,24 @@ export class HuiCardPicker extends LitElement {
`;
})}
</div>
${customCards.length
? html`
<div class="cards-container">
${customCards.map((card) => {
return html`
${until(
this._renderCardElement(card.type, true, true),
html`
<div class="card spinner">
<paper-spinner active alt="Loading"></paper-spinner>
</div>
`
)}
`;
})}
</div>
`
: ""}
<div class="cards-container">
<div
class="card"
@@ -248,8 +272,14 @@ export class HuiCardPicker extends LitElement {
private async _renderCardElement(
type: string,
noElement: boolean = false
noElement: boolean = false,
isCustom: boolean = false
): Promise<TemplateResult> {
const customCard = isCustom ? getCustomCardEntry(type) : undefined;
if (isCustom) {
type = `${CUSTOM_TYPE_PREFIX}${type}`;
}
let element: LovelaceCard | undefined;
let cardConfig: LovelaceCardConfig = { type };
@@ -261,7 +291,7 @@ export class HuiCardPicker extends LitElement {
this._usedEntities!
);
if (!noElement) {
if (!noElement || customCard?.preview) {
element = this._createCardElement(cardConfig);
}
}
@@ -273,20 +303,25 @@ export class HuiCardPicker extends LitElement {
description: !element || element.tagName === "HUI-ERROR-CARD",
})}"
>
${!element || element.tagName === "HUI-ERROR-CARD"
? html`
${this.hass!.localize(
`ui.panel.lovelace.editor.card.${cardConfig.type}.description`
)}
`
: html`
${element}
`}
${element && element.tagName !== "HUI-ERROR-CARD"
? element
: customCard
? customCard.description ||
this.hass!.localize(
`ui.panel.lovelace.editor.cardpicker.no_description`
)
: this.hass!.localize(
`ui.panel.lovelace.editor.card.${cardConfig.type}.description`
)}
</div>
<div class="card-header">
${this.hass!.localize(
`ui.panel.lovelace.editor.card.${cardConfig.type}.name`
)}
${customCard
? `${this.hass!.localize(
"ui.panel.lovelace.editor.cardpicker.custom_card"
)}: ${customCard.name || customCard.type}`
: this.hass!.localize(
`ui.panel.lovelace.editor.card.${cardConfig.type}.name`
)}
</div>
</div>
`;

View File

@@ -0,0 +1,189 @@
import {
html,
LitElement,
TemplateResult,
customElement,
property,
} from "lit-element";
import "@polymer/paper-input/paper-input";
import "../../components/hui-action-editor";
import "../../components/hui-theme-select-editor";
import "../../components/hui-entity-editor";
import { struct } from "../../common/structs/struct";
import { EntitiesEditorEvent, EditorTarget } from "../types";
import { HomeAssistant } from "../../../../types";
import { LovelaceCardEditor } from "../../types";
import { fireEvent } from "../../../../common/dom/fire_event";
import { configElementStyle } from "./config-elements-style";
import { EntityCardConfig } from "../../cards/types";
import { headerFooterConfigStructs } from "../../header-footer/types";
const cardConfigStruct = struct({
type: "string",
entity: "string?",
name: "string?",
icon: "string?",
attribute: "string?",
unit: "string?",
theme: "string?",
header: struct.optional(headerFooterConfigStructs),
footer: struct.optional(headerFooterConfigStructs),
});
@customElement("hui-entity-card-editor")
export class HuiEntityCardEditor extends LitElement
implements LovelaceCardEditor {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityCardConfig;
public setConfig(config: EntityCardConfig): void {
config = cardConfigStruct(config);
this._config = config;
}
get _entity(): string {
return this._config!.entity || "";
}
get _name(): string {
return this._config!.name || "";
}
get _icon(): string {
return this._config!.icon || "";
}
get _attribute(): string {
return this._config!.attribute || "";
}
get _unit(): string {
return this._config!.unit || "";
}
get _theme(): string {
return this._config!.theme || "default";
}
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
return html`
${configElementStyle}
<div class="card-config">
<ha-entity-picker
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.entity"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.hass=${this.hass}
.value=${this._entity}
.configValue=${"entity"}
@change=${this._valueChanged}
allow-custom-entity
></ha-entity-picker>
<div class="side-by-side">
<paper-input
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.name"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._name}
.configValue=${"name"}
@value-changed=${this._valueChanged}
></paper-input>
<paper-input
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.icon"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._icon}
.configValue=${"icon"}
@value-changed=${this._valueChanged}
></paper-input>
</div>
<div class="side-by-side">
<paper-input
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.attribute"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._attribute}
.configValue=${"attribute"}
@value-changed=${this._valueChanged}
></paper-input>
<paper-input
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.unit"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._unit}
.configValue=${"unit"}
@value-changed=${this._valueChanged}
></paper-input>
</div>
<hui-theme-select-editor
.hass=${this.hass}
.value=${this._theme}
.configValue=${"theme"}
@theme-changed=${this._valueChanged}
></hui-theme-select-editor>
</div>
`;
}
private _valueChanged(ev: EntitiesEditorEvent): void {
if (!this._config || !this.hass) {
return;
}
const target = ev.target! as EditorTarget;
if (
this[`_${target.configValue}`] === target.value ||
this[`_${target.configValue}`] === target.config
) {
return;
}
if (target.configValue) {
if (target.value === "") {
delete this._config[target.configValue!];
} else {
let newValue: string | undefined;
if (
target.configValue === "icon_height" &&
!isNaN(Number(target.value))
) {
newValue = `${String(target.value)}px`;
}
this._config = {
...this._config,
[target.configValue!]:
target.checked !== undefined
? target.checked
: newValue !== undefined
? newValue
: target.value
? target.value
: target.config,
};
}
}
fireEvent(this, "config-changed", { config: this._config });
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-entity-card-editor": HuiEntityCardEditor;
}
}

View File

@@ -8,18 +8,23 @@ import {
import "@polymer/paper-input/paper-input";
import "../../components/hui-theme-select-editor";
import "../../components/hui-action-editor";
import "../../../../components/ha-icon-input";
import "../../components/hui-entity-editor";
import { struct } from "../../common/structs/struct";
import { EntitiesEditorEvent, EditorTarget } from "../types";
import {
EntitiesEditorEvent,
EditorTarget,
actionConfigStruct,
} from "../types";
import { HomeAssistant } from "../../../../types";
import { LovelaceCardEditor } from "../../types";
import { fireEvent } from "../../../../common/dom/fire_event";
import { configElementStyle } from "./config-elements-style";
import { LightCardConfig } from "../../cards/types";
import { stateIcon } from "../../../../common/entity/state_icon";
import { ActionConfig } from "../../../../data/lovelace";
const cardConfigStruct = struct({
type: "string",
@@ -27,6 +32,8 @@ const cardConfigStruct = struct({
entity: "string?",
theme: "string?",
icon: "string?",
hold_action: struct.optional(actionConfigStruct),
double_tap_action: struct.optional(actionConfigStruct),
});
@customElement("hui-light-card-editor")
@@ -56,11 +63,28 @@ export class HuiLightCardEditor extends LitElement
return this._config!.icon || "";
}
get _hold_action(): ActionConfig {
return this._config!.hold_action || { action: "none" };
}
get _double_tap_action(): ActionConfig {
return this._config!.double_tap_action || { action: "none" };
}
protected render(): TemplateResult {
if (!this.hass) {
return html``;
}
const actions = [
"more-info",
"toggle",
"navigate",
"url",
"call-service",
"none",
];
return html`
${configElementStyle}
<div class="card-config">
@@ -71,10 +95,10 @@ export class HuiLightCardEditor extends LitElement
"ui.panel.lovelace.editor.card.config.required"
)})"
.hass=${this.hass}
.value="${this._entity}"
.value=${this._entity}
.configValue=${"entity"}
include-domains='["light"]'
@change="${this._valueChanged}"
@change=${this._valueChanged}
allow-custom-entity
></ha-entity-picker>
<div class="side-by-side">
@@ -84,9 +108,9 @@ export class HuiLightCardEditor extends LitElement
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value="${this._name}"
.configValue="${"name"}"
@value-changed="${this._valueChanged}"
.value=${this._name}
.configValue=${"name"}
@value-changed=${this._valueChanged}
></paper-input>
<ha-icon-input
.label="${this.hass.localize(
@@ -94,20 +118,46 @@ export class HuiLightCardEditor extends LitElement
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value="${this._icon}"
.value=${this._icon}
.placeholder=${this._icon ||
stateIcon(this.hass.states[this._entity])}
.configValue="${"icon"}"
@value-changed="${this._valueChanged}"
.configValue=${"icon"}
@value-changed=${this._valueChanged}
></ha-icon-input>
</div>
<hui-theme-select-editor
.hass=${this.hass}
.value="${this._theme}"
.configValue="${"theme"}"
@value-changed="${this._valueChanged}"
.value=${this._theme}
.configValue=${"theme"}
@value-changed=${this._valueChanged}
></hui-theme-select-editor>
<hui-action-editor
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.hold_action"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.hass=${this.hass}
.config=${this._hold_action}
.actions=${actions}
.configValue=${"hold_action"}
@action-changed=${this._valueChanged}
></hui-action-editor>
<hui-action-editor
.label="${this.hass.localize(
"ui.panel.lovelace.editor.card.generic.double_tap_action"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.hass=${this.hass}
.config=${this._double_tap_action}
.actions=${actions}
.configValue=${"double_tap_action"}
@action-changed=${this._valueChanged}
></hui-action-editor>
</div>
`;
}
@@ -118,7 +168,10 @@ export class HuiLightCardEditor extends LitElement
}
const target = ev.target! as EditorTarget;
if (this[`_${target.configValue}`] === target.value) {
if (
this[`_${target.configValue}`] === target.value ||
this[`_${target.configValue}`] === target.config
) {
return;
}
if (target.configValue) {
@@ -127,7 +180,7 @@ export class HuiLightCardEditor extends LitElement
} else {
this._config = {
...this._config,
[target.configValue!]: target.value,
[target.configValue!]: target.value ? target.value : target.config,
};
}
}

View File

@@ -0,0 +1,95 @@
import { HomeAssistant } from "../../../types";
import { LovelaceBadgeConfig } from "../../../data/lovelace";
import { ConfigError } from "./types";
import { computeRTL } from "../../../common/util/compute_rtl";
import { LovelaceBadge } from "../types";
import { createBadgeElement } from "../create-element/create-badge-element";
import { createErrorBadgeConfig } from "../badges/hui-error-badge";
import "../../../components/entity/ha-state-label-badge";
export class HuiBadgePreview extends HTMLElement {
private _hass?: HomeAssistant;
private _element?: LovelaceBadge;
private _config?: LovelaceBadgeConfig;
private get _error() {
return this._element?.tagName === "HUI-ERROR-CARD";
}
constructor() {
super();
this.addEventListener("ll-rebuild", () => {
this._cleanup();
if (this._config) {
this.config = this._config;
}
});
}
set hass(hass: HomeAssistant) {
if (!this._hass || this._hass.language !== hass.language) {
this.style.direction = computeRTL(hass) ? "rtl" : "ltr";
}
this._hass = hass;
if (this._element) {
this._element.hass = hass;
}
}
set error(error: ConfigError) {
this._createBadge(
createErrorBadgeConfig(`${error.type}: ${error.message}`)
);
}
set config(configValue: LovelaceBadgeConfig) {
const curConfig = this._config;
this._config = configValue;
if (!configValue) {
this._cleanup();
return;
}
if (!this._element) {
this._createBadge(configValue);
return;
}
// in case the element was an error element we always want to recreate it
if (!this._error && curConfig && configValue.type === curConfig.type) {
this._element.setConfig(configValue);
} else {
this._createBadge(configValue);
}
}
private _createBadge(configValue: LovelaceBadgeConfig): void {
this._cleanup();
this._element = createBadgeElement(configValue);
if (this._hass) {
this._element!.hass = this._hass;
}
this.appendChild(this._element!);
}
private _cleanup() {
if (!this._element) {
return;
}
this.removeChild(this._element);
this._element = undefined;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-badge-preview": HuiBadgePreview;
}
}
customElements.define("hui-badge-preview", HuiBadgePreview);

View File

@@ -23,6 +23,7 @@ import { haStyleDialog } from "../../../../resources/styles";
import "../../components/hui-entity-editor";
import "./hui-view-editor";
import "./hui-view-visibility-editor";
import "../hui-badge-preview";
import { HomeAssistant } from "../../../../types";
import {
LovelaceViewConfig,
@@ -123,6 +124,20 @@ export class HuiEditView extends LitElement {
break;
case "tab-badges":
content = html`
${this._badges?.length
? html`
<div class="preview-badges">
${this._badges.map((badgeConfig) => {
return html`
<hui-badge-preview
.hass=${this.hass}
.config=${badgeConfig}
></hui-badge-preview>
`;
})}
</div>
`
: ""}
<hui-entity-editor
.hass=${this.hass}
.entities="${this._badges}"
@@ -310,6 +325,7 @@ export class HuiEditView extends LitElement {
return;
}
this._badges = processEditorEntities(ev.detail.entities);
this._resizeDialog();
}
private _isConfigChanged(): boolean {
@@ -372,8 +388,13 @@ export class HuiEditView extends LitElement {
color: var(--error-color);
border-bottom: 1px solid var(--error-color);
}
</style>
`,
.preview-badges {
display: flex;
justify-content: center;
margin: 8px 16px;
flex-wrap: wrap;
}
`,
];
}
}

View File

@@ -2021,6 +2021,9 @@
"toggle": "Toggle entities.",
"description": "The Entities card is the most common type of card. It groups items together into lists."
},
"entity": {
"name": "Entity"
},
"button": {
"name": "Button",
"description": "The Button card allows you to add buttons to perform tasks."
@@ -2062,8 +2065,10 @@
},
"generic": {
"aspect_ratio": "Aspect Ratio",
"attribute": "Attribute",
"camera_image": "Camera Entity",
"camera_view": "Camera View",
"double_tap_action": "Double Tap Action",
"entities": "Entities",
"entity": "Entity",
"hold_action": "Hold Action",
@@ -2155,6 +2160,10 @@
"description": "This renders the first card at full width; other cards in this view will not be rendered.",
"warning_multiple_cards": "This view contains more than one card, but a panel view can only show 1 card."
}
},
"cardpicker": {
"no_description": "No description available.",
"custom_card": "Custom"
}
},
"warning": {

View File

@@ -1615,12 +1615,12 @@
"add": "Ein Gerät hinzufügen",
"delete": "Gerät löschen",
"header": "Geräte",
"introduction": "Fügen Sie die Geräte hinzu, die in Ihrer Szene aufgenommen werden sollen. Stellen Sie alle Geräte so ein, wie sie in der Szene sein sollen."
"introduction": "Füge die Geräte hinzu, die in deine Szene aufgenommen werden sollen. Stelle alle Geräte so ein, wie sie in der Szene sein sollen."
},
"entities": {
"add": "Eine Entität hinzufügen",
"delete": "Entität löschen",
"device_entities": "Wenn Sie eine Entität hinzufügen, die zu einem Gerät gehört, wird das Gerät hinzugefügt.",
"device_entities": "Wenn du eine Entität hinzufügst, die zu einem Gerät gehört, wird das Gerät hinzugefügt.",
"header": "Entitäten",
"introduction": "Entitäten, die nicht zu einem Gerät gehören, können hier festgelegt werden.",
"without_device": "Entitäten ohne Gerät"
@@ -1634,7 +1634,7 @@
},
"picker": {
"add_scene": "Szene hinzufügen",
"delete_confirm": "Sind Sie sicher, dass Sie diese Szene löschen möchten?",
"delete_confirm": "Bist du sicher, dass du diese Szene löschen möchtest?",
"delete_scene": "Szene löschen",
"edit_scene": "Szene bearbeiten",
"header": "Szenen-Editor",
@@ -2355,7 +2355,7 @@
"refresh_header": "Möchtest Du aktualisieren?"
},
"unused_entities": {
"available_entities": "Dies sind die Entitäten, die Sie zur Verfügung haben, die aber noch nicht in Ihrer Lovelace-Benutzeroberfläche enthalten sind.",
"available_entities": "Dies sind die Entitäten, die du zur Verfügung hast, die aber noch nicht in deiner Lovelace-Benutzeroberfläche enthalten sind.",
"domain": "Domain",
"entity": "Entität",
"entity_id": "Entitäts-ID",

View File

@@ -812,6 +812,10 @@
"areas": {
"caption": "Areas",
"create_area": "CREATE AREA",
"data_table": {
"area": "Area",
"devices": "Devices"
},
"delete": {
"confirmation_text": "All devices in this area will become unassigned.",
"confirmation_title": "Are you sure you want to delete this area?"
@@ -1054,6 +1058,9 @@
"delete_confirm": "Are you sure you want to delete this automation?",
"edit_automation": "Edit automation",
"header": "Automation Editor",
"headers": {
"name": "Name"
},
"introduction": "The automation editor allows you to create and edit automations. Please follow the link below to read the instructions to make sure that you have configured Home Assistant correctly.",
"learn_more": "Learn more about automations",
"no_automations": "We couldnt find any editable automations",
@@ -1334,6 +1341,7 @@
},
"info": "Device info",
"name": "Name",
"no_devices": "No devices",
"scene": {
"create": "Create scene with device",
"no_scenes": "No scenes",
@@ -1638,6 +1646,9 @@
"delete_scene": "Delete scene",
"edit_scene": "Edit scene",
"header": "Scene Editor",
"headers": {
"name": "Name"
},
"introduction": "The scene editor allows you to create and edit scenes. Please follow the link below to read the instructions to make sure that you have configured Home Assistant correctly.",
"learn_more": "Learn more about scenes",
"no_scenes": "We couldnt find any editable scenes",
@@ -1665,9 +1676,13 @@
"add_script": "Add script",
"edit_script": "Edit script",
"header": "Script Editor",
"headers": {
"name": "Name"
},
"introduction": "The script editor allows you to create and edit scripts. Please follow the link below to read the instructions to make sure that you have configured Home Assistant correctly.",
"learn_more": "Learn more about scripts",
"no_scripts": "We couldnt find any editable scripts",
"show_info": "Show info about script",
"trigger_script": "Trigger script"
}
},
@@ -1725,14 +1740,21 @@
"group": "Group",
"group_update_failed": "Group update failed:",
"id": "ID",
"name": "Name",
"owner": "Owner",
"rename_user": "Rename user",
"system_generated": "System generated",
"system_generated_users_not_removable": "Unable to remove system generated users.",
"unnamed_user": "Unnamed User",
"update_user": "Update",
"user_rename_failed": "User rename failed:"
},
"picker": {
"headers": {
"group": "Group",
"name": "Name",
"system": "System"
},
"system_generated": "System generated",
"title": "Users"
}
@@ -2135,6 +2157,9 @@
"description": "The Entity Filter card allows you to define a list of entities that you want to track only when in a certain state.",
"name": "Entity Filter"
},
"entity": {
"name": "Entity"
},
"gauge": {
"description": "The Gauge card is a basic card that allows visually seeing sensor data.",
"name": "Gauge",
@@ -2147,6 +2172,7 @@
},
"generic": {
"aspect_ratio": "Aspect Ratio",
"attribute": "Attribute",
"camera_image": "Camera Entity",
"camera_view": "Camera View",
"entities": "Entities",
@@ -2319,6 +2345,7 @@
"save_config": {
"cancel": "Never mind",
"close": "Close",
"empty_config": "Start with an empty dashboard",
"header": "Take control of your Lovelace UI",
"para": "By default Home Assistant will maintain your user interface, updating it when new entities or Lovelace UI components become available. If you take control we will no longer make changes automatically for you.",
"para_sure": "Are you sure you want to take control of your user interface?",
@@ -2568,6 +2595,11 @@
"submit": "Submit"
},
"current_user": "You are currently logged in as {fullName}.",
"dashboard": {
"description": "Pick a default dashboard for this device.",
"dropdown_label": "Dashboard",
"header": "Dashboard"
},
"force_narrow": {
"description": "This will hide the sidebar by default, similar to the mobile experience.",
"header": "Always hide the sidebar"

View File

@@ -2348,7 +2348,7 @@
"domain": "Domain",
"entity": "Entitás",
"entity_id": "Entitás ID",
"last_changed": "Utoljára módosítva",
"last_changed": "Utoljára változott",
"select_to_add": "Válaszd ki azokat az entitásokat, amelyeket hozzá akarsz adni egy kártyához, majd kattints a kártya hozzáadása gombra.",
"title": "Nem használt entitások"
},