mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-12 10:49:25 +00:00
Compare commits
99 Commits
Better-row
...
20201229.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a9d926e80a | ||
![]() |
c41369c89c | ||
![]() |
656bef3da9 | ||
![]() |
3d7ee6a4df | ||
![]() |
d844c89b94 | ||
![]() |
177ea2b85a | ||
![]() |
50c5c15f49 | ||
![]() |
1810760dc7 | ||
![]() |
4635b92e3f | ||
![]() |
1c652626eb | ||
![]() |
2000cfb1db | ||
![]() |
f4d07828e7 | ||
![]() |
95b552671c | ||
![]() |
ef3bc3efe1 | ||
![]() |
371ad899f5 | ||
![]() |
2c54158d84 | ||
![]() |
5d9e30bbdc | ||
![]() |
e477fd567d | ||
![]() |
6a6c2937fe | ||
![]() |
09e17c4da8 | ||
![]() |
fd00469d11 | ||
![]() |
cbbeb795f3 | ||
![]() |
bba40e0da8 | ||
![]() |
d23165d06a | ||
![]() |
405fef6f03 | ||
![]() |
588f217826 | ||
![]() |
3d8b7cf80e | ||
![]() |
c0ef923ad3 | ||
![]() |
3df44fc71e | ||
![]() |
c1965492d9 | ||
![]() |
1f56ffde80 | ||
![]() |
f335fdc002 | ||
![]() |
0c914b5ec8 | ||
![]() |
d767b06858 | ||
![]() |
d4e49f3944 | ||
![]() |
7dfc5b3faf | ||
![]() |
8a88033ab9 | ||
![]() |
7b06b38c94 | ||
![]() |
5409752817 | ||
![]() |
909f3a3005 | ||
![]() |
4930532c7b | ||
![]() |
8a42e65c6a | ||
![]() |
5d4121a9b4 | ||
![]() |
a70e6c49a1 | ||
![]() |
3d83d5f4b5 | ||
![]() |
f9dece0743 | ||
![]() |
ac0871d0e8 | ||
![]() |
ffc19e591d | ||
![]() |
c53380ca3d | ||
![]() |
7c74a2026a | ||
![]() |
adaed438d9 | ||
![]() |
baf38305cb | ||
![]() |
8254712521 | ||
![]() |
53214781e3 | ||
![]() |
88cbbbdf65 | ||
![]() |
c10dca9c7b | ||
![]() |
7f2ebb4bde | ||
![]() |
f1abb60e4a | ||
![]() |
e014c7aff6 | ||
![]() |
b79c03433e | ||
![]() |
34eb4d974d | ||
![]() |
3264be3c5e | ||
![]() |
655f4f75fb | ||
![]() |
4383f31696 | ||
![]() |
99eb15d15e | ||
![]() |
2682c6e150 | ||
![]() |
3a5d854e6d | ||
![]() |
1e90c6387c | ||
![]() |
2cca25f4d0 | ||
![]() |
565724d201 | ||
![]() |
3e4955becd | ||
![]() |
7b560c727f | ||
![]() |
35abd9dfdb | ||
![]() |
b7ccf3e0e5 | ||
![]() |
0d9ab8fdd0 | ||
![]() |
303f9290a8 | ||
![]() |
e0c4dc08a1 | ||
![]() |
8c655883fe | ||
![]() |
ba90785115 | ||
![]() |
7b392b626b | ||
![]() |
8e4ceb7d48 | ||
![]() |
2ab1c6e9a9 | ||
![]() |
dbdced0971 | ||
![]() |
5e481880bd | ||
![]() |
faec063f34 | ||
![]() |
bbea38d227 | ||
![]() |
a0ef60de49 | ||
![]() |
3313572606 | ||
![]() |
c4f850cb14 | ||
![]() |
3bdab738c6 | ||
![]() |
faaef31b9f | ||
![]() |
ca7b8b8b4c | ||
![]() |
9ca84e0694 | ||
![]() |
daaf2b1796 | ||
![]() |
25f7cbea5a | ||
![]() |
c485ea9d7b | ||
![]() |
295390c8e9 | ||
![]() |
3ebf816ce2 | ||
![]() |
50e7410002 |
@@ -14,7 +14,7 @@ This is the repository for the official [Home Assistant](https://home-assistant.
|
||||
- Development: [Instructions](https://developers.home-assistant.io/docs/frontend/development/)
|
||||
- Production build: `script/build_frontend`
|
||||
- Gallery: `cd gallery && script/develop_gallery`
|
||||
- Hass.io: [Instructions](https://developers.home-assistant.io/docs/en/hassio_hass.html)
|
||||
- Supervisor: [Instructions](https://developers.home-assistant.io/docs/supervisor/developing)
|
||||
|
||||
## Frontend development
|
||||
|
||||
|
@@ -7,8 +7,8 @@ export const createMediaPlayerEntities = () => [
|
||||
media_title: "I Wanna Be A Hippy (Flamman & Abraxas Radio Mix)",
|
||||
media_artist: "Technohead",
|
||||
// Pause + Seek + Volume Set + Volume Mute + Previous Track + Next Track + Play Media +
|
||||
// Select Source + Stop + Clear + Play + Shuffle Set + Browse Media
|
||||
supported_features: 195135,
|
||||
// Select Source + Stop + Clear + Play + Shuffle Set
|
||||
supported_features: 64063,
|
||||
entity_picture: "/images/album_cover_2.jpg",
|
||||
media_duration: 300,
|
||||
media_position: 50,
|
||||
@@ -24,8 +24,8 @@ export const createMediaPlayerEntities = () => [
|
||||
media_title: "I Wanna Be A Hippy (Flamman & Abraxas Radio Mix)",
|
||||
media_artist: "Technohead",
|
||||
// Pause + Seek + Volume Set + Volume Mute + Previous Track + Next Track + Play Media +
|
||||
// Select Source + Stop + Clear + Play + Shuffle Set
|
||||
supported_features: 64063,
|
||||
// Select Source + Stop + Clear + Play + Shuffle Set + Browse Media
|
||||
supported_features: 195135,
|
||||
entity_picture: "/images/album_cover.jpg",
|
||||
media_duration: 300,
|
||||
media_position: 0,
|
||||
|
@@ -146,6 +146,16 @@ const CONFIGS = [
|
||||
entity: media_player.receiver_off
|
||||
`,
|
||||
},
|
||||
{
|
||||
heading: "Grid Full Size",
|
||||
config: `
|
||||
- type: grid
|
||||
columns: 1
|
||||
cards:
|
||||
- type: media-control
|
||||
entity: media_player.music_paused
|
||||
`,
|
||||
},
|
||||
];
|
||||
|
||||
class DemoHuiMediControlCard extends PolymerElement {
|
||||
|
@@ -69,7 +69,7 @@ const STAGE_ICON = {
|
||||
const PERMIS_DESC = {
|
||||
stage: {
|
||||
title: "Add-on Stage",
|
||||
description: `Add-ons can have one of three stages:\n\n<ha-svg-icon .path='${STAGE_ICON.stable}'></ha-svg-icon> **Stable**: These are add-ons ready to be used in production.\n\n<ha-svg-icon .path='${STAGE_ICON.experimental}'></ha-svg-icon> **Experimental**: These may contain bugs, and may be unfinished.\n\n<ha-svg-icon .path='${STAGE_ICON.deprecated}'></ha-svg-icon> **Deprecated**: These add-ons will no longer receive any updates.`,
|
||||
description: `Add-ons can have one of three stages:\n\n<ha-svg-icon path="${STAGE_ICON.stable}"></ha-svg-icon> **Stable**: These are add-ons ready to be used in production.\n\n<ha-svg-icon path="${STAGE_ICON.experimental}"></ha-svg-icon> **Experimental**: These may contain bugs, and may be unfinished.\n\n<ha-svg-icon path="${STAGE_ICON.deprecated}"></ha-svg-icon> **Deprecated**: These add-ons will no longer receive any updates.`,
|
||||
},
|
||||
rating: {
|
||||
title: "Add-on Security Rating",
|
||||
|
@@ -74,9 +74,7 @@ export class HassioUpdate extends LitElement {
|
||||
"Supervisor",
|
||||
this.supervisor.supervisor,
|
||||
"hassio/supervisor/update",
|
||||
`https://github.com//home-assistant/hassio/releases/tag/${
|
||||
this.supervisor.supervisor.version_latest
|
||||
}`
|
||||
`https://github.com//home-assistant/hassio/releases/tag/${this.supervisor.supervisor.version_latest}`
|
||||
)}
|
||||
${this.supervisor.host.features.includes("hassos")
|
||||
? this._renderUpdateCard(
|
||||
|
@@ -178,7 +178,7 @@ class HassioSupervisorInfo extends LitElement {
|
||||
</div>`}
|
||||
${!this.supervisor.supervisor.healthy
|
||||
? html`<div class="error">
|
||||
Your installtion is running in an unhealthy state.
|
||||
Your installation is running in an unhealthy state.
|
||||
<button
|
||||
class="link"
|
||||
title="Learn more about why your system is marked as unhealthy"
|
||||
|
2
setup.py
2
setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="home-assistant-frontend",
|
||||
version="20201126.0",
|
||||
version="20201229.1",
|
||||
description="The Home Assistant frontend",
|
||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||
author="The Home Assistant Authors",
|
||||
|
6
src/common/ensure-array.ts
Normal file
6
src/common/ensure-array.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const ensureArray = (value?: any) => {
|
||||
if (!value || Array.isArray(value)) {
|
||||
return value;
|
||||
}
|
||||
return [value];
|
||||
};
|
@@ -67,6 +67,10 @@ export const computeStateDisplay = (
|
||||
}
|
||||
}
|
||||
|
||||
if (domain === "counter") {
|
||||
return formatNumber(compareState, language);
|
||||
}
|
||||
|
||||
return (
|
||||
// Return device class translation
|
||||
(stateObj.attributes.device_class &&
|
||||
|
@@ -1,8 +1,12 @@
|
||||
export const copyToClipboard = (str) => {
|
||||
const el = document.createElement("textarea");
|
||||
el.value = str;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(el);
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(str);
|
||||
} else {
|
||||
const el = document.createElement("textarea");
|
||||
el.value = str;
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(el);
|
||||
}
|
||||
};
|
||||
|
@@ -98,6 +98,12 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public hasFab = false;
|
||||
|
||||
/**
|
||||
* Add an extra row at the bottom of the data table
|
||||
* @type {TemplateResult}
|
||||
*/
|
||||
@property({ attribute: false }) public appendRow?;
|
||||
|
||||
@property({ type: Boolean, attribute: "auto-height" })
|
||||
public autoHeight = false;
|
||||
|
||||
@@ -126,6 +132,8 @@ export class HaDataTable extends LitElement {
|
||||
|
||||
@query("slot[name='header']") private _header!: HTMLSlotElement;
|
||||
|
||||
private _items: DataTableRowData[] = [];
|
||||
|
||||
private _checkableRowsCount?: number;
|
||||
|
||||
private _checkedRows: string[] = [];
|
||||
@@ -318,10 +326,13 @@ export class HaDataTable extends LitElement {
|
||||
@scroll=${this._saveScrollPos}
|
||||
>
|
||||
${scroll({
|
||||
items: !this.hasFab
|
||||
? this._filteredData
|
||||
: [...this._filteredData, ...[{ empty: true }]],
|
||||
items: this._items,
|
||||
renderItem: (row: DataTableRowData, index) => {
|
||||
if (row.append) {
|
||||
return html`
|
||||
<div class="mdc-data-table__row">${row.content}</div>
|
||||
`;
|
||||
}
|
||||
if (row.empty) {
|
||||
return html` <div class="mdc-data-table__row"></div> `;
|
||||
}
|
||||
@@ -447,6 +458,20 @@ export class HaDataTable extends LitElement {
|
||||
if (this.curRequest !== curRequest) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.appendRow || this.hasFab) {
|
||||
this._items = [...data];
|
||||
|
||||
if (this.appendRow) {
|
||||
this._items.push({ append: true, content: this.appendRow });
|
||||
}
|
||||
|
||||
if (this.hasFab) {
|
||||
this._items.push({ empty: true });
|
||||
}
|
||||
} else {
|
||||
this._items = data;
|
||||
}
|
||||
this._filteredData = data;
|
||||
}
|
||||
|
||||
|
@@ -58,6 +58,14 @@ const sortData = (
|
||||
valB = valB.toUpperCase();
|
||||
}
|
||||
|
||||
// Ensure "undefined" is always sorted to the bottom
|
||||
if (valA === undefined && valB !== undefined) {
|
||||
return 1;
|
||||
}
|
||||
if (valB === undefined && valA !== undefined) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (valA < valB) {
|
||||
return sort * -1;
|
||||
}
|
||||
|
@@ -139,7 +139,7 @@ export class HaAreaDevicesPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
private _filteredDevices: DeviceRegistryEntry[] = [];
|
||||
|
||||
private _getDevices = memoizeOne(
|
||||
private _getAreasWithDevices = memoizeOne(
|
||||
(
|
||||
devices: DeviceRegistryEntry[],
|
||||
areas: AreaRegistryEntry[],
|
||||
@@ -277,7 +277,7 @@ export class HaAreaDevicesPicker extends SubscribeMixin(LitElement) {
|
||||
if (!this._devices || !this._areas || !this._entities) {
|
||||
return html``;
|
||||
}
|
||||
const areas = this._getDevices(
|
||||
const areas = this._getAreasWithDevices(
|
||||
this._devices,
|
||||
this._areas,
|
||||
this._entities,
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "../ha-icon-button";
|
||||
import "../ha-svg-icon";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
@@ -12,6 +13,8 @@ import {
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
query,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import memoizeOne from "memoize-one";
|
||||
@@ -35,6 +38,7 @@ import {
|
||||
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
||||
import { PolymerChangedEvent } from "../../polymer-types";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { mdiClose, mdiMenuUp, mdiMenuDown } from "@mdi/js";
|
||||
|
||||
interface Device {
|
||||
name: string;
|
||||
@@ -111,6 +115,10 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
@property({ type: Boolean })
|
||||
private _opened?: boolean;
|
||||
|
||||
@query("vaadin-combo-box-light", true) private _comboBox!: HTMLElement;
|
||||
|
||||
private _init = false;
|
||||
|
||||
private _getDevices = memoizeOne(
|
||||
(
|
||||
devices: DeviceRegistryEntry[],
|
||||
@@ -122,18 +130,27 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
deviceFilter: this["deviceFilter"]
|
||||
): Device[] => {
|
||||
if (!devices.length) {
|
||||
return [];
|
||||
return [
|
||||
{
|
||||
id: "",
|
||||
area: "",
|
||||
name: this.hass.localize("ui.components.device-picker.no_devices"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const deviceEntityLookup: DeviceEntityLookup = {};
|
||||
for (const entity of entities) {
|
||||
if (!entity.device_id) {
|
||||
continue;
|
||||
|
||||
if (includeDomains || excludeDomains || includeDeviceClasses) {
|
||||
for (const entity of entities) {
|
||||
if (!entity.device_id) {
|
||||
continue;
|
||||
}
|
||||
if (!(entity.device_id in deviceEntityLookup)) {
|
||||
deviceEntityLookup[entity.device_id] = [];
|
||||
}
|
||||
deviceEntityLookup[entity.device_id].push(entity);
|
||||
}
|
||||
if (!(entity.device_id in deviceEntityLookup)) {
|
||||
deviceEntityLookup[entity.device_id] = [];
|
||||
}
|
||||
deviceEntityLookup[entity.device_id].push(entity);
|
||||
}
|
||||
|
||||
const areaLookup: { [areaId: string]: AreaRegistryEntry } = {};
|
||||
@@ -141,7 +158,9 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
areaLookup[area.area_id] = area;
|
||||
}
|
||||
|
||||
let inputDevices = [...devices];
|
||||
let inputDevices = devices.filter(
|
||||
(device) => device.id === this.value || !device.disabled_by
|
||||
);
|
||||
|
||||
if (includeDomains) {
|
||||
inputDevices = inputDevices.filter((device) => {
|
||||
@@ -208,6 +227,15 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
: this.hass.localize("ui.components.device-picker.no_area"),
|
||||
};
|
||||
});
|
||||
if (!outputDevices.length) {
|
||||
return [
|
||||
{
|
||||
id: "",
|
||||
area: "",
|
||||
name: this.hass.localize("ui.components.device-picker.no_match"),
|
||||
},
|
||||
];
|
||||
}
|
||||
if (outputDevices.length === 1) {
|
||||
return outputDevices;
|
||||
}
|
||||
@@ -215,6 +243,18 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
);
|
||||
|
||||
public open() {
|
||||
this.updateComplete.then(() => {
|
||||
(this.shadowRoot?.querySelector("vaadin-combo-box-light") as any)?.open();
|
||||
});
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this.updateComplete.then(() => {
|
||||
this.shadowRoot?.querySelector("paper-input")?.focus();
|
||||
});
|
||||
}
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
|
||||
@@ -229,25 +269,33 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
];
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (
|
||||
(!this._init && this.devices && this.areas && this.entities) ||
|
||||
(changedProps.has("_opened") && this._opened)
|
||||
) {
|
||||
this._init = true;
|
||||
(this._comboBox as any).items = this._getDevices(
|
||||
this.devices!,
|
||||
this.areas!,
|
||||
this.entities!,
|
||||
this.includeDomains,
|
||||
this.excludeDomains,
|
||||
this.includeDeviceClasses,
|
||||
this.deviceFilter
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.devices || !this.areas || !this.entities) {
|
||||
return html``;
|
||||
}
|
||||
const devices = this._getDevices(
|
||||
this.devices,
|
||||
this.areas,
|
||||
this.entities,
|
||||
this.includeDomains,
|
||||
this.excludeDomains,
|
||||
this.includeDeviceClasses,
|
||||
this.deviceFilter
|
||||
);
|
||||
return html`
|
||||
<vaadin-combo-box-light
|
||||
item-value-path="id"
|
||||
item-id-path="id"
|
||||
item-label-path="name"
|
||||
.items=${devices}
|
||||
.value=${this._value}
|
||||
.renderer=${rowRenderer}
|
||||
@opened-changed=${this._openedChanged}
|
||||
@@ -265,34 +313,30 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
>
|
||||
${this.value
|
||||
? html`
|
||||
<ha-icon-button
|
||||
aria-label=${this.hass.localize(
|
||||
<mwc-icon-button
|
||||
.label=${this.hass.localize(
|
||||
"ui.components.device-picker.clear"
|
||||
)}
|
||||
slot="suffix"
|
||||
class="clear-button"
|
||||
icon="hass:close"
|
||||
@click=${this._clearValue}
|
||||
no-ripple
|
||||
>
|
||||
Clear
|
||||
</ha-icon-button>
|
||||
`
|
||||
: ""}
|
||||
${devices.length > 0
|
||||
? html`
|
||||
<ha-icon-button
|
||||
aria-label=${this.hass.localize(
|
||||
"ui.components.device-picker.show_devices"
|
||||
)}
|
||||
slot="suffix"
|
||||
class="toggle-button"
|
||||
.icon=${this._opened ? "hass:menu-up" : "hass:menu-down"}
|
||||
>
|
||||
Toggle
|
||||
</ha-icon-button>
|
||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
`
|
||||
: ""}
|
||||
|
||||
<mwc-icon-button
|
||||
.label=${this.hass.localize(
|
||||
"ui.components.device-picker.show_devices"
|
||||
)}
|
||||
slot="suffix"
|
||||
class="toggle-button"
|
||||
>
|
||||
<ha-svg-icon
|
||||
.path=${this._opened ? mdiMenuUp : mdiMenuDown}
|
||||
></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</paper-input>
|
||||
</vaadin-combo-box-light>
|
||||
`;
|
||||
@@ -329,7 +373,7 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
paper-input > ha-icon-button {
|
||||
paper-input > mwc-icon-button {
|
||||
--mdc-icon-button-size: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
|
@@ -101,6 +101,18 @@ export class HaEntityPicker extends LitElement {
|
||||
|
||||
@query("vaadin-combo-box-light", true) private _comboBox!: HTMLElement;
|
||||
|
||||
public open() {
|
||||
this.updateComplete.then(() => {
|
||||
(this.shadowRoot?.querySelector("vaadin-combo-box-light") as any)?.open();
|
||||
});
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this.updateComplete.then(() => {
|
||||
this.shadowRoot?.querySelector("paper-input")?.focus();
|
||||
});
|
||||
}
|
||||
|
||||
private _initedStates = false;
|
||||
|
||||
private _states: HassEntity[] = [];
|
||||
@@ -153,6 +165,24 @@ export class HaEntityPicker extends LitElement {
|
||||
);
|
||||
}
|
||||
|
||||
if (!states.length) {
|
||||
return [
|
||||
{
|
||||
entity_id: "",
|
||||
state: "",
|
||||
last_changed: "",
|
||||
last_updated: "",
|
||||
context: { id: "", user_id: null },
|
||||
attributes: {
|
||||
friendly_name: this.hass!.localize(
|
||||
"ui.components.entity.entity-picker.no_match"
|
||||
),
|
||||
icon: "mdi:magnify",
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return states;
|
||||
}
|
||||
);
|
||||
@@ -203,7 +233,6 @@ export class HaEntityPicker extends LitElement {
|
||||
.label=${this.label === undefined
|
||||
? this.hass.localize("ui.components.entity.entity-picker.entity")
|
||||
: this.label}
|
||||
.value=${this._value}
|
||||
.disabled=${this.disabled}
|
||||
class="input"
|
||||
autocapitalize="none"
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import "./ha-icon-button";
|
||||
import "./ha-svg-icon";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-item/paper-item-body";
|
||||
@@ -14,6 +15,8 @@ import {
|
||||
property,
|
||||
internalProperty,
|
||||
TemplateResult,
|
||||
PropertyValues,
|
||||
query,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import {
|
||||
@@ -29,6 +32,18 @@ import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||
import { PolymerChangedEvent } from "../polymer-types";
|
||||
import { HomeAssistant } from "../types";
|
||||
import memoizeOne from "memoize-one";
|
||||
import {
|
||||
DeviceEntityLookup,
|
||||
DeviceRegistryEntry,
|
||||
subscribeDeviceRegistry,
|
||||
} from "../data/device_registry";
|
||||
import {
|
||||
EntityRegistryEntry,
|
||||
subscribeEntityRegistry,
|
||||
} from "../data/entity_registry";
|
||||
import { computeDomain } from "../common/entity/compute_domain";
|
||||
import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker";
|
||||
import { mdiClose, mdiMenuDown, mdiMenuUp } from "@mdi/js";
|
||||
|
||||
const rowRenderer = (
|
||||
root: HTMLElement,
|
||||
@@ -71,31 +86,250 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
@property() public placeholder?: string;
|
||||
|
||||
@property() public _areas?: AreaRegistryEntry[];
|
||||
|
||||
@property({ type: Boolean, attribute: "no-add" })
|
||||
public noAdd?: boolean;
|
||||
|
||||
/**
|
||||
* Show only areas with entities from specific domains.
|
||||
* @type {Array}
|
||||
* @attr include-domains
|
||||
*/
|
||||
@property({ type: Array, attribute: "include-domains" })
|
||||
public includeDomains?: string[];
|
||||
|
||||
/**
|
||||
* Show no areas with entities of these domains.
|
||||
* @type {Array}
|
||||
* @attr exclude-domains
|
||||
*/
|
||||
@property({ type: Array, attribute: "exclude-domains" })
|
||||
public excludeDomains?: string[];
|
||||
|
||||
/**
|
||||
* Show only areas with entities of these device classes.
|
||||
* @type {Array}
|
||||
* @attr include-device-classes
|
||||
*/
|
||||
@property({ type: Array, attribute: "include-device-classes" })
|
||||
public includeDeviceClasses?: string[];
|
||||
|
||||
@property() public deviceFilter?: HaDevicePickerDeviceFilterFunc;
|
||||
|
||||
@property() public entityFilter?: (entity: EntityRegistryEntry) => boolean;
|
||||
|
||||
@internalProperty() private _areas?: AreaRegistryEntry[];
|
||||
|
||||
@internalProperty() private _devices?: DeviceRegistryEntry[];
|
||||
|
||||
@internalProperty() private _entities?: EntityRegistryEntry[];
|
||||
|
||||
@internalProperty() private _opened?: boolean;
|
||||
|
||||
@query("vaadin-combo-box-light", true) private _comboBox!: HTMLElement;
|
||||
|
||||
private _init = false;
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeAreaRegistry(this.hass.connection!, (areas) => {
|
||||
this._areas = this.noAdd
|
||||
? areas
|
||||
: [
|
||||
...areas,
|
||||
{
|
||||
area_id: "add_new",
|
||||
name: this.hass.localize("ui.components.area-picker.add_new"),
|
||||
},
|
||||
];
|
||||
this._areas = areas;
|
||||
}),
|
||||
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
|
||||
this._devices = devices;
|
||||
}),
|
||||
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
||||
this._entities = entities;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public open() {
|
||||
this.updateComplete.then(() => {
|
||||
(this.shadowRoot?.querySelector("vaadin-combo-box-light") as any)?.open();
|
||||
});
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this.updateComplete.then(() => {
|
||||
this.shadowRoot?.querySelector("paper-input")?.focus();
|
||||
});
|
||||
}
|
||||
|
||||
private _getAreas = memoizeOne(
|
||||
(
|
||||
areas: AreaRegistryEntry[],
|
||||
devices: DeviceRegistryEntry[],
|
||||
entities: EntityRegistryEntry[],
|
||||
includeDomains: this["includeDomains"],
|
||||
excludeDomains: this["excludeDomains"],
|
||||
includeDeviceClasses: this["includeDeviceClasses"],
|
||||
deviceFilter: this["deviceFilter"],
|
||||
entityFilter: this["entityFilter"],
|
||||
noAdd: this["noAdd"]
|
||||
): AreaRegistryEntry[] => {
|
||||
if (!areas.length) {
|
||||
return [
|
||||
{
|
||||
area_id: "",
|
||||
name: this.hass.localize("ui.components.area-picker.no_areas"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const deviceEntityLookup: DeviceEntityLookup = {};
|
||||
let inputDevices: DeviceRegistryEntry[] | undefined;
|
||||
let inputEntities: EntityRegistryEntry[] | undefined;
|
||||
|
||||
if (includeDomains || excludeDomains || includeDeviceClasses) {
|
||||
for (const entity of entities) {
|
||||
if (!entity.device_id) {
|
||||
continue;
|
||||
}
|
||||
if (!(entity.device_id in deviceEntityLookup)) {
|
||||
deviceEntityLookup[entity.device_id] = [];
|
||||
}
|
||||
deviceEntityLookup[entity.device_id].push(entity);
|
||||
}
|
||||
inputDevices = devices;
|
||||
inputEntities = entities.filter((entity) => entity.area_id);
|
||||
} else if (deviceFilter) {
|
||||
inputDevices = devices;
|
||||
} else if (entityFilter) {
|
||||
inputEntities = entities.filter((entity) => entity.area_id);
|
||||
}
|
||||
|
||||
if (includeDomains) {
|
||||
inputDevices = inputDevices!.filter((device) => {
|
||||
const devEntities = deviceEntityLookup[device.id];
|
||||
if (!devEntities || !devEntities.length) {
|
||||
return false;
|
||||
}
|
||||
return deviceEntityLookup[device.id].some((entity) =>
|
||||
includeDomains.includes(computeDomain(entity.entity_id))
|
||||
);
|
||||
});
|
||||
inputEntities = inputEntities!.filter((entity) =>
|
||||
includeDomains.includes(computeDomain(entity.entity_id))
|
||||
);
|
||||
}
|
||||
|
||||
if (excludeDomains) {
|
||||
inputDevices = inputDevices!.filter((device) => {
|
||||
const devEntities = deviceEntityLookup[device.id];
|
||||
if (!devEntities || !devEntities.length) {
|
||||
return true;
|
||||
}
|
||||
return entities.every(
|
||||
(entity) =>
|
||||
!excludeDomains.includes(computeDomain(entity.entity_id))
|
||||
);
|
||||
});
|
||||
inputEntities = inputEntities!.filter(
|
||||
(entity) => !excludeDomains.includes(computeDomain(entity.entity_id))
|
||||
);
|
||||
}
|
||||
|
||||
if (includeDeviceClasses) {
|
||||
inputDevices = inputDevices!.filter((device) => {
|
||||
const devEntities = deviceEntityLookup[device.id];
|
||||
if (!devEntities || !devEntities.length) {
|
||||
return false;
|
||||
}
|
||||
return deviceEntityLookup[device.id].some((entity) => {
|
||||
const stateObj = this.hass.states[entity.entity_id];
|
||||
if (!stateObj) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
stateObj.attributes.device_class &&
|
||||
includeDeviceClasses.includes(stateObj.attributes.device_class)
|
||||
);
|
||||
});
|
||||
});
|
||||
inputEntities = inputEntities!.filter((entity) => {
|
||||
const stateObj = this.hass.states[entity.entity_id];
|
||||
return (
|
||||
stateObj.attributes.device_class &&
|
||||
includeDeviceClasses.includes(stateObj.attributes.device_class)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (deviceFilter) {
|
||||
inputDevices = inputDevices!.filter((device) => deviceFilter!(device));
|
||||
}
|
||||
|
||||
if (entityFilter) {
|
||||
inputEntities = inputEntities!.filter((entity) =>
|
||||
entityFilter!(entity)
|
||||
);
|
||||
}
|
||||
|
||||
let outputAreas = areas;
|
||||
|
||||
let areaIds: string[] | undefined;
|
||||
|
||||
if (inputDevices) {
|
||||
areaIds = inputDevices
|
||||
.filter((device) => device.area_id)
|
||||
.map((device) => device.area_id!);
|
||||
}
|
||||
|
||||
if (inputEntities) {
|
||||
areaIds = (areaIds ?? []).concat(
|
||||
inputEntities
|
||||
.filter((entity) => entity.area_id)
|
||||
.map((entity) => entity.area_id!)
|
||||
);
|
||||
}
|
||||
|
||||
if (areaIds) {
|
||||
outputAreas = areas.filter((area) => areaIds!.includes(area.area_id));
|
||||
}
|
||||
|
||||
if (!outputAreas.length) {
|
||||
outputAreas = [
|
||||
{
|
||||
area_id: "",
|
||||
name: this.hass.localize("ui.components.area-picker.no_match"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return noAdd
|
||||
? outputAreas
|
||||
: [
|
||||
...outputAreas,
|
||||
{
|
||||
area_id: "add_new",
|
||||
name: this.hass.localize("ui.components.area-picker.add_new"),
|
||||
},
|
||||
];
|
||||
}
|
||||
);
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (
|
||||
(!this._init && this._devices && this._areas && this._entities) ||
|
||||
(changedProps.has("_opened") && this._opened)
|
||||
) {
|
||||
this._init = true;
|
||||
(this._comboBox as any).items = this._getAreas(
|
||||
this._areas!,
|
||||
this._devices!,
|
||||
this._entities!,
|
||||
this.includeDomains,
|
||||
this.excludeDomains,
|
||||
this.includeDeviceClasses,
|
||||
this.deviceFilter,
|
||||
this.entityFilter,
|
||||
this.noAdd
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._areas) {
|
||||
if (!this._devices || !this._areas || !this._entities) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
@@ -103,7 +337,6 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
|
||||
item-value-path="area_id"
|
||||
item-id-path="area_id"
|
||||
item-label-path="name"
|
||||
.items=${this._areas}
|
||||
.value=${this._value}
|
||||
.renderer=${rowRenderer}
|
||||
@opened-changed=${this._openedChanged}
|
||||
@@ -124,34 +357,28 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
|
||||
>
|
||||
${this.value
|
||||
? html`
|
||||
<ha-icon-button
|
||||
aria-label=${this.hass.localize(
|
||||
<mwc-icon-button
|
||||
.label=${this.hass.localize(
|
||||
"ui.components.area-picker.clear"
|
||||
)}
|
||||
slot="suffix"
|
||||
class="clear-button"
|
||||
icon="hass:close"
|
||||
@click=${this._clearValue}
|
||||
no-ripple
|
||||
>
|
||||
${this.hass.localize("ui.components.area-picker.clear")}
|
||||
</ha-icon-button>
|
||||
`
|
||||
: ""}
|
||||
${this._areas.length > 0
|
||||
? html`
|
||||
<ha-icon-button
|
||||
aria-label=${this.hass.localize(
|
||||
"ui.components.area-picker.show_areas"
|
||||
)}
|
||||
slot="suffix"
|
||||
class="toggle-button"
|
||||
.icon=${this._opened ? "hass:menu-up" : "hass:menu-down"}
|
||||
>
|
||||
${this.hass.localize("ui.components.area-picker.toggle")}
|
||||
</ha-icon-button>
|
||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
`
|
||||
: ""}
|
||||
|
||||
<mwc-icon-button
|
||||
.label=${this.hass.localize("ui.components.area-picker.toggle")}
|
||||
slot="suffix"
|
||||
class="toggle-button"
|
||||
>
|
||||
<ha-svg-icon
|
||||
.path=${this._opened ? mdiMenuUp : mdiMenuDown}
|
||||
></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
</paper-input>
|
||||
</vaadin-combo-box-light>
|
||||
`;
|
||||
@@ -227,7 +454,7 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
paper-input > ha-icon-button {
|
||||
paper-input > mwc-icon-button {
|
||||
--mdc-icon-button-size: 24px;
|
||||
padding: 2px;
|
||||
color: var(--secondary-text-color);
|
||||
|
@@ -52,6 +52,7 @@ class HaBluePrintPicker extends LitElement {
|
||||
.label=${this.label ||
|
||||
this.hass.localize("ui.components.blueprint-picker.label")}
|
||||
.disabled=${this.disabled}
|
||||
horizontal-align="left"
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
@@ -110,6 +111,9 @@ class HaBluePrintPicker extends LitElement {
|
||||
paper-listbox {
|
||||
min-width: 200px;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ import {
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { ToggleButton } from "../types";
|
||||
import "./ha-svg-icon";
|
||||
import "@material/mwc-button/mwc-button";
|
||||
|
||||
@customElement("ha-button-toggle-group")
|
||||
export class HaButtonToggleGroup extends LitElement {
|
||||
@@ -21,17 +22,22 @@ export class HaButtonToggleGroup extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div>
|
||||
${this.buttons.map(
|
||||
(button) => html`
|
||||
<mwc-icon-button
|
||||
.label=${button.label}
|
||||
.value=${button.value}
|
||||
?active=${this.active === button.value}
|
||||
@click=${this._handleClick}
|
||||
>
|
||||
<ha-svg-icon .path=${button.iconPath}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
`
|
||||
${this.buttons.map((button) =>
|
||||
button.iconPath
|
||||
? html`<mwc-icon-button
|
||||
.label=${button.label}
|
||||
.value=${button.value}
|
||||
?active=${this.active === button.value}
|
||||
@click=${this._handleClick}
|
||||
>
|
||||
<ha-svg-icon .path=${button.iconPath}></ha-svg-icon>
|
||||
</mwc-icon-button>`
|
||||
: html`<mwc-button
|
||||
.value=${button.value}
|
||||
?active=${this.active === button.value}
|
||||
@click=${this._handleClick}
|
||||
>${button.label}</mwc-button
|
||||
>`
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
@@ -49,13 +55,15 @@ export class HaButtonToggleGroup extends LitElement {
|
||||
--mdc-icon-button-size: var(--button-toggle-size, 36px);
|
||||
--mdc-icon-size: var(--button-toggle-icon-size, 20px);
|
||||
}
|
||||
mwc-icon-button {
|
||||
mwc-icon-button,
|
||||
mwc-button {
|
||||
border: 1px solid var(--primary-color);
|
||||
border-right-width: 0px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
mwc-icon-button::before {
|
||||
mwc-icon-button::before,
|
||||
mwc-button::before {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
@@ -67,17 +75,21 @@ export class HaButtonToggleGroup extends LitElement {
|
||||
content: "";
|
||||
transition: opacity 15ms linear, background-color 15ms linear;
|
||||
}
|
||||
mwc-icon-button[active]::before {
|
||||
mwc-icon-button[active]::before,
|
||||
mwc-button[active]::before {
|
||||
opacity: var(--mdc-icon-button-ripple-opacity, 0.12);
|
||||
}
|
||||
mwc-icon-button:first-child {
|
||||
mwc-icon-button:first-child,
|
||||
mwc-button:first-child {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
mwc-icon-button:last-child {
|
||||
mwc-icon-button:last-child,
|
||||
mwc-button:last-child {
|
||||
border-radius: 0 4px 4px 0;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
mwc-icon-button:only-child {
|
||||
mwc-icon-button:only-child,
|
||||
mwc-button:only-child {
|
||||
border-radius: 4px;
|
||||
border-right-width: 1px;
|
||||
}
|
||||
|
@@ -127,7 +127,7 @@ class HaHLSPlayer extends LitElement {
|
||||
|
||||
// Parse playlist assuming it is a master playlist. Match group 1 is whether hevc, match group 2 is regular playlist url
|
||||
// See https://tools.ietf.org/html/rfc8216 for HLS spec details
|
||||
const playlistRegexp = /#EXT-X-STREAM-INF:.*?(?:CODECS=".*?(?<isHevc>hev1|hvc1)?\..*?".*?)?(?:\n|\r\n)(?<streamUrl>.+)/g;
|
||||
const playlistRegexp = /#EXT-X-STREAM-INF:.*?(?:CODECS=".*?(hev1|hvc1)?\..*?".*?)?(?:\n|\r\n)(.+)/g;
|
||||
const match = playlistRegexp.exec(masterPlaylist);
|
||||
const matchTwice = playlistRegexp.exec(masterPlaylist);
|
||||
|
||||
@@ -136,17 +136,13 @@ class HaHLSPlayer extends LitElement {
|
||||
let playlist_url: string;
|
||||
if (match !== null && matchTwice === null) {
|
||||
// Only send the regular playlist url if we match exactly once
|
||||
playlist_url = new URL(match.groups!.streamUrl, this.url).href;
|
||||
playlist_url = new URL(match[2], this.url).href;
|
||||
} else {
|
||||
playlist_url = this.url;
|
||||
}
|
||||
|
||||
// If codec is HEVC and ExoPlayer is supported, use ExoPlayer.
|
||||
if (
|
||||
this._useExoPlayer &&
|
||||
match !== null &&
|
||||
match.groups!.isHevc !== undefined
|
||||
) {
|
||||
if (this._useExoPlayer && match !== null && match[1] !== undefined) {
|
||||
this._renderHLSExoPlayer(playlist_url);
|
||||
} else if (hls.isSupported()) {
|
||||
this._renderHLSPolyfill(videoEl, hls, playlist_url);
|
||||
|
@@ -60,8 +60,9 @@ export class HaIconInput extends LitElement {
|
||||
static get styles() {
|
||||
return css`
|
||||
ha-icon {
|
||||
position: relative;
|
||||
bottom: 4px;
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 0;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
@@ -10,7 +10,6 @@ class HaLabeledSlider extends PolymerElement {
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.title {
|
||||
@@ -30,6 +29,7 @@ class HaLabeledSlider extends PolymerElement {
|
||||
ha-slider {
|
||||
flex-grow: 1;
|
||||
background-image: var(--ha-slider-background);
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@@ -13,7 +13,7 @@ import type { HomeAssistant } from "../types";
|
||||
class HaRelativeTime extends UpdatingElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public datetime?: string;
|
||||
@property({ attribute: false }) public datetime?: string | Date;
|
||||
|
||||
private _interval?: number;
|
||||
|
||||
|
45
src/components/ha-selector/ha-selector-action.ts
Normal file
45
src/components/ha-selector/ha-selector-action.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { ActionSelector } from "../../data/selector";
|
||||
import { Action } from "../../data/script";
|
||||
import "../../panels/config/automation/action/ha-automation-action";
|
||||
|
||||
@customElement("ha-selector-action")
|
||||
export class HaActionSelector extends LitElement {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public selector!: ActionSelector;
|
||||
|
||||
@property() public value?: Action;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
protected render() {
|
||||
return html`<ha-automation-action
|
||||
.actions=${this.value || []}
|
||||
.hass=${this.hass}
|
||||
></ha-automation-action>`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
ha-automation-action {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-action": HaActionSelector;
|
||||
}
|
||||
}
|
@@ -1,7 +1,16 @@
|
||||
import { customElement, html, LitElement, property } from "lit-element";
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { AreaSelector } from "../../data/selector";
|
||||
import "../ha-area-picker";
|
||||
import { ConfigEntry, getConfigEntries } from "../../data/config_entries";
|
||||
import { DeviceRegistryEntry } from "../../data/device_registry";
|
||||
import { EntityRegistryEntry } from "../../data/entity_registry";
|
||||
|
||||
@customElement("ha-selector-area")
|
||||
export class HaAreaSelector extends LitElement {
|
||||
@@ -13,14 +22,77 @@ export class HaAreaSelector extends LitElement {
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@internalProperty() public _configEntries?: ConfigEntry[];
|
||||
|
||||
protected updated(changedProperties) {
|
||||
if (changedProperties.has("selector")) {
|
||||
const oldSelector = changedProperties.get("selector");
|
||||
if (
|
||||
oldSelector !== this.selector &&
|
||||
this.selector.area.device?.integration
|
||||
) {
|
||||
this._loadConfigEntries();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`<ha-area-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.label=${this.label}
|
||||
no-add
|
||||
.deviceFilter=${(device) => this._filterDevices(device)}
|
||||
.entityFilter=${(entity) => this._filterEntities(entity)}
|
||||
.includeDeviceClasses=${this.selector.area.entity?.device_class
|
||||
? [this.selector.area.entity.device_class]
|
||||
: undefined}
|
||||
.includeDomains=${this.selector.area.entity?.domain
|
||||
? [this.selector.area.entity.domain]
|
||||
: undefined}
|
||||
></ha-area-picker>`;
|
||||
}
|
||||
|
||||
private _filterEntities(entity: EntityRegistryEntry): boolean {
|
||||
if (this.selector.area.entity?.integration) {
|
||||
if (entity.platform !== this.selector.area.entity.integration) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _filterDevices(device: DeviceRegistryEntry): boolean {
|
||||
if (
|
||||
this.selector.area.device?.manufacturer &&
|
||||
device.manufacturer !== this.selector.area.device.manufacturer
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
this.selector.area.device?.model &&
|
||||
device.model !== this.selector.area.device.model
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (this.selector.area.device?.integration) {
|
||||
if (
|
||||
this._configEntries &&
|
||||
!this._configEntries.some((entry) =>
|
||||
device.config_entries.includes(entry.entry_id)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async _loadConfigEntries() {
|
||||
this._configEntries = (await getConfigEntries(this.hass)).filter(
|
||||
(entry) => entry.domain === this.selector.area.device?.integration
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -63,7 +63,8 @@ export class HaDeviceSelector extends LitElement {
|
||||
}
|
||||
if (this.selector.device.integration) {
|
||||
if (
|
||||
!this._configEntries?.some((entry) =>
|
||||
this._configEntries &&
|
||||
!this._configEntries.some((entry) =>
|
||||
device.config_entries.includes(entry.entry_id)
|
||||
)
|
||||
) {
|
||||
|
@@ -19,7 +19,7 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
||||
|
||||
@property() public selector!: EntitySelector;
|
||||
|
||||
@internalProperty() private _entities?: Record<string, string>;
|
||||
@internalProperty() private _entityPlaformLookup?: Record<string, string>;
|
||||
|
||||
@property() public value?: any;
|
||||
|
||||
@@ -45,7 +45,7 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
entityLookup[confEnt.entity_id] = confEnt.platform;
|
||||
}
|
||||
this._entities = entityLookup;
|
||||
this._entityPlaformLookup = entityLookup;
|
||||
}),
|
||||
];
|
||||
}
|
||||
@@ -66,8 +66,9 @@ export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
||||
}
|
||||
if (this.selector.entity.integration) {
|
||||
if (
|
||||
!this._entities ||
|
||||
this._entities[entity.entity_id] !== this.selector.entity.integration
|
||||
!this._entityPlaformLookup ||
|
||||
this._entityPlaformLookup[entity.entity_id] !==
|
||||
this.selector.entity.integration
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
153
src/components/ha-selector/ha-selector-target.ts
Normal file
153
src/components/ha-selector/ha-selector-target.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { TargetSelector } from "../../data/selector";
|
||||
import { ConfigEntry, getConfigEntries } from "../../data/config_entries";
|
||||
import { DeviceRegistryEntry } from "../../data/device_registry";
|
||||
import "../ha-target-picker";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@material/mwc-list/mwc-list";
|
||||
import {
|
||||
EntityRegistryEntry,
|
||||
subscribeEntityRegistry,
|
||||
} from "../../data/entity_registry";
|
||||
import { Target } from "../../data/target";
|
||||
import "@material/mwc-tab-bar/mwc-tab-bar";
|
||||
import "@material/mwc-tab/mwc-tab";
|
||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
||||
|
||||
@customElement("ha-selector-target")
|
||||
export class HaTargetSelector extends SubscribeMixin(LitElement) {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public selector!: TargetSelector;
|
||||
|
||||
@property() public value?: Target;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@internalProperty() private _entityPlaformLookup?: Record<string, string>;
|
||||
|
||||
@internalProperty() private _configEntries?: ConfigEntry[];
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
||||
const entityLookup = {};
|
||||
for (const confEnt of entities) {
|
||||
if (!confEnt.platform) {
|
||||
continue;
|
||||
}
|
||||
entityLookup[confEnt.entity_id] = confEnt.platform;
|
||||
}
|
||||
this._entityPlaformLookup = entityLookup;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected updated(changedProperties) {
|
||||
if (changedProperties.has("selector")) {
|
||||
const oldSelector = changedProperties.get("selector");
|
||||
if (
|
||||
oldSelector !== this.selector &&
|
||||
this.selector.target.device?.integration
|
||||
) {
|
||||
this._loadConfigEntries();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
return html`<ha-target-picker
|
||||
.hass=${this.hass}
|
||||
.value=${this.value}
|
||||
.deviceFilter=${(device) => this._filterDevices(device)}
|
||||
.entityRegFilter=${(entity: EntityRegistryEntry) =>
|
||||
this._filterRegEntities(entity)}
|
||||
.entityFilter=${(entity: HassEntity) => this._filterEntities(entity)}
|
||||
.includeDeviceClasses=${this.selector.target.entity?.device_class
|
||||
? [this.selector.target.entity.device_class]
|
||||
: undefined}
|
||||
.includeDomains=${this.selector.target.entity?.domain
|
||||
? [this.selector.target.entity.domain]
|
||||
: undefined}
|
||||
></ha-target-picker>`;
|
||||
}
|
||||
|
||||
private _filterEntities(entity: HassEntity): boolean {
|
||||
if (this.selector.target.entity?.integration) {
|
||||
if (
|
||||
!this._entityPlaformLookup ||
|
||||
this._entityPlaformLookup[entity.entity_id] !==
|
||||
this.selector.target.entity.integration
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _filterRegEntities(entity: EntityRegistryEntry): boolean {
|
||||
if (this.selector.target.entity?.integration) {
|
||||
if (entity.platform !== this.selector.target.entity.integration) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _filterDevices(device: DeviceRegistryEntry): boolean {
|
||||
if (
|
||||
this.selector.target.device?.manufacturer &&
|
||||
device.manufacturer !== this.selector.target.device.manufacturer
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
this.selector.target.device?.model &&
|
||||
device.model !== this.selector.target.device.model
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (this.selector.target.device?.integration) {
|
||||
if (
|
||||
!this._configEntries?.some((entry) =>
|
||||
device.config_entries.includes(entry.entry_id)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async _loadConfigEntries() {
|
||||
this._configEntries = (await getConfigEntries(this.hass)).filter(
|
||||
(entry) => entry.domain === this.selector.target.device?.integration
|
||||
);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
ha-target-picker {
|
||||
margin: 0 -8px;
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-selector-target": HaTargetSelector;
|
||||
}
|
||||
}
|
@@ -5,9 +5,11 @@ import { HomeAssistant } from "../../types";
|
||||
import "./ha-selector-entity";
|
||||
import "./ha-selector-device";
|
||||
import "./ha-selector-area";
|
||||
import "./ha-selector-target";
|
||||
import "./ha-selector-number";
|
||||
import "./ha-selector-boolean";
|
||||
import "./ha-selector-time";
|
||||
import "./ha-selector-action";
|
||||
import { Selector } from "../../data/selector";
|
||||
|
||||
@customElement("ha-selector")
|
||||
|
@@ -18,11 +18,6 @@ export class HaSettingsRow extends LitElement {
|
||||
|
||||
protected render(): SVGTemplateResult {
|
||||
return html`
|
||||
<style>
|
||||
paper-item-body {
|
||||
padding-right: 16px;
|
||||
}
|
||||
</style>
|
||||
<paper-item-body
|
||||
?two-line=${!this.threeLine}
|
||||
?three-line=${this.threeLine}
|
||||
@@ -43,6 +38,14 @@ export class HaSettingsRow extends LitElement {
|
||||
align-self: auto;
|
||||
align-items: center;
|
||||
}
|
||||
paper-item-body {
|
||||
padding: 8px 16px 8px 0;
|
||||
}
|
||||
paper-item-body[two-line] {
|
||||
min-height: calc(
|
||||
var(--paper-item-body-two-line-min-height, 72px) - 16px
|
||||
);
|
||||
}
|
||||
:host([narrow]) {
|
||||
align-items: normal;
|
||||
flex-direction: column;
|
||||
@@ -52,6 +55,9 @@ export class HaSettingsRow extends LitElement {
|
||||
::slotted(ha-switch) {
|
||||
padding: 16px 0;
|
||||
}
|
||||
div[secondary] {
|
||||
white-space: normal;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
605
src/components/ha-target-picker.ts
Normal file
605
src/components/ha-target-picker.ts
Normal file
@@ -0,0 +1,605 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
query,
|
||||
unsafeCSS,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../types";
|
||||
// @ts-ignore
|
||||
import chipStyles from "@material/chips/dist/mdc.chips.min.css";
|
||||
import {
|
||||
mdiSofa,
|
||||
mdiDevices,
|
||||
mdiClose,
|
||||
mdiPlus,
|
||||
mdiUnfoldMoreVertical,
|
||||
} from "@mdi/js";
|
||||
import "./ha-svg-icon";
|
||||
import "./ha-icon";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import {
|
||||
AreaRegistryEntry,
|
||||
subscribeAreaRegistry,
|
||||
} from "../data/area_registry";
|
||||
import {
|
||||
computeDeviceName,
|
||||
DeviceRegistryEntry,
|
||||
subscribeDeviceRegistry,
|
||||
} from "../data/device_registry";
|
||||
import {
|
||||
EntityRegistryEntry,
|
||||
subscribeEntityRegistry,
|
||||
} from "../data/entity_registry";
|
||||
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||
import { computeStateName } from "../common/entity/compute_state_name";
|
||||
import { stateIcon } from "../common/entity/state_icon";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker";
|
||||
import { computeDomain } from "../common/entity/compute_domain";
|
||||
import { Target } from "../data/target";
|
||||
import { ensureArray } from "../common/ensure-array";
|
||||
import "./entity/ha-entity-picker";
|
||||
import "./device/ha-device-picker";
|
||||
import "./ha-area-picker";
|
||||
import type { HaEntityPickerEntityFilterFunc } from "./entity/ha-entity-picker";
|
||||
import "@polymer/paper-tooltip/paper-tooltip";
|
||||
|
||||
@customElement("ha-target-picker")
|
||||
export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
||||
@property() public hass!: HomeAssistant;
|
||||
|
||||
@property() public value?: Target;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
/**
|
||||
* Show only targets with entities from specific domains.
|
||||
* @type {Array}
|
||||
* @attr include-domains
|
||||
*/
|
||||
@property({ type: Array, attribute: "include-domains" })
|
||||
public includeDomains?: string[];
|
||||
|
||||
/**
|
||||
* Show only targets with entities of these device classes.
|
||||
* @type {Array}
|
||||
* @attr include-device-classes
|
||||
*/
|
||||
@property({ type: Array, attribute: "include-device-classes" })
|
||||
public includeDeviceClasses?: string[];
|
||||
|
||||
@property() public deviceFilter?: HaDevicePickerDeviceFilterFunc;
|
||||
|
||||
@property() public entityRegFilter?: (entity: EntityRegistryEntry) => boolean;
|
||||
|
||||
@property() public entityFilter?: HaEntityPickerEntityFilterFunc;
|
||||
|
||||
@internalProperty() private _areas?: { [areaId: string]: AreaRegistryEntry };
|
||||
|
||||
@internalProperty() private _devices?: {
|
||||
[deviceId: string]: DeviceRegistryEntry;
|
||||
};
|
||||
|
||||
@internalProperty() private _entities?: EntityRegistryEntry[];
|
||||
|
||||
@internalProperty() private _addMode?: "area_id" | "entity_id" | "device_id";
|
||||
|
||||
@query("#input") private _inputElement?;
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeAreaRegistry(this.hass.connection!, (areas) => {
|
||||
const areaLookup: { [areaId: string]: AreaRegistryEntry } = {};
|
||||
for (const area of areas) {
|
||||
areaLookup[area.area_id] = area;
|
||||
}
|
||||
this._areas = areaLookup;
|
||||
}),
|
||||
subscribeDeviceRegistry(this.hass.connection!, (devices) => {
|
||||
const deviceLookup: { [deviceId: string]: DeviceRegistryEntry } = {};
|
||||
for (const device of devices) {
|
||||
deviceLookup[device.id] = device;
|
||||
}
|
||||
this._devices = deviceLookup;
|
||||
}),
|
||||
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
||||
this._entities = entities;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._areas || !this._devices || !this._entities) {
|
||||
return html``;
|
||||
}
|
||||
return html`<div class="mdc-chip-set items">
|
||||
${ensureArray(this.value?.area_id)?.map((area_id) => {
|
||||
const area = this._areas![area_id];
|
||||
return this._renderChip(
|
||||
"area_id",
|
||||
area_id,
|
||||
area?.name || area_id,
|
||||
undefined,
|
||||
mdiSofa
|
||||
);
|
||||
})}
|
||||
${ensureArray(this.value?.device_id)?.map((device_id) => {
|
||||
const device = this._devices![device_id];
|
||||
return this._renderChip(
|
||||
"device_id",
|
||||
device_id,
|
||||
device ? computeDeviceName(device, this.hass) : device_id,
|
||||
undefined,
|
||||
mdiDevices
|
||||
);
|
||||
})}
|
||||
${ensureArray(this.value?.entity_id)?.map((entity_id) => {
|
||||
const entity = this.hass.states[entity_id];
|
||||
return this._renderChip(
|
||||
"entity_id",
|
||||
entity_id,
|
||||
entity ? computeStateName(entity) : entity_id,
|
||||
entity ? stateIcon(entity) : undefined
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
${this._renderPicker()}
|
||||
<div class="mdc-chip-set">
|
||||
<div
|
||||
class="mdc-chip area_id add"
|
||||
.type=${"area_id"}
|
||||
@click=${this._showPicker}
|
||||
>
|
||||
<div class="mdc-chip__ripple"></div>
|
||||
<ha-svg-icon
|
||||
class="mdc-chip__icon mdc-chip__icon--leading"
|
||||
.path=${mdiPlus}
|
||||
></ha-svg-icon>
|
||||
<span role="gridcell">
|
||||
<span role="button" tabindex="0" class="mdc-chip__primary-action">
|
||||
<span class="mdc-chip__text"
|
||||
>${this.hass.localize(
|
||||
"ui.components.target-picker.add_area_id"
|
||||
)}</span
|
||||
>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mdc-chip device_id add"
|
||||
.type=${"device_id"}
|
||||
@click=${this._showPicker}
|
||||
>
|
||||
<div class="mdc-chip__ripple"></div>
|
||||
<ha-svg-icon
|
||||
class="mdc-chip__icon mdc-chip__icon--leading"
|
||||
.path=${mdiPlus}
|
||||
></ha-svg-icon>
|
||||
<span role="gridcell">
|
||||
<span role="button" tabindex="0" class="mdc-chip__primary-action">
|
||||
<span class="mdc-chip__text"
|
||||
>${this.hass.localize(
|
||||
"ui.components.target-picker.add_device_id"
|
||||
)}</span
|
||||
>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="mdc-chip entity_id add"
|
||||
.type=${"entity_id"}
|
||||
@click=${this._showPicker}
|
||||
>
|
||||
<div class="mdc-chip__ripple"></div>
|
||||
<ha-svg-icon
|
||||
class="mdc-chip__icon mdc-chip__icon--leading"
|
||||
.path=${mdiPlus}
|
||||
></ha-svg-icon>
|
||||
<span role="gridcell">
|
||||
<span role="button" tabindex="0" class="mdc-chip__primary-action">
|
||||
<span class="mdc-chip__text"
|
||||
>${this.hass.localize(
|
||||
"ui.components.target-picker.add_entity_id"
|
||||
)}</span
|
||||
>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
private async _showPicker(ev) {
|
||||
this._addMode = ev.currentTarget.type;
|
||||
await this.updateComplete;
|
||||
setTimeout(() => {
|
||||
this._inputElement?.open();
|
||||
this._inputElement?.focus();
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private _renderChip(
|
||||
type: string,
|
||||
id: string,
|
||||
name: string,
|
||||
icon?: string,
|
||||
iconPath?: string
|
||||
) {
|
||||
return html`
|
||||
<div
|
||||
class="mdc-chip ${classMap({
|
||||
[type]: true,
|
||||
})}"
|
||||
>
|
||||
${iconPath
|
||||
? html`<ha-svg-icon
|
||||
class="mdc-chip__icon mdc-chip__icon--leading"
|
||||
.path=${iconPath}
|
||||
></ha-svg-icon>`
|
||||
: ""}
|
||||
${icon
|
||||
? html`<ha-icon
|
||||
class="mdc-chip__icon mdc-chip__icon--leading"
|
||||
.icon=${icon}
|
||||
></ha-icon>`
|
||||
: ""}
|
||||
<span role="gridcell">
|
||||
<span role="button" tabindex="0" class="mdc-chip__primary-action">
|
||||
<span class="mdc-chip__text">${name}</span>
|
||||
</span>
|
||||
</span>
|
||||
${type === "entity_id"
|
||||
? ""
|
||||
: html` <span role="gridcell">
|
||||
<mwc-icon-button
|
||||
class="expand-btn mdc-chip__icon mdc-chip__icon--trailing"
|
||||
tabindex="-1"
|
||||
role="button"
|
||||
.label=${"Expand"}
|
||||
.id=${id}
|
||||
.type=${type}
|
||||
@click=${this._handleExpand}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiUnfoldMoreVertical}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<paper-tooltip class="expand" animation-delay="0"
|
||||
>${this.hass.localize(
|
||||
`ui.components.target-picker.expand_${type}`
|
||||
)}</paper-tooltip
|
||||
>
|
||||
</span>`}
|
||||
<span role="gridcell">
|
||||
<mwc-icon-button
|
||||
class="mdc-chip__icon mdc-chip__icon--trailing"
|
||||
tabindex="-1"
|
||||
role="button"
|
||||
.label=${"Remove"}
|
||||
.id=${id}
|
||||
.type=${type}
|
||||
@click=${this._handleRemove}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<paper-tooltip animation-delay="0"
|
||||
>${this.hass.localize(
|
||||
`ui.components.target-picker.remove_${type}`
|
||||
)}</paper-tooltip
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _renderPicker() {
|
||||
switch (this._addMode) {
|
||||
case "area_id":
|
||||
return html`<ha-area-picker
|
||||
.hass=${this.hass}
|
||||
id="input"
|
||||
.type=${"area_id"}
|
||||
.label=${this.hass.localize(
|
||||
"ui.components.target-picker.add_area_id"
|
||||
)}
|
||||
no-add
|
||||
.deviceFilter=${this.deviceFilter}
|
||||
.entityFilter=${this.entityRegFilter}
|
||||
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||
.includeDomains=${this.includeDomains}
|
||||
@value-changed=${this._targetPicked}
|
||||
></ha-area-picker>`;
|
||||
case "device_id":
|
||||
return html`<ha-device-picker
|
||||
.hass=${this.hass}
|
||||
id="input"
|
||||
.type=${"device_id"}
|
||||
.label=${this.hass.localize(
|
||||
"ui.components.target-picker.add_device_id"
|
||||
)}
|
||||
.deviceFilter=${this.deviceFilter}
|
||||
.entityFilter=${this.entityRegFilter}
|
||||
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||
.includeDomains=${this.includeDomains}
|
||||
@value-changed=${this._targetPicked}
|
||||
></ha-device-picker>`;
|
||||
case "entity_id":
|
||||
return html`<ha-entity-picker
|
||||
.hass=${this.hass}
|
||||
id="input"
|
||||
.type=${"entity_id"}
|
||||
.label=${this.hass.localize(
|
||||
"ui.components.target-picker.add_entity_id"
|
||||
)}
|
||||
.entityFilter=${this.entityFilter}
|
||||
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||
.includeDomains=${this.includeDomains}
|
||||
@value-changed=${this._targetPicked}
|
||||
></ha-entity-picker>`;
|
||||
}
|
||||
return html``;
|
||||
}
|
||||
|
||||
private _targetPicked(ev) {
|
||||
ev.stopPropagation();
|
||||
if (!ev.detail.value) {
|
||||
return;
|
||||
}
|
||||
const value = ev.detail.value;
|
||||
const target = ev.currentTarget;
|
||||
target.value = "";
|
||||
this._addMode = undefined;
|
||||
fireEvent(this, "value-changed", {
|
||||
value: this.value
|
||||
? {
|
||||
...this.value,
|
||||
[target.type]: this.value[target.type]
|
||||
? [...ensureArray(this.value[target.type]), value]
|
||||
: value,
|
||||
}
|
||||
: { [target.type]: value },
|
||||
});
|
||||
}
|
||||
|
||||
private _handleExpand(ev) {
|
||||
const target = ev.currentTarget as any;
|
||||
const newDevices: string[] = [];
|
||||
const newEntities: string[] = [];
|
||||
if (target.type === "area_id") {
|
||||
Object.values(this._devices!).forEach((device) => {
|
||||
if (
|
||||
device.area_id === target.id &&
|
||||
!this.value!.device_id?.includes(device.id) &&
|
||||
this._deviceMeetsFilter(device)
|
||||
) {
|
||||
newDevices.push(device.id);
|
||||
}
|
||||
});
|
||||
this._entities!.forEach((entity) => {
|
||||
if (
|
||||
entity.area_id === target.id &&
|
||||
!this.value!.entity_id?.includes(entity.entity_id) &&
|
||||
this._entityRegMeetsFilter(entity)
|
||||
) {
|
||||
newEntities.push(entity.entity_id);
|
||||
}
|
||||
});
|
||||
} else if (target.type === "device_id") {
|
||||
this._entities!.forEach((entity) => {
|
||||
if (
|
||||
entity.device_id === target.id &&
|
||||
!this.value!.entity_id?.includes(entity.entity_id) &&
|
||||
this._entityRegMeetsFilter(entity)
|
||||
) {
|
||||
newEntities.push(entity.entity_id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
let value = this.value;
|
||||
if (newEntities.length) {
|
||||
value = this._addItems(value, "entity_id", newEntities);
|
||||
}
|
||||
if (newDevices.length) {
|
||||
value = this._addItems(value, "device_id", newDevices);
|
||||
}
|
||||
value = this._removeItem(value, target.type, target.id);
|
||||
fireEvent(this, "value-changed", { value });
|
||||
}
|
||||
|
||||
private _handleRemove(ev) {
|
||||
const target = ev.currentTarget as any;
|
||||
fireEvent(this, "value-changed", {
|
||||
value: this._removeItem(this.value, target.type, target.id),
|
||||
});
|
||||
}
|
||||
|
||||
private _addItems(
|
||||
value: this["value"],
|
||||
type: string,
|
||||
ids: string[]
|
||||
): this["value"] {
|
||||
return {
|
||||
...value,
|
||||
[type]: value![type] ? ensureArray(value![type])!.concat(ids) : ids,
|
||||
};
|
||||
}
|
||||
|
||||
private _removeItem(
|
||||
value: this["value"],
|
||||
type: string,
|
||||
id: string
|
||||
): this["value"] {
|
||||
const newVal = ensureArray(value![type])!.filter((val) => val !== id);
|
||||
if (newVal.length) {
|
||||
return {
|
||||
...value,
|
||||
[type]: newVal,
|
||||
};
|
||||
}
|
||||
const val = { ...value }!;
|
||||
delete val[type];
|
||||
if (Object.keys(val).length) {
|
||||
return val;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private _deviceMeetsFilter(device: DeviceRegistryEntry): boolean {
|
||||
const devEntities = this._entities?.filter(
|
||||
(entity) => entity.device_id === device.id
|
||||
);
|
||||
if (this.includeDomains) {
|
||||
if (!devEntities || !devEntities.length) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!devEntities.some((entity) =>
|
||||
this.includeDomains!.includes(computeDomain(entity.entity_id))
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.includeDeviceClasses) {
|
||||
if (!devEntities || !devEntities.length) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!devEntities.some((entity) => {
|
||||
const stateObj = this.hass.states[entity.entity_id];
|
||||
if (!stateObj) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
stateObj.attributes.device_class &&
|
||||
this.includeDeviceClasses!.includes(
|
||||
stateObj.attributes.device_class
|
||||
)
|
||||
);
|
||||
})
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.deviceFilter) {
|
||||
return this.deviceFilter(device);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private _entityRegMeetsFilter(entity: EntityRegistryEntry): boolean {
|
||||
if (
|
||||
this.includeDomains &&
|
||||
!this.includeDomains.includes(computeDomain(entity.entity_id))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (this.includeDeviceClasses) {
|
||||
const stateObj = this.hass.states[entity.entity_id];
|
||||
if (!stateObj) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
!stateObj.attributes.device_class ||
|
||||
!this.includeDeviceClasses!.includes(stateObj.attributes.device_class)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.entityRegFilter) {
|
||||
return this.entityRegFilter(entity);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
${unsafeCSS(chipStyles)}
|
||||
.mdc-chip {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.items {
|
||||
z-index: 2;
|
||||
}
|
||||
.mdc-chip.add {
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
}
|
||||
.mdc-chip:not(.add) {
|
||||
cursor: default;
|
||||
}
|
||||
.mdc-chip mwc-icon-button {
|
||||
--mdc-icon-button-size: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
}
|
||||
.mdc-chip mwc-icon-button ha-svg-icon {
|
||||
border-radius: 50%;
|
||||
background: var(--secondary-text-color);
|
||||
}
|
||||
.mdc-chip__icon.mdc-chip__icon--trailing {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
--mdc-icon-size: 14px;
|
||||
color: var(--card-background-color);
|
||||
}
|
||||
.mdc-chip__icon--leading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
--mdc-icon-size: 20px;
|
||||
border-radius: 50%;
|
||||
padding: 6px;
|
||||
margin-left: -14px !important;
|
||||
}
|
||||
.expand-btn {
|
||||
margin-right: 0;
|
||||
}
|
||||
.mdc-chip.area_id:not(.add) {
|
||||
border: 2px solid #fed6a4;
|
||||
background: var(--card-background-color);
|
||||
}
|
||||
.mdc-chip.area_id:not(.add) .mdc-chip__icon--leading,
|
||||
.mdc-chip.area_id.add {
|
||||
background: #fed6a4;
|
||||
}
|
||||
.mdc-chip.device_id:not(.add) {
|
||||
border: 2px solid #a8e1fb;
|
||||
background: var(--card-background-color);
|
||||
}
|
||||
.mdc-chip.device_id:not(.add) .mdc-chip__icon--leading,
|
||||
.mdc-chip.device_id.add {
|
||||
background: #a8e1fb;
|
||||
}
|
||||
.mdc-chip.entity_id:not(.add) {
|
||||
border: 2px solid #d2e7b9;
|
||||
background: var(--card-background-color);
|
||||
}
|
||||
.mdc-chip.entity_id:not(.add) .mdc-chip__icon--leading,
|
||||
.mdc-chip.entity_id.add {
|
||||
background: #d2e7b9;
|
||||
}
|
||||
.mdc-chip:hover {
|
||||
z-index: 5;
|
||||
}
|
||||
paper-tooltip.expand {
|
||||
min-width: 200px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-target-picker": HaTargetPicker;
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@ import { navigate } from "../common/navigate";
|
||||
import { Context, HomeAssistant } from "../types";
|
||||
import { BlueprintInput } from "./blueprint";
|
||||
import { DeviceCondition, DeviceTrigger } from "./device_automation";
|
||||
import { Action } from "./script";
|
||||
import { Action, MODES } from "./script";
|
||||
|
||||
export interface AutomationEntity extends HassEntityBase {
|
||||
attributes: HassEntityAttributeBase & {
|
||||
@@ -26,7 +26,7 @@ export interface ManualAutomationConfig {
|
||||
trigger: Trigger[];
|
||||
condition?: Condition[];
|
||||
action: Action[];
|
||||
mode?: "single" | "restart" | "queued" | "parallel";
|
||||
mode?: typeof MODES[number];
|
||||
max?: number;
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@ export interface DeviceRegistryEntry {
|
||||
area_id?: string;
|
||||
name_by_user?: string;
|
||||
entry_type: "service" | null;
|
||||
disabled_by: string | null;
|
||||
}
|
||||
|
||||
export interface DeviceEntityLookup {
|
||||
@@ -26,6 +27,7 @@ export interface DeviceEntityLookup {
|
||||
export interface DeviceRegistryEntryMutableParams {
|
||||
area_id?: string | null;
|
||||
name_by_user?: string | null;
|
||||
disabled_by?: string | null;
|
||||
}
|
||||
|
||||
export const fallbackDeviceName = (
|
||||
|
@@ -124,13 +124,17 @@ export const getLogbookMessage = (
|
||||
switch (domain) {
|
||||
case "device_tracker":
|
||||
case "person":
|
||||
return state === "not_home"
|
||||
? hass.localize(`${LOGBOOK_LOCALIZE_PATH}.was_away`)
|
||||
: hass.localize(
|
||||
`${LOGBOOK_LOCALIZE_PATH}.was_at_state`,
|
||||
"state",
|
||||
state
|
||||
);
|
||||
if (state === "not_home") {
|
||||
return hass.localize(`${LOGBOOK_LOCALIZE_PATH}.was_away`);
|
||||
}
|
||||
if (state === "home") {
|
||||
return hass.localize(`${LOGBOOK_LOCALIZE_PATH}.was_at_home`);
|
||||
}
|
||||
return hass.localize(
|
||||
`${LOGBOOK_LOCALIZE_PATH}.was_at_state`,
|
||||
"state",
|
||||
state
|
||||
);
|
||||
|
||||
case "sun":
|
||||
return state === "above_horizon"
|
||||
|
@@ -7,13 +7,13 @@ import { navigate } from "../common/navigate";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { Condition, Trigger } from "./automation";
|
||||
|
||||
export const MODES = ["single", "restart", "queued", "parallel"];
|
||||
export const MODES = ["single", "restart", "queued", "parallel"] as const;
|
||||
export const MODES_MAX = ["queued", "parallel"];
|
||||
|
||||
export interface ScriptEntity extends HassEntityBase {
|
||||
attributes: HassEntityAttributeBase & {
|
||||
last_triggered: string;
|
||||
mode: "single" | "restart" | "queued" | "parallel";
|
||||
mode: typeof MODES[number];
|
||||
current?: number;
|
||||
max?: number;
|
||||
};
|
||||
@@ -23,7 +23,7 @@ export interface ScriptConfig {
|
||||
alias: string;
|
||||
sequence: Action[];
|
||||
icon?: string;
|
||||
mode?: "single" | "restart" | "queued" | "parallel";
|
||||
mode?: typeof MODES[number];
|
||||
max?: number;
|
||||
}
|
||||
|
||||
|
@@ -2,9 +2,11 @@ export type Selector =
|
||||
| EntitySelector
|
||||
| DeviceSelector
|
||||
| AreaSelector
|
||||
| TargetSelector
|
||||
| NumberSelector
|
||||
| BooleanSelector
|
||||
| TimeSelector;
|
||||
| TimeSelector
|
||||
| ActionSelector;
|
||||
|
||||
export interface EntitySelector {
|
||||
entity: {
|
||||
@@ -19,13 +21,41 @@ export interface DeviceSelector {
|
||||
integration?: string;
|
||||
manufacturer?: string;
|
||||
model?: string;
|
||||
entity?: EntitySelector["entity"];
|
||||
entity?: {
|
||||
domain?: EntitySelector["entity"]["domain"];
|
||||
device_class?: EntitySelector["entity"]["device_class"];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface AreaSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
area: {};
|
||||
area: {
|
||||
entity?: {
|
||||
integration?: EntitySelector["entity"]["integration"];
|
||||
domain?: EntitySelector["entity"]["domain"];
|
||||
device_class?: EntitySelector["entity"]["device_class"];
|
||||
};
|
||||
device?: {
|
||||
integration?: DeviceSelector["device"]["integration"];
|
||||
manufacturer?: DeviceSelector["device"]["manufacturer"];
|
||||
model?: DeviceSelector["device"]["model"];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface TargetSelector {
|
||||
target: {
|
||||
entity?: {
|
||||
integration?: EntitySelector["entity"]["integration"];
|
||||
domain?: EntitySelector["entity"]["domain"];
|
||||
device_class?: EntitySelector["entity"]["device_class"];
|
||||
};
|
||||
device?: {
|
||||
integration?: DeviceSelector["device"]["integration"];
|
||||
manufacturer?: DeviceSelector["device"]["manufacturer"];
|
||||
model?: DeviceSelector["device"]["model"];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface NumberSelector {
|
||||
@@ -47,3 +77,8 @@ export interface TimeSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
time: {};
|
||||
}
|
||||
|
||||
export interface ActionSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
action: {};
|
||||
}
|
||||
|
5
src/data/target.ts
Normal file
5
src/data/target.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export interface Target {
|
||||
entity_id?: string[];
|
||||
device_id?: string[];
|
||||
area_id?: string[];
|
||||
}
|
@@ -20,6 +20,7 @@ export interface User {
|
||||
|
||||
export interface UpdateUserParams {
|
||||
name?: User["name"];
|
||||
is_active?: User["is_active"];
|
||||
group_ids?: User["group_ids"];
|
||||
}
|
||||
|
||||
|
@@ -17,17 +17,17 @@ import "../../components/ha-switch";
|
||||
import { PolymerChangedEvent } from "../../polymer-types";
|
||||
import { haStyleDialog } from "../../resources/styles";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { DialogParams } from "./show-dialog-box";
|
||||
import { DialogBoxParams } from "./show-dialog-box";
|
||||
|
||||
@customElement("dialog-box")
|
||||
class DialogBox extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@internalProperty() private _params?: DialogParams;
|
||||
@internalProperty() private _params?: DialogBoxParams;
|
||||
|
||||
@internalProperty() private _value?: string;
|
||||
|
||||
public async showDialog(params: DialogParams): Promise<void> {
|
||||
public async showDialog(params: DialogBoxParams): Promise<void> {
|
||||
this._params = params;
|
||||
if (params.prompt) {
|
||||
this._value = params.defaultValue;
|
||||
@@ -55,8 +55,8 @@ class DialogBox extends LitElement {
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
?scrimClickAction=${this._params.prompt}
|
||||
?escapeKeyAction=${this._params.prompt}
|
||||
?scrimClickAction=${confirmPrompt}
|
||||
?escapeKeyAction=${confirmPrompt}
|
||||
@closed=${this._dialogClosed}
|
||||
defaultAction="ignore"
|
||||
.heading=${this._params.title
|
||||
@@ -140,10 +140,10 @@ class DialogBox extends LitElement {
|
||||
}
|
||||
|
||||
private _dialogClosed(ev) {
|
||||
if (ev.detail.action === "ignore") {
|
||||
if (this._params?.prompt && ev.detail.action === "ignore") {
|
||||
return;
|
||||
}
|
||||
this.closeDialog();
|
||||
this._dismiss();
|
||||
}
|
||||
|
||||
private _close(): void {
|
||||
|
@@ -1,31 +1,31 @@
|
||||
import { TemplateResult } from "lit-html";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
|
||||
interface BaseDialogParams {
|
||||
interface BaseDialogBoxParams {
|
||||
confirmText?: string;
|
||||
text?: string | TemplateResult;
|
||||
title?: string;
|
||||
warning?: boolean;
|
||||
}
|
||||
|
||||
export interface AlertDialogParams extends BaseDialogParams {
|
||||
export interface AlertDialogParams extends BaseDialogBoxParams {
|
||||
confirm?: () => void;
|
||||
}
|
||||
|
||||
export interface ConfirmationDialogParams extends BaseDialogParams {
|
||||
export interface ConfirmationDialogParams extends BaseDialogBoxParams {
|
||||
dismissText?: string;
|
||||
confirm?: () => void;
|
||||
cancel?: () => void;
|
||||
}
|
||||
|
||||
export interface PromptDialogParams extends BaseDialogParams {
|
||||
export interface PromptDialogParams extends BaseDialogBoxParams {
|
||||
inputLabel?: string;
|
||||
inputType?: string;
|
||||
defaultValue?: string;
|
||||
confirm?: (out?: string) => void;
|
||||
}
|
||||
|
||||
export interface DialogParams
|
||||
export interface DialogBoxParams
|
||||
extends ConfirmationDialogParams,
|
||||
PromptDialogParams {
|
||||
confirm?: (out?: string) => void;
|
||||
@@ -37,10 +37,10 @@ export const loadGenericDialog = () => import("./dialog-box");
|
||||
|
||||
const showDialogHelper = (
|
||||
element: HTMLElement,
|
||||
dialogParams: DialogParams,
|
||||
dialogParams: DialogBoxParams,
|
||||
extra?: {
|
||||
confirmation?: DialogParams["confirmation"];
|
||||
prompt?: DialogParams["prompt"];
|
||||
confirmation?: DialogBoxParams["confirmation"];
|
||||
prompt?: DialogBoxParams["prompt"];
|
||||
}
|
||||
) =>
|
||||
new Promise((resolve) => {
|
||||
|
@@ -44,7 +44,7 @@ class MoreInfoSun extends LitElement {
|
||||
>
|
||||
<ha-relative-time
|
||||
.hass=${this.hass}
|
||||
.datetimeObj=${item === "ris" ? risingDate : settingDate}
|
||||
.datetime=${item === "ris" ? risingDate : settingDate}
|
||||
></ha-relative-time>
|
||||
</div>
|
||||
<div class="value">
|
||||
@@ -80,6 +80,7 @@ class MoreInfoSun extends LitElement {
|
||||
}
|
||||
ha-relative-time {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
ha-relative-time::first-letter {
|
||||
text-transform: lowercase;
|
||||
|
@@ -60,6 +60,12 @@ export class HaTabsSubpageDataTable extends LitElement {
|
||||
*/
|
||||
@property({ type: Boolean }) public hasFab = false;
|
||||
|
||||
/**
|
||||
* Add an extra row at the bottom of the data table
|
||||
* @type {TemplateResult}
|
||||
*/
|
||||
@property({ attribute: false }) public appendRow?;
|
||||
|
||||
/**
|
||||
* Field with a unique id per entry in data.
|
||||
* @type {String}
|
||||
@@ -171,6 +177,7 @@ export class HaTabsSubpageDataTable extends LitElement {
|
||||
.noDataText=${this.noDataText}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.clickable=${this.clickable}
|
||||
.appendRow=${this.appendRow}
|
||||
>
|
||||
${!this.narrow
|
||||
? html`
|
||||
|
@@ -17,6 +17,7 @@ import { PolymerChangedEvent } from "../../../polymer-types";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { AreaRegistryDetailDialogParams } from "./show-dialog-area-registry-detail";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
|
||||
class DialogAreaDetail extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@@ -154,6 +155,8 @@ class DialogAreaDetail extends LitElement {
|
||||
} finally {
|
||||
this._submitting = false;
|
||||
}
|
||||
|
||||
navigate(this, "/config/areas/dashboard");
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
|
@@ -39,7 +39,7 @@ export class HaWaitForTriggerAction extends LitElement
|
||||
)}
|
||||
>
|
||||
<ha-switch
|
||||
.checked=${continue_on_timeout}
|
||||
.checked=${continue_on_timeout ?? true}
|
||||
@change=${this._continueChanged}
|
||||
></ha-switch>
|
||||
</ha-formfield>
|
||||
|
@@ -18,13 +18,9 @@ import "@polymer/paper-input/paper-textarea";
|
||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
||||
import "../../../components/entity/ha-entity-toggle";
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "./trigger/ha-automation-trigger";
|
||||
import "./condition/ha-automation-condition";
|
||||
import "./action/ha-automation-action";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import {
|
||||
BlueprintOrError,
|
||||
Blueprints,
|
||||
@@ -63,7 +59,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
|
||||
protected render() {
|
||||
const blueprint = this._blueprint;
|
||||
return html`<ha-config-section .isWide=${this.isWide}>
|
||||
return html`<ha-config-section vertical .isWide=${this.isWide}>
|
||||
${!this.narrow
|
||||
? html` <span slot="header">${this.config.alias}</span> `
|
||||
: ""}
|
||||
@@ -119,7 +115,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
</ha-card>
|
||||
</ha-config-section>
|
||||
|
||||
<ha-config-section .isWide=${this.isWide}>
|
||||
<ha-config-section vertical .isWide=${this.isWide}>
|
||||
<span slot="header"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.blueprint.header"
|
||||
@@ -144,11 +140,6 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
"ui.panel.config.automation.editor.blueprint.no_blueprints"
|
||||
)
|
||||
: html`<ha-circular-progress active></ha-circular-progress>`}
|
||||
<mwc-button @click=${this._navigateBlueprints}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.blueprint.manage_blueprints"
|
||||
)}
|
||||
</mwc-button>
|
||||
</div>
|
||||
|
||||
${this.config.use_blueprint.path
|
||||
@@ -157,41 +148,37 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
There is an error in this Blueprint: ${blueprint.error}
|
||||
</p>`
|
||||
: html`${blueprint?.metadata.description
|
||||
? html`<p>${blueprint.metadata.description}</p>`
|
||||
? html`<p class="card-content pre-line">
|
||||
${blueprint.metadata.description}
|
||||
</p>`
|
||||
: ""}
|
||||
${blueprint?.metadata?.input &&
|
||||
Object.keys(blueprint.metadata.input).length
|
||||
? html`<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.blueprint.inputs"
|
||||
)}
|
||||
</h3>
|
||||
${Object.entries(blueprint.metadata.input).map(
|
||||
([key, value]) =>
|
||||
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}
|
||||
.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}
|
||||
.value=${this.config.use_blueprint.input &&
|
||||
this.config.use_blueprint.input[key]}
|
||||
@value-changed=${this._inputChanged}
|
||||
no-label-float
|
||||
></paper-input>`}
|
||||
</ha-settings-row>`
|
||||
)}`
|
||||
? Object.entries(blueprint.metadata.input).map(
|
||||
([key, value]) =>
|
||||
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}
|
||||
.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}
|
||||
required
|
||||
.value=${this.config.use_blueprint.input &&
|
||||
this.config.use_blueprint.input[key]}
|
||||
@value-changed=${this._inputChanged}
|
||||
no-label-float
|
||||
></paper-input>`}
|
||||
</ha-settings-row>`
|
||||
)
|
||||
: html`<p class="padding">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.blueprint.no_inputs"
|
||||
@@ -237,12 +224,18 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const input = { ...this.config.use_blueprint.input, [key]: value };
|
||||
|
||||
if (value === "" || value === undefined) {
|
||||
delete input[key];
|
||||
}
|
||||
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.config!,
|
||||
use_blueprint: {
|
||||
...this.config.use_blueprint,
|
||||
input: { ...this.config.use_blueprint.input, [key]: value },
|
||||
input,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -267,25 +260,18 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _navigateBlueprints() {
|
||||
navigate(this, "/config/blueprint");
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
ha-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
.padding {
|
||||
padding: 16px;
|
||||
}
|
||||
.pre-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
.blueprint-picker-container {
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
h3 {
|
||||
margin: 16px;
|
||||
@@ -304,10 +290,10 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
||||
border-top: 1px solid var(--divider-color);
|
||||
}
|
||||
:host(:not([narrow])) ha-settings-row paper-input {
|
||||
width: 50%;
|
||||
width: 60%;
|
||||
}
|
||||
:host(:not([narrow])) ha-settings-row ha-selector {
|
||||
width: 50%;
|
||||
width: 60%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -32,6 +32,7 @@ import "../../../components/ha-svg-icon";
|
||||
import "../../../components/ha-yaml-editor";
|
||||
import { showToast } from "../../../util/toast";
|
||||
import type { HaYamlEditor } from "../../../components/ha-yaml-editor";
|
||||
import { copyToClipboard } from "../../../common/util/copy-clipboard";
|
||||
import {
|
||||
AutomationConfig,
|
||||
AutomationEntity,
|
||||
@@ -206,6 +207,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
? html`<blueprint-automation-editor
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.isWide=${this.isWide}
|
||||
.stateObj=${stateObj}
|
||||
.config=${this._config}
|
||||
@value-changed=${this._valueChanged}
|
||||
@@ -213,6 +215,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
: html`<manual-automation-editor
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.isWide=${this.isWide}
|
||||
.stateObj=${stateObj}
|
||||
.config=${this._config}
|
||||
@value-changed=${this._valueChanged}
|
||||
@@ -394,7 +397,7 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
|
||||
private async _copyYaml() {
|
||||
if (this._editor?.yaml) {
|
||||
navigator.clipboard.writeText(this._editor.yaml);
|
||||
copyToClipboard(this._editor.yaml);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,7 @@ import {
|
||||
internalProperty,
|
||||
query,
|
||||
TemplateResult,
|
||||
css,
|
||||
} from "lit-element";
|
||||
import "../../../components/ha-dialog";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
@@ -73,7 +74,9 @@ class DialogImportBlueprint extends LitElement {
|
||||
this._result.blueprint.metadata.domain
|
||||
)}
|
||||
<br />
|
||||
${this._result.blueprint.metadata.description}
|
||||
<p class="pre-line">
|
||||
${this._result.blueprint.metadata.description}
|
||||
</p>
|
||||
${this._result.validation_errors
|
||||
? html`
|
||||
<p class="error">
|
||||
@@ -104,7 +107,16 @@ class DialogImportBlueprint extends LitElement {
|
||||
<pre>${this._result.raw_data}</pre>
|
||||
</ha-expansion-panel>`
|
||||
: html`${this.hass.localize(
|
||||
"ui.panel.config.blueprint.add.import_introduction"
|
||||
"ui.panel.config.blueprint.add.import_introduction_link",
|
||||
"community_link",
|
||||
html`<a
|
||||
href="https://www.home-assistant.io/get-blueprints"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.blueprint.add.community_forums"
|
||||
)}</a
|
||||
>`
|
||||
)}<paper-input
|
||||
id="input"
|
||||
.label=${this.hass.localize(
|
||||
@@ -199,8 +211,15 @@ class DialogImportBlueprint extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return haStyleDialog;
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyleDialog,
|
||||
css`
|
||||
.pre-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import "../../../components/ha-fab";
|
||||
import "@material/mwc-icon-button";
|
||||
import { mdiPlus, mdiHelpCircle, mdiDelete, mdiRobot } from "@mdi/js";
|
||||
import { mdiHelpCircle, mdiDelete, mdiRobot, mdiDownload } from "@mdi/js";
|
||||
import "@polymer/paper-tooltip/paper-tooltip";
|
||||
import {
|
||||
CSSResult,
|
||||
@@ -112,7 +112,6 @@ class HaBlueprintOverview extends LitElement {
|
||||
create: {
|
||||
title: "",
|
||||
type: narrow ? "icon-button" : undefined,
|
||||
width: narrow ? undefined : "180px",
|
||||
template: (_, blueprint: any) =>
|
||||
blueprint.error
|
||||
? ""
|
||||
@@ -126,8 +125,9 @@ class HaBlueprintOverview extends LitElement {
|
||||
"ui.panel.config.blueprint.overview.use_blueprint"
|
||||
)}
|
||||
@click=${(ev) => this._createNew(ev)}
|
||||
><ha-svg-icon .path=${mdiRobot}></ha-svg-icon
|
||||
></mwc-icon-button>`
|
||||
>
|
||||
<ha-svg-icon .path=${mdiRobot}></ha-svg-icon>
|
||||
</mwc-icon-button>`
|
||||
: html`<mwc-button
|
||||
.blueprint=${blueprint}
|
||||
@click=${(ev) => this._createNew(ev)}
|
||||
@@ -170,6 +170,23 @@ class HaBlueprintOverview extends LitElement {
|
||||
"ui.panel.config.blueprint.overview.no_blueprints"
|
||||
)}
|
||||
hasFab
|
||||
.appendRow=${html` <div
|
||||
class="mdc-data-table__cell"
|
||||
style="width: 100%; text-align: center;"
|
||||
role="cell"
|
||||
>
|
||||
<a
|
||||
href="https://www.home-assistant.io/get-blueprints"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
<mwc-button
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.blueprint.overview.discover_more"
|
||||
)}</mwc-button
|
||||
>
|
||||
</a>
|
||||
</div>`}
|
||||
>
|
||||
<mwc-icon-button slot="toolbar-icon" @click=${this._showHelp}>
|
||||
<ha-svg-icon .path=${mdiHelpCircle}></ha-svg-icon>
|
||||
@@ -182,7 +199,7 @@ class HaBlueprintOverview extends LitElement {
|
||||
extended
|
||||
@click=${this._addBlueprint}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
<ha-svg-icon slot="icon" .path=${mdiDownload}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
</hass-tabs-subpage-data-table>
|
||||
`;
|
||||
@@ -195,7 +212,10 @@ class HaBlueprintOverview extends LitElement {
|
||||
${this.hass.localize("ui.panel.config.blueprint.overview.introduction")}
|
||||
<p>
|
||||
<a
|
||||
href="${documentationUrl(this.hass, "/docs/blueprint/editor/")}"
|
||||
href="${documentationUrl(
|
||||
this.hass,
|
||||
"/docs/automation/using_blueprints/"
|
||||
)}"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
|
@@ -92,7 +92,7 @@ class HaConfigCustomize extends LocalizeMixin(PolymerElement) {
|
||||
}
|
||||
|
||||
_computeTabs() {
|
||||
return configSections.general;
|
||||
return configSections.advanced;
|
||||
}
|
||||
|
||||
computeEntities(hass) {
|
||||
|
@@ -8,7 +8,6 @@ import {
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
internalProperty,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
@@ -31,7 +30,7 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
|
||||
@property() public entities!: EntityRegistryStateEntry[];
|
||||
|
||||
@internalProperty() private _showDisabled = false;
|
||||
@property() public showDisabled = false;
|
||||
|
||||
private _entityRows: Array<LovelaceRow | HuiErrorCard> = [];
|
||||
|
||||
@@ -68,7 +67,7 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
})}
|
||||
</div>
|
||||
${disabledEntities.length
|
||||
? !this._showDisabled
|
||||
? !this.showDisabled
|
||||
? html`
|
||||
<button
|
||||
class="show-more"
|
||||
@@ -119,7 +118,7 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
}
|
||||
|
||||
private _toggleShowDisabled() {
|
||||
this._showDisabled = !this._showDisabled;
|
||||
this.showDisabled = !this.showDisabled;
|
||||
}
|
||||
|
||||
private _renderEntity(entry: EntityRegistryStateEntry): TemplateResult {
|
||||
@@ -227,3 +226,9 @@ export class HaDeviceEntitiesCard extends LitElement {
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-device-entities-card": HaDeviceEntitiesCard;
|
||||
}
|
||||
}
|
||||
|
@@ -19,10 +19,11 @@ import {
|
||||
|
||||
import { DeviceRegistryDetailDialogParams } from "./show-dialog-device-registry-detail";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
import type { HaSwitch } from "../../../../components/ha-switch";
|
||||
import { PolymerChangedEvent } from "../../../../polymer-types";
|
||||
import { computeDeviceName } from "../../../../data/device_registry";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { haStyleDialog } from "../../../../resources/styles";
|
||||
import { haStyle, haStyleDialog } from "../../../../resources/styles";
|
||||
|
||||
@customElement("dialog-device-registry-detail")
|
||||
class DialogDeviceRegistryDetail extends LitElement {
|
||||
@@ -36,6 +37,8 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
|
||||
@internalProperty() private _areaId?: string;
|
||||
|
||||
@internalProperty() private _disabledBy!: string | null;
|
||||
|
||||
@internalProperty() private _submitting?: boolean;
|
||||
|
||||
public async showDialog(
|
||||
@@ -45,6 +48,7 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
this._error = undefined;
|
||||
this._nameByUser = this._params.device.name_by_user || "";
|
||||
this._areaId = this._params.device.area_id;
|
||||
this._disabledBy = this._params.device.disabled_by;
|
||||
await this.updateComplete;
|
||||
}
|
||||
|
||||
@@ -80,6 +84,32 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
.value=${this._areaId}
|
||||
@value-changed=${this._areaPicked}
|
||||
></ha-area-picker>
|
||||
<div class="row">
|
||||
<ha-switch
|
||||
.checked=${!this._disabledBy}
|
||||
@change=${this._disabledByChanged}
|
||||
>
|
||||
</ha-switch>
|
||||
<div>
|
||||
<div>
|
||||
${this.hass.localize("ui.panel.config.devices.enabled_label")}
|
||||
</div>
|
||||
<div class="secondary">
|
||||
${this._disabledBy && this._disabledBy !== "user"
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.devices.enabled_cause",
|
||||
"cause",
|
||||
this.hass.localize(
|
||||
`config_entry.disabled_by.${this._disabledBy}`
|
||||
)
|
||||
)
|
||||
: ""}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.devices.enabled_description"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<mwc-button
|
||||
@@ -109,12 +139,17 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
this._areaId = event.detail.value;
|
||||
}
|
||||
|
||||
private _disabledByChanged(ev: Event): void {
|
||||
this._disabledBy = (ev.target as HaSwitch).checked ? null : "user";
|
||||
}
|
||||
|
||||
private async _updateEntry(): Promise<void> {
|
||||
this._submitting = true;
|
||||
try {
|
||||
await this._params!.updateEntry({
|
||||
name_by_user: this._nameByUser.trim() || null,
|
||||
area_id: this._areaId || null,
|
||||
disabled_by: this._disabledBy || null,
|
||||
});
|
||||
this._params = undefined;
|
||||
} catch (err) {
|
||||
@@ -128,6 +163,7 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
haStyleDialog,
|
||||
css`
|
||||
.form {
|
||||
@@ -139,6 +175,15 @@ class DialogDeviceRegistryDetail extends LitElement {
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
}
|
||||
ha-switch {
|
||||
margin-right: 16px;
|
||||
}
|
||||
.row {
|
||||
margin-top: 8px;
|
||||
color: var(--primary-text-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@@ -46,6 +46,7 @@ import "./device-detail/ha-device-entities-card";
|
||||
import "./device-detail/ha-device-info-card";
|
||||
import { showDeviceAutomationDialog } from "./device-detail/show-dialog-device-automation";
|
||||
import { brandsUrl } from "../../../util/brands-url";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
|
||||
export interface EntityRegistryStateEntry extends EntityRegistryEntry {
|
||||
stateName?: string | null;
|
||||
@@ -246,6 +247,28 @@ export class HaConfigDevicePage extends LitElement {
|
||||
.devices=${this.devices}
|
||||
.device=${device}
|
||||
>
|
||||
${
|
||||
device.disabled_by
|
||||
? html`
|
||||
<div>
|
||||
<p class="warning">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.devices.enabled_cause",
|
||||
"cause",
|
||||
this.hass.localize(
|
||||
`ui.panel.config.devices.disabled_by.${device.disabled_by}`
|
||||
)
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-actions" slot="actions">
|
||||
<mwc-button unelevated @click=${this._enableDevice}>
|
||||
${this.hass.localize("ui.common.enable")}
|
||||
</mwc-button>
|
||||
</div>
|
||||
`
|
||||
: html``
|
||||
}
|
||||
${this._renderIntegrationInfo(device, integrations)}
|
||||
</ha-device-info-card>
|
||||
|
||||
@@ -255,6 +278,7 @@ export class HaConfigDevicePage extends LitElement {
|
||||
<ha-device-entities-card
|
||||
.hass=${this.hass}
|
||||
.entities=${entities}
|
||||
.showDisabled=${device.disabled_by !== null}
|
||||
>
|
||||
</ha-device-entities-card>
|
||||
`
|
||||
@@ -272,9 +296,14 @@ export class HaConfigDevicePage extends LitElement {
|
||||
)}
|
||||
<ha-icon-button
|
||||
@click=${this._showAutomationDialog}
|
||||
title=${this.hass.localize(
|
||||
"ui.panel.config.devices.automation.create"
|
||||
)}
|
||||
.disabled=${device.disabled_by}
|
||||
title=${device.disabled_by
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.devices.automation.create_disabled"
|
||||
)
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.devices.automation.create"
|
||||
)}
|
||||
icon="hass:plus-circle"
|
||||
></ha-icon-button>
|
||||
</h1>
|
||||
@@ -342,9 +371,16 @@ export class HaConfigDevicePage extends LitElement {
|
||||
|
||||
<ha-icon-button
|
||||
@click=${this._createScene}
|
||||
title=${this.hass.localize(
|
||||
"ui.panel.config.devices.scene.create"
|
||||
)}
|
||||
.disabled=${device.disabled_by}
|
||||
title=${
|
||||
device.disabled_by
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.devices.scene.create_disabled"
|
||||
)
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.devices.scene.create"
|
||||
)
|
||||
}
|
||||
icon="hass:plus-circle"
|
||||
></ha-icon-button>
|
||||
</h1>
|
||||
@@ -415,9 +451,14 @@ export class HaConfigDevicePage extends LitElement {
|
||||
)}
|
||||
<ha-icon-button
|
||||
@click=${this._showScriptDialog}
|
||||
title=${this.hass.localize(
|
||||
"ui.panel.config.devices.script.create"
|
||||
)}
|
||||
.disabled=${device.disabled_by}
|
||||
title=${device.disabled_by
|
||||
? this.hass.localize(
|
||||
"ui.panel.config.devices.script.create_disabled"
|
||||
)
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.devices.script.create"
|
||||
)}
|
||||
icon="hass:plus-circle"
|
||||
></ha-icon-button>
|
||||
</h1>
|
||||
@@ -632,128 +673,137 @@ export class HaConfigDevicePage extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return css`
|
||||
.container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
private async _enableDevice(): Promise<void> {
|
||||
await updateDeviceRegistryEntry(this.hass, this.deviceId, {
|
||||
disabled_by: null,
|
||||
});
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: auto;
|
||||
max-width: 1000px;
|
||||
margin-top: 32px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.card-header ha-icon-button {
|
||||
margin-right: -8px;
|
||||
color: var(--primary-color);
|
||||
height: auto;
|
||||
}
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.device-info {
|
||||
padding: 16px;
|
||||
}
|
||||
.card-header ha-icon-button {
|
||||
margin-right: -8px;
|
||||
color: var(--primary-color);
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.show-more {
|
||||
}
|
||||
.device-info {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-family: var(--paper-font-headline_-_font-family);
|
||||
-webkit-font-smoothing: var(
|
||||
--paper-font-headline_-_-webkit-font-smoothing
|
||||
);
|
||||
font-size: var(--paper-font-headline_-_font-size);
|
||||
font-weight: var(--paper-font-headline_-_font-weight);
|
||||
letter-spacing: var(--paper-font-headline_-_letter-spacing);
|
||||
line-height: var(--paper-font-headline_-_line-height);
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
.show-more {
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-family: var(--paper-font-headline_-_font-family);
|
||||
-webkit-font-smoothing: var(
|
||||
--paper-font-headline_-_-webkit-font-smoothing
|
||||
);
|
||||
font-size: var(--paper-font-headline_-_font-size);
|
||||
font-weight: var(--paper-font-headline_-_font-weight);
|
||||
letter-spacing: var(--paper-font-headline_-_letter-spacing);
|
||||
line-height: var(--paper-font-headline_-_line-height);
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
|
||||
.column,
|
||||
.fullwidth {
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.column {
|
||||
width: 33%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
align-self: center;
|
||||
}
|
||||
.column,
|
||||
.fullwidth {
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.column {
|
||||
width: 33%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.fullwidth {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.header-right img {
|
||||
height: 30px;
|
||||
}
|
||||
.header-right {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
}
|
||||
.header-right img {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.header-right:first-child {
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.header-right {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-right > *:not(:first-child) {
|
||||
margin-left: 16px;
|
||||
}
|
||||
.header-right:first-child {
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.battery {
|
||||
align-self: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
.header-right > *:not(:first-child) {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.column > *:not(:first-child) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.battery {
|
||||
align-self: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
:host([narrow]) .column {
|
||||
width: 100%;
|
||||
}
|
||||
.column > *:not(:first-child) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
:host([narrow]) .container {
|
||||
margin-top: 0;
|
||||
}
|
||||
:host([narrow]) .column {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
font-size: var(--paper-font-body1_-_font-size);
|
||||
}
|
||||
:host([narrow]) .container {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
paper-item.no-link {
|
||||
cursor: default;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
font-size: var(--paper-font-body1_-_font-size);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-item.no-link {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
ha-card {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
ha-card a {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
`;
|
||||
ha-card {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
ha-card a {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,9 @@
|
||||
import { mdiPlus } from "@mdi/js";
|
||||
import { mdiPlus, mdiFilterVariant, mdiCancel } from "@mdi/js";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import "@polymer/paper-tooltip/paper-tooltip";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
@@ -7,7 +11,9 @@ import {
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item";
|
||||
import { HASSDomEvent } from "../../../common/dom/fire_event";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { LocalizeFunc } from "../../../common/translations/localize";
|
||||
@@ -18,6 +24,7 @@ import {
|
||||
RowClickedEvent,
|
||||
} from "../../../components/data-table/ha-data-table";
|
||||
import "../../../components/entity/ha-battery-icon";
|
||||
import "../../../components/ha-button-menu";
|
||||
import { AreaRegistryEntry } from "../../../data/area_registry";
|
||||
import { ConfigEntry } from "../../../data/config_entries";
|
||||
import {
|
||||
@@ -34,6 +41,7 @@ import { domainToName } from "../../../data/integration";
|
||||
import "../../../layouts/hass-tabs-subpage-data-table";
|
||||
import { HomeAssistant, Route } from "../../../types";
|
||||
import { configSections } from "../ha-panel-config";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
|
||||
interface DeviceRowData extends DeviceRegistryEntry {
|
||||
device?: DeviceRowData;
|
||||
@@ -64,6 +72,12 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
window.location.search
|
||||
);
|
||||
|
||||
@internalProperty() private _showDisabled = false;
|
||||
|
||||
@internalProperty() private _filter = "";
|
||||
|
||||
@internalProperty() private _numHiddenDevices = 0;
|
||||
|
||||
private _activeFilters = memoizeOne(
|
||||
(
|
||||
entries: ConfigEntry[],
|
||||
@@ -74,6 +88,10 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
filters.forEach((value, key) => {
|
||||
switch (key) {
|
||||
case "config_entry": {
|
||||
// If we are requested to show the devices for a given config entry,
|
||||
// also show the disabled ones by default.
|
||||
this._showDisabled = true;
|
||||
|
||||
const configEntry = entries.find(
|
||||
(entry) => entry.entry_id === value
|
||||
);
|
||||
@@ -105,6 +123,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
entities: EntityRegistryEntry[],
|
||||
areas: AreaRegistryEntry[],
|
||||
filters: URLSearchParams,
|
||||
showDisabled: boolean,
|
||||
localize: LocalizeFunc
|
||||
) => {
|
||||
// Some older installations might have devices pointing at invalid entryIDs
|
||||
@@ -117,6 +136,9 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
deviceLookup[device.id] = device;
|
||||
}
|
||||
|
||||
// If nothing gets filtered, this is our correct count of devices
|
||||
let startLength = outputDevices.length;
|
||||
|
||||
const deviceEntityLookup: DeviceEntityLookup = {};
|
||||
for (const entity of entities) {
|
||||
if (!entity.device_id) {
|
||||
@@ -145,6 +167,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
outputDevices = outputDevices.filter((device) =>
|
||||
device.config_entries.includes(value)
|
||||
);
|
||||
startLength = outputDevices.length;
|
||||
const configEntry = entries.find((entry) => entry.entry_id === value);
|
||||
if (configEntry) {
|
||||
filterDomains.push(configEntry.domain);
|
||||
@@ -152,6 +175,10 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
}
|
||||
});
|
||||
|
||||
if (!showDisabled) {
|
||||
outputDevices = outputDevices.filter((device) => !device.disabled_by);
|
||||
}
|
||||
|
||||
outputDevices = outputDevices.map((device) => {
|
||||
return {
|
||||
...device,
|
||||
@@ -162,9 +189,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
),
|
||||
model: device.model || "<unknown>",
|
||||
manufacturer: device.manufacturer || "<unknown>",
|
||||
area: device.area_id
|
||||
? areaLookup[device.area_id].name
|
||||
: this.hass.localize("ui.panel.config.devices.data_table.no_area"),
|
||||
area: device.area_id ? areaLookup[device.area_id].name : undefined,
|
||||
integration: device.config_entries.length
|
||||
? device.config_entries
|
||||
.filter((entId) => entId in entryLookup)
|
||||
@@ -182,16 +207,19 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
};
|
||||
});
|
||||
|
||||
this._numHiddenDevices = startLength - outputDevices.length;
|
||||
return { devicesOutput: outputDevices, filteredDomains: filterDomains };
|
||||
}
|
||||
);
|
||||
|
||||
private _columns = memoizeOne(
|
||||
(narrow: boolean): DataTableColumnContainer => {
|
||||
(narrow: boolean, showDisabled: boolean): DataTableColumnContainer => {
|
||||
const columns: DataTableColumnContainer = narrow
|
||||
? {
|
||||
name: {
|
||||
title: "Device",
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.devices.data_table.device"
|
||||
),
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
@@ -277,6 +305,24 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
: html` - `;
|
||||
},
|
||||
};
|
||||
if (showDisabled) {
|
||||
columns.disabled_by = {
|
||||
title: "",
|
||||
type: "icon",
|
||||
template: (disabled_by) =>
|
||||
disabled_by
|
||||
? html`<div
|
||||
tabindex="0"
|
||||
style="display:inline-block; position: relative;"
|
||||
>
|
||||
<ha-svg-icon .path=${mdiCancel}></ha-svg-icon>
|
||||
<paper-tooltip animation-delay="0" position="left">
|
||||
${this.hass.localize("ui.panel.config.devices.disabled")}
|
||||
</paper-tooltip>
|
||||
</div>`
|
||||
: "",
|
||||
};
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
);
|
||||
@@ -298,9 +344,119 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
this.entities,
|
||||
this.areas,
|
||||
this._searchParms,
|
||||
this._showDisabled,
|
||||
this.hass.localize
|
||||
);
|
||||
const includeZHAFab = filteredDomains.includes("zha");
|
||||
const activeFilters = this._activeFilters(
|
||||
this.entries,
|
||||
this._searchParms,
|
||||
this.hass.localize
|
||||
);
|
||||
|
||||
const headerToolbar = html`
|
||||
<search-input
|
||||
no-label-float
|
||||
no-underline
|
||||
@value-changed=${this._handleSearchChange}
|
||||
.filter=${this._filter}
|
||||
.label=${this.hass.localize("ui.panel.config.devices.picker.search")}
|
||||
></search-input
|
||||
>${activeFilters
|
||||
? html`<div class="active-filters">
|
||||
${this.narrow
|
||||
? html` <div>
|
||||
<ha-icon icon="hass:filter-variant"></ha-icon>
|
||||
<paper-tooltip animation-delay="0" position="left">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.filtering.filtering_by"
|
||||
)}
|
||||
${activeFilters.join(", ")}
|
||||
${this._numHiddenDevices
|
||||
? "(" +
|
||||
this.hass.localize(
|
||||
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||
"number",
|
||||
this._numHiddenDevices
|
||||
) +
|
||||
")"
|
||||
: ""}
|
||||
</paper-tooltip>
|
||||
</div>`
|
||||
: `${this.hass.localize(
|
||||
"ui.panel.config.filtering.filtering_by"
|
||||
)} ${activeFilters.join(", ")}
|
||||
${
|
||||
this._numHiddenDevices
|
||||
? "(" +
|
||||
this.hass.localize(
|
||||
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||
"number",
|
||||
this._numHiddenDevices
|
||||
) +
|
||||
")"
|
||||
: ""
|
||||
}
|
||||
`}
|
||||
<mwc-button @click=${this._clearFilter}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.filtering.clear"
|
||||
)}</mwc-button
|
||||
>
|
||||
</div>`
|
||||
: ""}
|
||||
${this._numHiddenDevices && !activeFilters
|
||||
? html`<div class="active-filters">
|
||||
${this.narrow
|
||||
? html` <div>
|
||||
<ha-icon icon="hass:filter-variant"></ha-icon>
|
||||
<paper-tooltip animation-delay="0" position="left">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||
"number",
|
||||
this._numHiddenDevices
|
||||
)}
|
||||
</paper-tooltip>
|
||||
</div>`
|
||||
: `${this.hass.localize(
|
||||
"ui.panel.config.devices.picker.filter.hidden_devices",
|
||||
"number",
|
||||
this._numHiddenDevices
|
||||
)}`}
|
||||
<mwc-button @click=${this._showAll}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.devices.picker.filter.show_all"
|
||||
)}</mwc-button
|
||||
>
|
||||
</div>`
|
||||
: ""}
|
||||
<ha-button-menu corner="BOTTOM_START" multi>
|
||||
<mwc-icon-button
|
||||
slot="trigger"
|
||||
.label=${this.hass!.localize(
|
||||
"ui.panel.config.devices.picker.filter.filter"
|
||||
)}
|
||||
.title=${this.hass!.localize(
|
||||
"ui.panel.config.devices.picker.filter.filter"
|
||||
)}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiFilterVariant}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-list-item
|
||||
@request-selected="${this._showDisabledChanged}"
|
||||
graphic="control"
|
||||
.selected=${this._showDisabled}
|
||||
>
|
||||
<ha-checkbox
|
||||
slot="graphic"
|
||||
.checked=${this._showDisabled}
|
||||
></ha-checkbox>
|
||||
${this.hass!.localize(
|
||||
"ui.panel.config.devices.picker.filter.show_disabled"
|
||||
)}
|
||||
</mwc-list-item>
|
||||
</ha-button-menu>
|
||||
`;
|
||||
|
||||
return html`
|
||||
<hass-tabs-subpage-data-table
|
||||
@@ -311,13 +467,9 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
: "/config"}
|
||||
.tabs=${configSections.integrations}
|
||||
.route=${this.route}
|
||||
.columns=${this._columns(this.narrow)}
|
||||
.columns=${this._columns(this.narrow, this._showDisabled)}
|
||||
.data=${devicesOutput}
|
||||
.activeFilters=${this._activeFilters(
|
||||
this.entries,
|
||||
this._searchParms,
|
||||
this.hass.localize
|
||||
)}
|
||||
.filter=${this._filter}
|
||||
@row-click=${this._handleRowClicked}
|
||||
clickable
|
||||
.hasFab=${includeZHAFab}
|
||||
@@ -333,6 +485,15 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
</ha-fab>
|
||||
</a>`
|
||||
: html``}
|
||||
<div
|
||||
class=${classMap({
|
||||
"search-toolbar": this.narrow,
|
||||
"table-header": !this.narrow,
|
||||
})}
|
||||
slot="header"
|
||||
>
|
||||
${headerToolbar}
|
||||
</div>
|
||||
</hass-tabs-subpage-data-table>
|
||||
`;
|
||||
}
|
||||
@@ -363,6 +524,136 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
const deviceId = ev.detail.id;
|
||||
navigate(this, `/config/devices/device/${deviceId}`);
|
||||
}
|
||||
|
||||
private _showDisabledChanged(ev: CustomEvent<RequestSelectedDetail>) {
|
||||
if (ev.detail.source !== "property") {
|
||||
return;
|
||||
}
|
||||
this._showDisabled = ev.detail.selected;
|
||||
}
|
||||
|
||||
private _handleSearchChange(ev: CustomEvent) {
|
||||
this._filter = ev.detail.value;
|
||||
}
|
||||
|
||||
private _clearFilter() {
|
||||
navigate(this, window.location.pathname, true);
|
||||
}
|
||||
|
||||
private _showAll() {
|
||||
this._showDisabled = true;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
hass-loading-screen {
|
||||
--app-header-background-color: var(--sidebar-background-color);
|
||||
--app-header-text-color: var(--sidebar-text-color);
|
||||
}
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
font-family: var(--paper-font-headline_-_font-family);
|
||||
-webkit-font-smoothing: var(
|
||||
--paper-font-headline_-_-webkit-font-smoothing
|
||||
);
|
||||
font-size: var(--paper-font-headline_-_font-size);
|
||||
font-weight: var(--paper-font-headline_-_font-weight);
|
||||
letter-spacing: var(--paper-font-headline_-_letter-spacing);
|
||||
line-height: var(--paper-font-headline_-_line-height);
|
||||
opacity: var(--dark-primary-opacity);
|
||||
}
|
||||
p {
|
||||
font-family: var(--paper-font-subhead_-_font-family);
|
||||
-webkit-font-smoothing: var(
|
||||
--paper-font-subhead_-_-webkit-font-smoothing
|
||||
);
|
||||
font-weight: var(--paper-font-subhead_-_font-weight);
|
||||
line-height: var(--paper-font-subhead_-_line-height);
|
||||
}
|
||||
ha-data-table {
|
||||
width: 100%;
|
||||
--data-table-border-width: 0;
|
||||
}
|
||||
:host(:not([narrow])) ha-data-table {
|
||||
height: calc(100vh - 1px - var(--header-height));
|
||||
display: block;
|
||||
}
|
||||
ha-button-menu {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12);
|
||||
}
|
||||
search-input {
|
||||
margin-left: 16px;
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
.search-toolbar search-input {
|
||||
margin-left: 8px;
|
||||
top: 1px;
|
||||
}
|
||||
.search-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.search-toolbar ha-button-menu {
|
||||
position: static;
|
||||
}
|
||||
.selected-txt {
|
||||
font-weight: bold;
|
||||
padding-left: 16px;
|
||||
}
|
||||
.table-header .selected-txt {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.search-toolbar .selected-txt {
|
||||
font-size: 16px;
|
||||
}
|
||||
.header-btns > mwc-button,
|
||||
.header-btns > ha-icon-button {
|
||||
margin: 8px;
|
||||
}
|
||||
.active-filters {
|
||||
color: var(--primary-text-color);
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2px 2px 2px 8px;
|
||||
margin-left: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.active-filters ha-icon {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.active-filters mwc-button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
.active-filters::before {
|
||||
background-color: var(--primary-color);
|
||||
opacity: 0.12;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
content: "";
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@@ -111,10 +111,19 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
return html`
|
||||
${!stateObj
|
||||
? html`
|
||||
<div class="container">
|
||||
<div class="container warning">
|
||||
${this.hass!.localize(
|
||||
"ui.dialogs.entity_registry.editor.unavailable"
|
||||
)}
|
||||
${this._device?.disabled_by
|
||||
? html`<br />${this.hass!.localize(
|
||||
"ui.dialogs.entity_registry.editor.device_disabled"
|
||||
)}<br /><mwc-button @click=${this._openDeviceSettings}>
|
||||
${this.hass!.localize(
|
||||
"ui.dialogs.entity_registry.editor.open_device_settings"
|
||||
)}
|
||||
</mwc-button>`
|
||||
: ""}
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
@@ -161,6 +170,7 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
|
||||
<div class="row">
|
||||
<ha-switch
|
||||
.checked=${!this._disabledBy}
|
||||
.disabled=${this._device?.disabled_by}
|
||||
@change=${this._disabledByChanged}
|
||||
>
|
||||
</ha-switch>
|
||||
|
@@ -189,9 +189,11 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
? (name, entity: any) =>
|
||||
html`
|
||||
${name}<br />
|
||||
${entity.entity_id} |
|
||||
${this.hass.localize(`component.${entity.platform}.title`) ||
|
||||
entity.platform}
|
||||
<div class="secondary">
|
||||
${entity.entity_id} |
|
||||
${this.hass.localize(`component.${entity.platform}.title`) ||
|
||||
entity.platform}
|
||||
</div>
|
||||
`
|
||||
: undefined,
|
||||
},
|
||||
|
@@ -5,6 +5,8 @@ import { classMap } from "lit-html/directives/class-map";
|
||||
export class HaConfigSection extends LitElement {
|
||||
@property() public isWide = false;
|
||||
|
||||
@property({ type: Boolean }) public vertical = false;
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div
|
||||
@@ -16,8 +18,8 @@ export class HaConfigSection extends LitElement {
|
||||
<div
|
||||
class="together layout ${classMap({
|
||||
narrow: !this.isWide,
|
||||
vertical: !this.isWide,
|
||||
horizontal: this.isWide,
|
||||
vertical: this.vertical || !this.isWide,
|
||||
horizontal: !this.vertical && this.isWide,
|
||||
})}"
|
||||
>
|
||||
<div class="intro"><slot name="introduction"></slot></div>
|
||||
|
@@ -148,7 +148,7 @@ export class HaConfigHelpers extends LitElement {
|
||||
.narrow=${this.narrow}
|
||||
back-path="/config"
|
||||
.route=${this.route}
|
||||
.tabs=${configSections.automation}
|
||||
.tabs=${configSections.helpers}
|
||||
.columns=${this._columns(this.narrow, this.hass.language)}
|
||||
.data=${this._getItems(this._stateItems)}
|
||||
@row-click=${this._openEditDialog}
|
||||
|
@@ -68,6 +68,8 @@ class DialogPersonDetail extends LitElement {
|
||||
|
||||
@internalProperty() private _submitting = false;
|
||||
|
||||
@internalProperty() private _personExists = false;
|
||||
|
||||
private _deviceTrackersAvailable = memoizeOne((hass) => {
|
||||
return Object.keys(hass.states).some(
|
||||
(entityId) =>
|
||||
@@ -79,6 +81,7 @@ class DialogPersonDetail extends LitElement {
|
||||
this._params = params;
|
||||
this._error = undefined;
|
||||
if (this._params.entry) {
|
||||
this._personExists = true;
|
||||
this._name = this._params.entry.name || "";
|
||||
this._userId = this._params.entry.user_id || undefined;
|
||||
this._deviceTrackers = this._params.entry.device_trackers || [];
|
||||
@@ -88,6 +91,7 @@ class DialogPersonDetail extends LitElement {
|
||||
: undefined;
|
||||
this._isAdmin = this._user?.group_ids.includes(SYSTEM_GROUP_ID_ADMIN);
|
||||
} else {
|
||||
this._personExists = false;
|
||||
this._name = "";
|
||||
this._userId = undefined;
|
||||
this._user = undefined;
|
||||
@@ -398,6 +402,7 @@ class DialogPersonDetail extends LitElement {
|
||||
await this._params!.updateEntry(values);
|
||||
} else {
|
||||
await this._params!.createEntry(values);
|
||||
this._personExists = true;
|
||||
}
|
||||
this._params = undefined;
|
||||
} catch (err) {
|
||||
@@ -422,6 +427,14 @@ class DialogPersonDetail extends LitElement {
|
||||
}
|
||||
|
||||
private _close(): void {
|
||||
// If we do not have a person ID yet (= person creation dialog was just cancelled), but
|
||||
// we already created a user ID for it, delete it now to not have it "free floating".
|
||||
if (!this._personExists && this._userId) {
|
||||
deleteUser(this.hass, this._userId);
|
||||
this._params?.refreshUsers();
|
||||
this._userId = undefined;
|
||||
}
|
||||
|
||||
this._params = undefined;
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@ import "../../../components/ha-icon-input";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import "../../../components/ha-yaml-editor";
|
||||
import type { HaYamlEditor } from "../../../components/ha-yaml-editor";
|
||||
import { copyToClipboard } from "../../../common/util/copy-clipboard";
|
||||
import {
|
||||
Action,
|
||||
deleteScript,
|
||||
@@ -545,7 +546,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
|
||||
private async _copyYaml() {
|
||||
if (this._editor?.yaml) {
|
||||
navigator.clipboard.writeText(this._editor.yaml);
|
||||
copyToClipboard(this._editor.yaml);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -84,7 +84,7 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
|
||||
${tag.last_scanned_datetime
|
||||
? html`<ha-relative-time
|
||||
.hass=${this.hass}
|
||||
.datetimeObj=${tag.last_scanned_datetime}
|
||||
.datetime=${tag.last_scanned_datetime}
|
||||
></ha-relative-time>`
|
||||
: this.hass.localize("ui.panel.config.tags.never_scanned")}
|
||||
</div>`
|
||||
@@ -103,7 +103,7 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
|
||||
${last_scanned_datetime
|
||||
? html`<ha-relative-time
|
||||
.hass=${this.hass}
|
||||
.datetimeObj=${last_scanned_datetime}
|
||||
.datetime=${last_scanned_datetime}
|
||||
></ha-relative-time>`
|
||||
: this.hass.localize("ui.panel.config.tags.never_scanned")}
|
||||
`,
|
||||
|
@@ -241,7 +241,7 @@ export class DialogAddUser extends LitElement {
|
||||
user = userResponse.user;
|
||||
} catch (err) {
|
||||
this._loading = false;
|
||||
this._error = err.code;
|
||||
this._error = err.message;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ export class DialogAddUser extends LitElement {
|
||||
} catch (err) {
|
||||
await deleteUser(this.hass, user.id);
|
||||
this._loading = false;
|
||||
this._error = err.code;
|
||||
this._error = err.message;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,7 @@ import {
|
||||
} from "lit-element";
|
||||
import { computeRTLDirection } from "../../../common/util/compute_rtl";
|
||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||
import "../../../components/ha-help-tooltip";
|
||||
import "../../../components/ha-formfield";
|
||||
import "../../../components/ha-switch";
|
||||
import { adminChangePassword } from "../../../data/auth";
|
||||
@@ -37,6 +38,8 @@ class DialogUserDetail extends LitElement {
|
||||
|
||||
@internalProperty() private _isAdmin?: boolean;
|
||||
|
||||
@internalProperty() private _isActive?: boolean;
|
||||
|
||||
@internalProperty() private _error?: string;
|
||||
|
||||
@internalProperty() private _params?: UserDetailDialogParams;
|
||||
@@ -48,6 +51,7 @@ class DialogUserDetail extends LitElement {
|
||||
this._error = undefined;
|
||||
this._name = params.entry.name || "";
|
||||
this._isAdmin = params.entry.group_ids.includes(SYSTEM_GROUP_ID_ADMIN);
|
||||
this._isActive = params.entry.is_active;
|
||||
await this.updateComplete;
|
||||
}
|
||||
|
||||
@@ -91,15 +95,6 @@ class DialogUserDetail extends LitElement {
|
||||
</span>
|
||||
`
|
||||
: ""}
|
||||
${user.is_active
|
||||
? html`
|
||||
<span class="state"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.users.editor.active"
|
||||
)}</span
|
||||
>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
<div class="form">
|
||||
<paper-input
|
||||
@@ -110,17 +105,21 @@ class DialogUserDetail extends LitElement {
|
||||
"ui.panel.config.users.editor.name"
|
||||
)}"
|
||||
></paper-input>
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize("ui.panel.config.users.editor.admin")}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.disabled=${user.system_generated || user.is_owner}
|
||||
.checked=${this._isAdmin}
|
||||
@change=${this._adminChanged}
|
||||
<div class="row">
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.users.editor.admin"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
</ha-switch>
|
||||
</ha-formfield>
|
||||
<ha-switch
|
||||
.disabled=${user.system_generated || user.is_owner}
|
||||
.checked=${this._isAdmin}
|
||||
@change=${this._adminChanged}
|
||||
>
|
||||
</ha-switch>
|
||||
</ha-formfield>
|
||||
</div>
|
||||
${!this._isAdmin
|
||||
? html`
|
||||
<br />
|
||||
@@ -129,6 +128,27 @@ class DialogUserDetail extends LitElement {
|
||||
)}
|
||||
`
|
||||
: ""}
|
||||
<div class="row">
|
||||
<ha-formfield
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.users.editor.active"
|
||||
)}
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
>
|
||||
<ha-switch
|
||||
.disabled=${user.system_generated || user.is_owner}
|
||||
.checked=${this._isActive}
|
||||
@change=${this._activeChanged}
|
||||
>
|
||||
</ha-switch>
|
||||
</ha-formfield>
|
||||
<ha-help-tooltip
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.users.editor.active_tooltip"
|
||||
)}
|
||||
>
|
||||
</ha-help-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -192,11 +212,16 @@ class DialogUserDetail extends LitElement {
|
||||
this._isAdmin = ev.target.checked;
|
||||
}
|
||||
|
||||
private async _activeChanged(ev): Promise<void> {
|
||||
this._isActive = ev.target.checked;
|
||||
}
|
||||
|
||||
private async _updateEntry() {
|
||||
this._submitting = true;
|
||||
try {
|
||||
await this._params!.updateEntry({
|
||||
name: this._name.trim(),
|
||||
is_active: this._isActive,
|
||||
group_ids: [
|
||||
this._isAdmin ? SYSTEM_GROUP_ID_ADMIN : SYSTEM_GROUP_ID_USER,
|
||||
],
|
||||
@@ -293,8 +318,13 @@ class DialogUserDetail extends LitElement {
|
||||
.state:not(:first-child) {
|
||||
margin-left: 8px;
|
||||
}
|
||||
ha-switch {
|
||||
margin-top: 8px;
|
||||
.row {
|
||||
display: flex;
|
||||
padding: 8px 0;
|
||||
}
|
||||
ha-help-tooltip {
|
||||
margin-left: 4px;
|
||||
position: relative;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -46,10 +46,17 @@ export class HaConfigUsers extends LitElement {
|
||||
width: "25%",
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
template: (name) => html`
|
||||
${name ||
|
||||
this.hass!.localize("ui.panel.config.users.editor.unnamed_user")}
|
||||
`,
|
||||
template: (name, user: any) =>
|
||||
narrow
|
||||
? html` ${name}<br />
|
||||
<div class="secondary">
|
||||
${user.username} |
|
||||
${this.hass.localize(`groups.${user.group_ids[0]}`)}
|
||||
</div>`
|
||||
: html` ${name ||
|
||||
this.hass!.localize(
|
||||
"ui.panel.config.users.editor.unnamed_user"
|
||||
)}`,
|
||||
},
|
||||
username: {
|
||||
title: this.hass.localize(
|
||||
@@ -59,6 +66,7 @@ export class HaConfigUsers extends LitElement {
|
||||
filterable: true,
|
||||
width: "20%",
|
||||
direction: "asc",
|
||||
hidden: narrow,
|
||||
template: (username) => html`
|
||||
${username ||
|
||||
this.hass!.localize("ui.panel.config.users.editor.unnamed_user")}
|
||||
@@ -71,13 +79,24 @@ export class HaConfigUsers extends LitElement {
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "20%",
|
||||
direction: "asc",
|
||||
hidden: narrow,
|
||||
template: (groupIds) => html`
|
||||
${this.hass.localize(`groups.${groupIds[0]}`)}
|
||||
`,
|
||||
},
|
||||
};
|
||||
if (!narrow) {
|
||||
columns.system_generated = {
|
||||
is_active: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.users.picker.headers.is_active"
|
||||
),
|
||||
type: "icon",
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
width: "80px",
|
||||
template: (is_active) =>
|
||||
is_active ? html`<ha-icon icon="hass:check"> </ha-icon>` : "",
|
||||
},
|
||||
system_generated: {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.users.picker.headers.system"
|
||||
),
|
||||
@@ -87,8 +106,9 @@ export class HaConfigUsers extends LitElement {
|
||||
width: "160px",
|
||||
template: (generated) =>
|
||||
generated ? html`<ha-icon icon="hass:check"> </ha-icon>` : "",
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return columns;
|
||||
}
|
||||
);
|
||||
|
@@ -84,9 +84,6 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
public setConfig(config: ButtonCardConfig): void {
|
||||
if (!config.entity) {
|
||||
throw new Error("Entity must be specified");
|
||||
}
|
||||
if (config.entity && !isValidEntityId(config.entity)) {
|
||||
throw new Error("Invalid entity");
|
||||
}
|
||||
|
@@ -109,7 +109,7 @@ class HuiEntitiesCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
public setConfig(config: EntitiesCardConfig): void {
|
||||
if (!config || !config.entities.length) {
|
||||
if (!config.entities || !Array.isArray(config.entities)) {
|
||||
throw new Error("Entities must be specified");
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,14 @@ import { customElement } from "lit-element";
|
||||
import { HuiButtonCard } from "./hui-button-card";
|
||||
|
||||
@customElement("hui-entity-button-card")
|
||||
class HuiEntityButtonCard extends HuiButtonCard {}
|
||||
class HuiEntityButtonCard extends HuiButtonCard {
|
||||
public setConfig(config): void {
|
||||
if (!config.entity) {
|
||||
throw new Error("Entity must be specified");
|
||||
}
|
||||
super.setConfig(config);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
|
@@ -16,7 +16,6 @@ import "../../../components/state-history-charts";
|
||||
import { CacheConfig, getRecentWithCache } from "../../../data/cached-history";
|
||||
import { HistoryResult } from "../../../data/history";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { findEntities } from "../common/find-entites";
|
||||
import { hasConfigOrEntitiesChanged } from "../common/has-changed";
|
||||
import { processConfigEntities } from "../common/process-config-entities";
|
||||
import { EntityConfig } from "../entity-rows/types";
|
||||
@@ -30,22 +29,9 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
||||
return document.createElement("hui-history-graph-card-editor");
|
||||
}
|
||||
|
||||
public static getStubConfig(
|
||||
hass: HomeAssistant,
|
||||
entities: string[],
|
||||
entitiesFallback: string[]
|
||||
): HistoryGraphCardConfig {
|
||||
const includeDomains = ["sensor"];
|
||||
const maxEntities = 1;
|
||||
const foundEntities = findEntities(
|
||||
hass,
|
||||
maxEntities,
|
||||
entities,
|
||||
entitiesFallback,
|
||||
includeDomains
|
||||
);
|
||||
|
||||
return { type: "history-graph", entities: foundEntities };
|
||||
public static getStubConfig(): HistoryGraphCardConfig {
|
||||
// Hard coded to sun.sun to prevent high server load when it would pick an entity with a lot of state changes
|
||||
return { type: "history-graph", entities: ["sun.sun"] };
|
||||
}
|
||||
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
@@ -71,12 +57,12 @@ export class HuiHistoryGraphCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
public setConfig(config: HistoryGraphCardConfig): void {
|
||||
if (!config.entities.length) {
|
||||
throw new Error("Entities must be specified");
|
||||
if (!config.entities || !Array.isArray(config.entities)) {
|
||||
throw new Error("Entities need to be an array");
|
||||
}
|
||||
|
||||
if (config.entities && !Array.isArray(config.entities)) {
|
||||
throw new Error("Entities need to be an array");
|
||||
if (!config.entities.length) {
|
||||
throw new Error("You must include at least one entity");
|
||||
}
|
||||
|
||||
this._config = config;
|
||||
|
@@ -29,7 +29,7 @@ class HuiHorizontalStackCard extends HuiStackCard {
|
||||
}
|
||||
#root > * {
|
||||
flex: 1 1 0;
|
||||
margin: 0 4px;
|
||||
margin: var(--horizontal-stack-card-margin, var(--stack-card-margin, 0 4px));
|
||||
min-width: 0;
|
||||
}
|
||||
#root > *:first-child {
|
||||
|
@@ -246,78 +246,73 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
|
||||
${!isUnavailable &&
|
||||
(mediaDescription || stateObj.attributes.media_title || showControls)
|
||||
? html`
|
||||
<div
|
||||
class="title-controls"
|
||||
style=${styleMap({
|
||||
paddingRight: isOffState
|
||||
? "0"
|
||||
: `${this._cardHeight - 40}px`,
|
||||
})}
|
||||
>
|
||||
${!mediaDescription && !stateObj.attributes.media_title
|
||||
? ""
|
||||
: html`
|
||||
<div class="media-info">
|
||||
<hui-marquee
|
||||
.text=${stateObj.attributes.media_title ||
|
||||
mediaDescription}
|
||||
.active=${this._marqueeActive}
|
||||
@mouseover=${this._marqueeMouseOver}
|
||||
@mouseleave=${this._marqueeMouseLeave}
|
||||
></hui-marquee>
|
||||
${!stateObj.attributes.media_title
|
||||
? ""
|
||||
: mediaDescription}
|
||||
</div>
|
||||
`}
|
||||
${!showControls
|
||||
? ""
|
||||
: html`
|
||||
<div class="controls">
|
||||
${controls!.map(
|
||||
(control) => html`
|
||||
<ha-icon-button
|
||||
.title=${this.hass.localize(
|
||||
`ui.card.media_player.${control.action}`
|
||||
)}
|
||||
.icon=${control.icon}
|
||||
action=${control.action}
|
||||
@click=${this._handleClick}
|
||||
></ha-icon-button>
|
||||
`
|
||||
)}
|
||||
${supportsFeature(stateObj, SUPPORT_BROWSE_MEDIA)
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
class="browse-media"
|
||||
<div>
|
||||
<div class="title-controls">
|
||||
${!mediaDescription && !stateObj.attributes.media_title
|
||||
? ""
|
||||
: html`
|
||||
<div class="media-info">
|
||||
<hui-marquee
|
||||
.text=${stateObj.attributes.media_title ||
|
||||
mediaDescription}
|
||||
.active=${this._marqueeActive}
|
||||
@mouseover=${this._marqueeMouseOver}
|
||||
@mouseleave=${this._marqueeMouseLeave}
|
||||
></hui-marquee>
|
||||
${!stateObj.attributes.media_title
|
||||
? ""
|
||||
: mediaDescription}
|
||||
</div>
|
||||
`}
|
||||
${!showControls
|
||||
? ""
|
||||
: html`
|
||||
<div class="controls">
|
||||
${controls!.map(
|
||||
(control) => html`
|
||||
<ha-icon-button
|
||||
.title=${this.hass.localize(
|
||||
"ui.card.media_player.browse_media"
|
||||
`ui.card.media_player.${control.action}`
|
||||
)}
|
||||
@click=${this._handleBrowseMedia}
|
||||
><ha-svg-icon
|
||||
.path=${mdiPlayBoxMultiple}
|
||||
></ha-svg-icon
|
||||
></mwc-icon-button>
|
||||
.icon=${control.icon}
|
||||
action=${control.action}
|
||||
@click=${this._handleClick}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
)}
|
||||
${supportsFeature(stateObj, SUPPORT_BROWSE_MEDIA)
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
class="browse-media"
|
||||
.title=${this.hass.localize(
|
||||
"ui.card.media_player.browse_media"
|
||||
)}
|
||||
@click=${this._handleBrowseMedia}
|
||||
><ha-svg-icon
|
||||
.path=${mdiPlayBoxMultiple}
|
||||
></ha-svg-icon
|
||||
></mwc-icon-button>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
`}
|
||||
</div>
|
||||
${!this._showProgressBar
|
||||
? ""
|
||||
: html`
|
||||
<paper-progress
|
||||
.max=${stateObj.attributes.media_duration}
|
||||
style=${styleMap({
|
||||
"--paper-progress-active-color":
|
||||
this._foregroundColor || "var(--accent-color)",
|
||||
cursor: supportsFeature(stateObj, SUPPORT_SEEK)
|
||||
? "pointer"
|
||||
: "initial",
|
||||
})}
|
||||
@click=${this._handleSeek}
|
||||
></paper-progress>
|
||||
`}
|
||||
</div>
|
||||
${!this._showProgressBar
|
||||
? ""
|
||||
: html`
|
||||
<paper-progress
|
||||
.max=${stateObj.attributes.media_duration}
|
||||
style=${styleMap({
|
||||
"--paper-progress-active-color":
|
||||
this._foregroundColor || "var(--accent-color)",
|
||||
cursor: supportsFeature(stateObj, SUPPORT_SEEK)
|
||||
? "pointer"
|
||||
: "initial",
|
||||
})}
|
||||
@click=${this._handleSeek}
|
||||
></paper-progress>
|
||||
`}
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
@@ -635,6 +630,11 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
|
||||
.player {
|
||||
position: relative;
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
color: var(--text-primary-color);
|
||||
transition-property: color, padding;
|
||||
transition-duration: 0.4s;
|
||||
@@ -671,7 +671,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
|
||||
|
||||
mwc-icon-button.browse-media {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
right: 4px;
|
||||
--mdc-icon-size: 24px;
|
||||
}
|
||||
|
||||
@@ -693,7 +693,7 @@ export class HuiMediaControlCard extends LitElement implements LovelaceCard {
|
||||
.more-info {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 0px;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
.media-info {
|
||||
|
@@ -29,7 +29,7 @@ class HuiVerticalStackCard extends HuiStackCard {
|
||||
height: 100%;
|
||||
}
|
||||
#root > * {
|
||||
margin: 4px 0 4px 0;
|
||||
margin: var(--vertical-stack-card-margin, var(--stack-card-margin, 4px 0));
|
||||
}
|
||||
#root > *:first-child {
|
||||
margin-top: 0;
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import "@material/mwc-icon-button";
|
||||
import "../../../components/ha-button-menu";
|
||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
import { mdiArrowDown, mdiArrowUp, mdiDotsVertical } from "@mdi/js";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -9,21 +10,20 @@ import {
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
queryAssignedNodes,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||
import { swapCard, moveCard, addCard, deleteCard } from "../editor/config-util";
|
||||
import { confDeleteCard } from "../editor/delete-card";
|
||||
import { Lovelace, LovelaceCard } from "../types";
|
||||
import { computeCardSize } from "../common/compute-card-size";
|
||||
import { mdiDotsVertical, mdiArrowDown, mdiArrowUp } from "@mdi/js";
|
||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||
import { showSelectViewDialog } from "../editor/select-view/show-select-view-dialog";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import "../../../components/ha-button-menu";
|
||||
import { saveConfig } from "../../../data/lovelace";
|
||||
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { showSaveSuccessToast } from "../../../util/toast-saved-success";
|
||||
import { computeCardSize } from "../common/compute-card-size";
|
||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||
import { addCard, deleteCard, moveCard, swapCard } from "../editor/config-util";
|
||||
import { showSelectViewDialog } from "../editor/select-view/show-select-view-dialog";
|
||||
import { Lovelace, LovelaceCard } from "../types";
|
||||
|
||||
@customElement("hui-card-options")
|
||||
export class HuiCardOptions extends LitElement {
|
||||
@@ -168,11 +168,7 @@ export class HuiCardOptions extends LitElement {
|
||||
}
|
||||
|
||||
private _editCard(): void {
|
||||
showEditCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: this.path!,
|
||||
});
|
||||
fireEvent(this, "ll-edit-card", { path: this.path! });
|
||||
}
|
||||
|
||||
private _cardUp(): void {
|
||||
@@ -229,7 +225,7 @@ export class HuiCardOptions extends LitElement {
|
||||
}
|
||||
|
||||
private _deleteCard(): void {
|
||||
confDeleteCard(this, this.hass!, this.lovelace!, this.path!);
|
||||
fireEvent(this, "ll-delete-card", { path: this.path! });
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -72,7 +72,7 @@ class HuiMarquee extends LitElement {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
height: 1em;
|
||||
height: 1.2em;
|
||||
contain: strict;
|
||||
}
|
||||
|
||||
|
@@ -59,6 +59,9 @@ export class HuiThemeSelectEditor extends LitElement {
|
||||
paper-dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
paper-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -353,11 +353,9 @@ export class HuiCardPicker extends LitElement {
|
||||
max-width: 500px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: var(--ha-card-border-radius, 4px);
|
||||
background: var(--primary-background-color, #fafafa);
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -375,7 +373,6 @@ export class HuiCardPicker extends LitElement {
|
||||
--ha-card-background,
|
||||
var(--card-background-color, white)
|
||||
);
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
@@ -408,6 +405,10 @@ export class HuiCardPicker extends LitElement {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
box-sizing: border-box;
|
||||
border: var(--ha-card-border-width, 1px) solid
|
||||
var(--ha-card-border-color, var(--divider-color));
|
||||
border-radius: var(--ha-card-border-radius, 4px);
|
||||
}
|
||||
|
||||
.manual {
|
||||
|
@@ -450,6 +450,10 @@ export class HuiDialogEditCard extends LitElement
|
||||
}
|
||||
.element-preview {
|
||||
position: relative;
|
||||
height: max-content;
|
||||
background: var(--primary-background-color);
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.element-preview ha-circular-progress {
|
||||
top: 50%;
|
||||
|
@@ -8,7 +8,7 @@ export interface CreateCardDialogParams {
|
||||
entities?: string[]; // We can pass entity id's that will be added to the config when a card is picked
|
||||
}
|
||||
|
||||
const importCreateCardDialog = () => import("./hui-dialog-create-card");
|
||||
export const importCreateCardDialog = () => import("./hui-dialog-create-card");
|
||||
|
||||
export const showCreateCardDialog = (
|
||||
element: HTMLElement,
|
||||
|
@@ -6,7 +6,7 @@ export interface DeleteCardDialogParams {
|
||||
cardConfig?: LovelaceCardConfig;
|
||||
}
|
||||
|
||||
const importDeleteCardDialog = () => import("./hui-dialog-delete-card");
|
||||
export const importDeleteCardDialog = () => import("./hui-dialog-delete-card");
|
||||
|
||||
export const showDeleteCardDialog = (
|
||||
element: HTMLElement,
|
||||
|
@@ -8,7 +8,7 @@ export interface EditCardDialogParams {
|
||||
cardConfig?: LovelaceCardConfig;
|
||||
}
|
||||
|
||||
const importEditCardDialog = () => import("./hui-dialog-edit-card");
|
||||
export const importEditCardDialog = () => import("./hui-dialog-edit-card");
|
||||
|
||||
export const showEditCardDialog = (
|
||||
element: HTMLElement,
|
||||
|
@@ -115,7 +115,7 @@ export class HuiButtonCardEditor extends LitElement
|
||||
.label="${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.card.generic.entity"
|
||||
)} (${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.card.config.required"
|
||||
"ui.panel.lovelace.editor.card.config.optional"
|
||||
)})"
|
||||
.hass=${this.hass}
|
||||
.value=${this._entity}
|
||||
|
@@ -173,8 +173,8 @@ class LovelaceFullConfigEditor extends LitElement {
|
||||
text: this.hass.localize(
|
||||
"ui.panel.lovelace.editor.raw_editor.confirm_unsaved_changes"
|
||||
),
|
||||
dismissText: this.hass!.localize("ui.common.leave"),
|
||||
confirmText: this.hass!.localize("ui.common.stay"),
|
||||
dismissText: this.hass!.localize("ui.common.stay"),
|
||||
confirmText: this.hass!.localize("ui.common.leave"),
|
||||
}))
|
||||
) {
|
||||
return;
|
||||
|
@@ -793,10 +793,6 @@ class HUIRoot extends LitElement {
|
||||
|
||||
ha-app-layout {
|
||||
min-height: 100%;
|
||||
background: var(
|
||||
--lovelace-background,
|
||||
var(--primary-background-color)
|
||||
);
|
||||
}
|
||||
ha-tabs {
|
||||
width: 100%;
|
||||
@@ -884,6 +880,12 @@ class HUIRoot extends LitElement {
|
||||
.menu-link {
|
||||
text-decoration: none;
|
||||
}
|
||||
hui-view {
|
||||
background: var(
|
||||
--lovelace-background,
|
||||
var(--primary-background-color)
|
||||
);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@@ -1,3 +1,10 @@
|
||||
// hui-view dependencies for when in edit mode.
|
||||
import "../../../components/ha-fab";
|
||||
import "../components/hui-card-options";
|
||||
import { importCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
||||
import { importDeleteCardDialog } from "../editor/card-editor/show-delete-card-dialog";
|
||||
import { importEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||
|
||||
importCreateCardDialog();
|
||||
importDeleteCardDialog();
|
||||
importEditCardDialog();
|
||||
|
@@ -10,6 +10,7 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import { nextRender } from "../../../common/util/render-status";
|
||||
import "../../../components/entity/ha-state-label-badge";
|
||||
@@ -21,7 +22,6 @@ import type {
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { HuiErrorCard } from "../cards/hui-error-card";
|
||||
import { computeCardSize } from "../common/compute-card-size";
|
||||
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
||||
import type { Lovelace, LovelaceBadge, LovelaceCard } from "../types";
|
||||
|
||||
let editCodeLoaded = false;
|
||||
@@ -148,11 +148,7 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
||||
}
|
||||
|
||||
private _addCard(): void {
|
||||
showCreateCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: [this.index!],
|
||||
});
|
||||
fireEvent(this, "ll-create-card");
|
||||
}
|
||||
|
||||
private async _createColumns() {
|
||||
@@ -293,7 +289,7 @@ export class MasonryView extends LitElement implements LovelaceViewElement {
|
||||
|
||||
.column > * {
|
||||
display: block;
|
||||
margin: 4px 4px 8px;
|
||||
margin: var(--masonry-view-card-margin, 4px 4px 8px);
|
||||
}
|
||||
|
||||
ha-fab {
|
||||
|
@@ -20,11 +20,23 @@ import { processConfigEntities } from "../common/process-config-entities";
|
||||
import { createBadgeElement } from "../create-element/create-badge-element";
|
||||
import { createCardElement } from "../create-element/create-card-element";
|
||||
import { createViewElement } from "../create-element/create-view-element";
|
||||
import { showCreateCardDialog } from "../editor/card-editor/show-create-card-dialog";
|
||||
import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog";
|
||||
import { confDeleteCard } from "../editor/delete-card";
|
||||
import type { Lovelace, LovelaceBadge, LovelaceCard } from "../types";
|
||||
|
||||
const DEFAULT_VIEW_LAYOUT = "masonry";
|
||||
const PANEL_VIEW_LAYOUT = "panel";
|
||||
|
||||
declare global {
|
||||
// for fire event
|
||||
interface HASSDomEvents {
|
||||
"ll-create-card": undefined;
|
||||
"ll-edit-card": { path: [number] | [number, number] };
|
||||
"ll-delete-card": { path: [number] | [number, number] };
|
||||
}
|
||||
}
|
||||
|
||||
@customElement("hui-view")
|
||||
export class HUIView extends UpdatingElement {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
@@ -106,6 +118,23 @@ export class HUIView extends UpdatingElement {
|
||||
|
||||
if (configChanged && !this._layoutElement) {
|
||||
this._layoutElement = createViewElement(viewConfig!);
|
||||
this._layoutElement.addEventListener("ll-create-card", () => {
|
||||
showCreateCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: [this.index!],
|
||||
});
|
||||
});
|
||||
this._layoutElement.addEventListener("ll-edit-card", (ev) => {
|
||||
showEditCardDialog(this, {
|
||||
lovelaceConfig: this.lovelace!.config,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
path: ev.detail.path,
|
||||
});
|
||||
});
|
||||
this._layoutElement.addEventListener("ll-delete-card", (ev) => {
|
||||
confDeleteCard(this, this.hass!, this.lovelace!, ev.detail.path);
|
||||
});
|
||||
}
|
||||
|
||||
if (configChanged) {
|
||||
|
@@ -1,154 +0,0 @@
|
||||
import "@material/mwc-button";
|
||||
import "@polymer/paper-dialog/paper-dialog";
|
||||
import "../../components/ha-circular-progress";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import "../../components/ha-card";
|
||||
import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
import "../../styles/polymer-ha-style";
|
||||
|
||||
/*
|
||||
* @appliesMixin LocalizeMixin
|
||||
*/
|
||||
class HaChangePasswordCard extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style include="ha-style">
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
.status {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
.error,
|
||||
.status {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
}
|
||||
.currentPassword {
|
||||
margin-top: -4px;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<ha-card
|
||||
header="[[localize('ui.panel.profile.change_password.header')]]"
|
||||
>
|
||||
<div class="card-content">
|
||||
<template is="dom-if" if="[[_errorMsg]]">
|
||||
<div class="error">[[_errorMsg]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[_statusMsg]]">
|
||||
<div class="status">[[_statusMsg]]</div>
|
||||
</template>
|
||||
<paper-input
|
||||
class="currentPassword"
|
||||
label="[[localize('ui.panel.profile.change_password.current_password')]]"
|
||||
type="password"
|
||||
value="{{_currentPassword}}"
|
||||
required
|
||||
auto-validate
|
||||
error-message="[[localize('ui.panel.profile.change_password.error_required')]]"
|
||||
></paper-input>
|
||||
<template is="dom-if" if="[[_currentPassword]]">
|
||||
<paper-input
|
||||
label="[[localize('ui.panel.profile.change_password.new_password')]]"
|
||||
type="password"
|
||||
value="{{_password1}}"
|
||||
required
|
||||
auto-validate
|
||||
error-message="[[localize('ui.panel.profile.change_password.error_required')]]"
|
||||
></paper-input>
|
||||
<paper-input
|
||||
label="[[localize('ui.panel.profile.change_password.confirm_new_password')]]"
|
||||
type="password"
|
||||
value="{{_password2}}"
|
||||
required
|
||||
auto-validate
|
||||
error-message="[[localize('ui.panel.profile.change_password.error_required')]]"
|
||||
></paper-input>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<template is="dom-if" if="[[_loading]]">
|
||||
<div><ha-circular-progress active></ha-circular-progress></div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!_loading]]">
|
||||
<mwc-button on-click="_changePassword"
|
||||
>[[localize('ui.panel.profile.change_password.submit')]]</mwc-button
|
||||
>
|
||||
</template>
|
||||
</div>
|
||||
</ha-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
|
||||
_loading: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
// Error message when can't talk to server etc
|
||||
_statusMsg: String,
|
||||
_errorMsg: String,
|
||||
|
||||
_currentPassword: String,
|
||||
_password1: String,
|
||||
_password2: String,
|
||||
};
|
||||
}
|
||||
|
||||
ready() {
|
||||
super.ready();
|
||||
this.addEventListener("keypress", (ev) => {
|
||||
this._statusMsg = null;
|
||||
if (ev.keyCode === 13) {
|
||||
this._changePassword();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _changePassword() {
|
||||
this._statusMsg = null;
|
||||
if (!this._currentPassword || !this._password1 || !this._password2) return;
|
||||
|
||||
if (this._password1 !== this._password2) {
|
||||
this._errorMsg = "New password confirmation doesn't match";
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._currentPassword === this._password1) {
|
||||
this._errorMsg = "New password must be different than current password";
|
||||
return;
|
||||
}
|
||||
|
||||
this._loading = true;
|
||||
this._errorMsg = null;
|
||||
|
||||
try {
|
||||
await this.hass.callWS({
|
||||
type: "config/auth_provider/homeassistant/change_password",
|
||||
current_password: this._currentPassword,
|
||||
new_password: this._password1,
|
||||
});
|
||||
|
||||
this.setProperties({
|
||||
_statusMsg: "Password changed successfully",
|
||||
_currentPassword: null,
|
||||
_password1: null,
|
||||
_password2: null,
|
||||
});
|
||||
} catch (err) {
|
||||
this._errorMsg = err.message;
|
||||
}
|
||||
|
||||
this._loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ha-change-password-card", HaChangePasswordCard);
|
195
src/panels/profile/ha-change-password-card.ts
Normal file
195
src/panels/profile/ha-change-password-card.ts
Normal file
@@ -0,0 +1,195 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import "@polymer/paper-dialog/paper-dialog";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import "@material/mwc-button";
|
||||
import "../../components/ha-circular-progress";
|
||||
import "../../components/ha-card";
|
||||
import { haStyle } from "../../resources/styles";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
|
||||
@customElement("ha-change-password-card")
|
||||
class HaChangePasswordCard extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@internalProperty() private _loading = false;
|
||||
|
||||
@internalProperty() private _statusMsg?: string;
|
||||
|
||||
@internalProperty() private _errorMsg?: string;
|
||||
|
||||
@internalProperty() private _currentPassword?: string;
|
||||
|
||||
@internalProperty() private _password?: string;
|
||||
|
||||
@internalProperty() private _passwordConfirm?: string;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div>
|
||||
<ha-card
|
||||
.header=${this.hass.localize(
|
||||
"ui.panel.profile.change_password.header"
|
||||
)}
|
||||
>
|
||||
<div class="card-content">
|
||||
${this._errorMsg
|
||||
? html` <div class="error">${this._errorMsg}</div> `
|
||||
: ""}
|
||||
${this._statusMsg
|
||||
? html` <div class="status">${this._statusMsg}</div> `
|
||||
: ""}
|
||||
|
||||
<paper-input
|
||||
id="currentPassword"
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.profile.change_password.current_password"
|
||||
)}
|
||||
type="password"
|
||||
.value=${this._currentPassword}
|
||||
@value-changed=${this._currentPasswordChanged}
|
||||
required
|
||||
></paper-input>
|
||||
|
||||
${this._currentPassword
|
||||
? html` <paper-input
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.profile.change_password.new_password"
|
||||
)}
|
||||
name="password"
|
||||
type="password"
|
||||
.value=${this._password}
|
||||
@value-changed=${this._newPasswordChanged}
|
||||
required
|
||||
auto-validate
|
||||
></paper-input>
|
||||
<paper-input
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.profile.change_password.confirm_new_password"
|
||||
)}
|
||||
name="passwordConfirm"
|
||||
type="password"
|
||||
.value=${this._passwordConfirm}
|
||||
@value-changed=${this._newPasswordConfirmChanged}
|
||||
required
|
||||
auto-validate
|
||||
></paper-input>`
|
||||
: ""}
|
||||
</div>
|
||||
|
||||
<div class="card-actions">
|
||||
${this._loading
|
||||
? html`<div>
|
||||
<ha-circular-progress active></ha-circular-progress>
|
||||
</div>`
|
||||
: html`<mwc-button
|
||||
@click=${this._changePassword}
|
||||
.disabled=${!this._passwordConfirm}
|
||||
>${this.hass.localize(
|
||||
"ui.panel.profile.change_password.submit"
|
||||
)}</mwc-button
|
||||
>`}
|
||||
</div>
|
||||
</ha-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _currentPasswordChanged(ev: CustomEvent) {
|
||||
this._currentPassword = ev.detail.value;
|
||||
}
|
||||
|
||||
private _newPasswordChanged(ev: CustomEvent) {
|
||||
this._password = ev.detail.value;
|
||||
}
|
||||
|
||||
private _newPasswordConfirmChanged(ev: CustomEvent) {
|
||||
this._passwordConfirm = ev.detail.value;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
this.addEventListener("keypress", (ev) => {
|
||||
this._statusMsg = undefined;
|
||||
if (ev.keyCode === 13) {
|
||||
this._changePassword();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _changePassword() {
|
||||
this._statusMsg = undefined;
|
||||
if (!this._currentPassword || !this._password || !this._passwordConfirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._password !== this._passwordConfirm) {
|
||||
this._errorMsg = this.hass.localize(
|
||||
"ui.panel.profile.change_password.error_new_mismatch"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._currentPassword === this._password) {
|
||||
this._errorMsg = this.hass.localize(
|
||||
"ui.panel.profile.change_password.error_new_is_old"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this._loading = true;
|
||||
this._errorMsg = undefined;
|
||||
|
||||
try {
|
||||
await this.hass.callWS({
|
||||
type: "config/auth_provider/homeassistant/change_password",
|
||||
current_password: this._currentPassword,
|
||||
new_password: this._password,
|
||||
});
|
||||
} catch (err) {
|
||||
this._errorMsg = err.message;
|
||||
return;
|
||||
} finally {
|
||||
this._loading = false;
|
||||
}
|
||||
|
||||
this._statusMsg = this.hass.localize(
|
||||
"ui.panel.profile.change_password.success"
|
||||
);
|
||||
this._currentPassword = undefined;
|
||||
this._password = undefined;
|
||||
this._passwordConfirm = undefined;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
}
|
||||
.status {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
#currentPassword {
|
||||
margin-top: -8px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-change-password-card": HaChangePasswordCard;
|
||||
}
|
||||
}
|
@@ -25,7 +25,7 @@ class HaPushNotificationsRow extends LocalizeMixin(PolymerElement) {
|
||||
>[[localize('ui.panel.profile.push_notifications.header')]]</span
|
||||
>
|
||||
<span slot="description">
|
||||
[[_description(_platformLoaded, _pushSupported)]]
|
||||
[[localize(_descrLocalizeKey)]]
|
||||
<a
|
||||
href="[[_computeDocumentationUrl(hass)]]"
|
||||
target="_blank"
|
||||
@@ -45,6 +45,10 @@ class HaPushNotificationsRow extends LocalizeMixin(PolymerElement) {
|
||||
return {
|
||||
hass: Object,
|
||||
narrow: Boolean,
|
||||
_descrLocalizeKey: {
|
||||
type: String,
|
||||
computed: "_descriptionKey(_platformLoaded, _pushSupported)",
|
||||
},
|
||||
_platformLoaded: {
|
||||
type: Boolean,
|
||||
computed: "_compPlatformLoaded(hass)",
|
||||
@@ -72,7 +76,7 @@ class HaPushNotificationsRow extends LocalizeMixin(PolymerElement) {
|
||||
return !platformLoaded || !pushSupported_;
|
||||
}
|
||||
|
||||
_description(platformLoaded, pushSupported_) {
|
||||
_descriptionKey(platformLoaded, pushSupported_) {
|
||||
let key;
|
||||
if (!pushSupported_) {
|
||||
key = "error_use_https";
|
||||
@@ -81,7 +85,7 @@ class HaPushNotificationsRow extends LocalizeMixin(PolymerElement) {
|
||||
} else {
|
||||
key = "description";
|
||||
}
|
||||
return this.localize(`ui.panel.profile.push_notifications.${key}`);
|
||||
return `ui.panel.profile.push_notifications.${key}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -33,7 +33,8 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
duration: 0,
|
||||
dismissable: false,
|
||||
action: {
|
||||
text: this.hass!.localize("ui.notification_toast.dismiss"),
|
||||
text:
|
||||
this.hass!.localize("ui.notification_toast.dismiss") || "Dismiss",
|
||||
action: () => {},
|
||||
},
|
||||
});
|
||||
|
@@ -21,7 +21,8 @@ export const panelTitleMixin = <T extends Constructor<HassBaseEl>>(
|
||||
if (
|
||||
!oldHass ||
|
||||
oldHass.panels !== this.hass.panels ||
|
||||
oldHass.panelUrl !== this.hass.panelUrl
|
||||
oldHass.panelUrl !== this.hass.panelUrl ||
|
||||
oldHass.localize !== this.hass.localize
|
||||
) {
|
||||
setTitle(getPanelTitle(this.hass));
|
||||
}
|
||||
|
@@ -36,6 +36,8 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
// eslint-disable-next-line: variable-name
|
||||
private __coreProgress?: string;
|
||||
|
||||
private __loadedFragmetTranslations: Set<string> = new Set();
|
||||
|
||||
private __loadedTranslations: {
|
||||
// track what things have been loaded
|
||||
[category: string]: LoadedTranslationCategory;
|
||||
@@ -101,6 +103,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
document.querySelector("html")!.setAttribute("lang", hass.language);
|
||||
this.style.direction = computeRTL(hass) ? "rtl" : "ltr";
|
||||
this._loadCoreTranslations(hass.language);
|
||||
this.__loadedFragmetTranslations = new Set();
|
||||
this._loadFragmentTranslations(hass.language, hass.panelUrl);
|
||||
}
|
||||
|
||||
@@ -195,10 +198,31 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
language: string,
|
||||
panelUrl: string
|
||||
) {
|
||||
if (translationMetadata.fragments.includes(panelUrl)) {
|
||||
const result = await getTranslation(panelUrl, language);
|
||||
this._updateResources(result.language, result.data);
|
||||
if (!panelUrl) {
|
||||
return;
|
||||
}
|
||||
const panelComponent = this.hass?.panels?.[panelUrl]?.component_name;
|
||||
|
||||
// If it's the first call we don't have panel info yet to check the component.
|
||||
// If the url is not known it might be a custom lovelace dashboard, so we load lovelace translations
|
||||
const fragment = translationMetadata.fragments.includes(
|
||||
panelComponent || panelUrl
|
||||
)
|
||||
? panelComponent || panelUrl
|
||||
: !panelComponent
|
||||
? "lovelace"
|
||||
: undefined;
|
||||
|
||||
if (!fragment) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.__loadedFragmetTranslations.has(fragment)) {
|
||||
return;
|
||||
}
|
||||
this.__loadedFragmetTranslations.add(fragment);
|
||||
const result = await getTranslation(fragment, language);
|
||||
this._updateResources(result.language, result.data);
|
||||
}
|
||||
|
||||
private async _loadCoreTranslations(language: string) {
|
||||
@@ -210,7 +234,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
this.__coreProgress = language;
|
||||
try {
|
||||
const result = await getTranslation(null, language);
|
||||
this._updateResources(result.language, result.data);
|
||||
await this._updateResources(result.language, result.data);
|
||||
} finally {
|
||||
this.__coreProgress = undefined;
|
||||
}
|
||||
@@ -226,18 +250,29 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
// before this.hass is even created. In this case our base state comes
|
||||
// from this._pendingHass instead. Otherwise the first set of strings is
|
||||
// overwritten when we call _updateHass the second time!
|
||||
const baseHass = this.hass ?? this._pendingHass;
|
||||
|
||||
// Allow hass to be updated
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
|
||||
if (language !== (this.hass ?? this._pendingHass).language) {
|
||||
// the language was changed, abort
|
||||
return;
|
||||
}
|
||||
|
||||
const resources = {
|
||||
[language]: {
|
||||
...baseHass?.resources?.[language],
|
||||
...(this.hass ?? this._pendingHass)?.resources?.[language],
|
||||
...data,
|
||||
},
|
||||
};
|
||||
const changes: Partial<HomeAssistant> = { resources };
|
||||
if (this.hass && language === this.hass.language) {
|
||||
changes.localize = await computeLocalize(this, language, resources);
|
||||
const changes: Partial<HomeAssistant> = {
|
||||
resources,
|
||||
localize: await computeLocalize(this, language, resources),
|
||||
};
|
||||
|
||||
if (language === (this.hass ?? this._pendingHass).language) {
|
||||
this._updateHass(changes);
|
||||
}
|
||||
this._updateHass(changes);
|
||||
}
|
||||
|
||||
private _refetchCachedHassTranslations(
|
||||
|
@@ -98,7 +98,8 @@
|
||||
"disabled_by": {
|
||||
"user": "User",
|
||||
"integration": "Integration",
|
||||
"config_entry": "Config Entry"
|
||||
"config_entry": "Config Entry",
|
||||
"device": "Device"
|
||||
}
|
||||
},
|
||||
"ui": {
|
||||
@@ -327,6 +328,7 @@
|
||||
"entity-picker": {
|
||||
"entity": "Entity",
|
||||
"clear": "Clear",
|
||||
"no_match": "No matching entities found",
|
||||
"show_entities": "Show entities"
|
||||
},
|
||||
"entity-attribute-picker": {
|
||||
@@ -334,6 +336,16 @@
|
||||
"show_attributes": "Show attributes"
|
||||
}
|
||||
},
|
||||
"target-picker": {
|
||||
"expand_area_id": "Expand this area in the seperate devices and entities that it contains. After expanding it will not update the devices and entities when the area changes.",
|
||||
"expand_device_id": "Expand this device in seperate entities. After expanding it will not update the entities when the device changes.",
|
||||
"remove_area_id": "Remove area",
|
||||
"remove_device_id": "Remove device",
|
||||
"remove_entity_id": "Remove entity",
|
||||
"add_area_id": "Pick area",
|
||||
"add_device_id": "Pick device",
|
||||
"add_entity_id": "Pick entity"
|
||||
},
|
||||
"user-picker": {
|
||||
"no_user": "No user",
|
||||
"add_user": "Add user",
|
||||
@@ -348,6 +360,8 @@
|
||||
"clear": "Clear",
|
||||
"toggle": "Toggle",
|
||||
"show_devices": "Show devices",
|
||||
"no_devices": "You don't have any devices",
|
||||
"no_match": "No matching devices found",
|
||||
"device": "Device",
|
||||
"no_area": "No area"
|
||||
},
|
||||
@@ -356,6 +370,8 @@
|
||||
"show_areas": "Show areas",
|
||||
"area": "Area",
|
||||
"add_new": "Add new area…",
|
||||
"no_areas": "You don't have any areas",
|
||||
"no_match": "No matching areas found",
|
||||
"add_dialog": {
|
||||
"title": "Add new area",
|
||||
"text": "Enter the name of the new area.",
|
||||
@@ -612,6 +628,8 @@
|
||||
"unavailable": "This entity is not currently available.",
|
||||
"enabled_label": "Enable entity",
|
||||
"enabled_cause": "Disabled by {cause}.",
|
||||
"device_disabled": "The device of this entity is disabled.",
|
||||
"open_device_settings": "Open device settings",
|
||||
"enabled_description": "Disabled entities will not be added to Home Assistant.",
|
||||
"enabled_delay_confirm": "The enabled entities will be added to Home Assistant in {delay} seconds",
|
||||
"enabled_restart_confirm": "Restart Home Assistant to finish enabling the entities",
|
||||
@@ -787,7 +805,7 @@
|
||||
},
|
||||
"areas": {
|
||||
"caption": "Areas",
|
||||
"description": "Manage areas in your home",
|
||||
"description": "Group devices and entities into areas",
|
||||
"data_table": {
|
||||
"area": "Area",
|
||||
"devices": "Devices"
|
||||
@@ -817,7 +835,7 @@
|
||||
},
|
||||
"tags": {
|
||||
"caption": "Tags",
|
||||
"description": "Manage tags",
|
||||
"description": "Trigger automations when a NFC tag, QR code, etc. is scanned",
|
||||
"learn_more": "Learn more about tags",
|
||||
"no_tags": "No tags",
|
||||
"add_tag": "Add tag",
|
||||
@@ -836,7 +854,7 @@
|
||||
"new_tag": "New tag",
|
||||
"name": "Name",
|
||||
"description": "Description",
|
||||
"tag_id": "Tag id",
|
||||
"tag_id": "Tag ID",
|
||||
"tag_id_placeholder": "Autogenerated when left empty",
|
||||
"delete": "Delete",
|
||||
"update": "Update",
|
||||
@@ -848,7 +866,7 @@
|
||||
},
|
||||
"helpers": {
|
||||
"caption": "Helpers",
|
||||
"description": "Manage elements that help build automations",
|
||||
"description": "Elements that help build automations",
|
||||
"types": {
|
||||
"input_text": "Text",
|
||||
"input_number": "Number",
|
||||
@@ -876,7 +894,7 @@
|
||||
},
|
||||
"core": {
|
||||
"caption": "General",
|
||||
"description": "Change your general Home Assistant configuration",
|
||||
"description": "Unit system, location, time zone & other general parameters",
|
||||
"section": {
|
||||
"core": {
|
||||
"header": "General Configuration",
|
||||
@@ -905,7 +923,7 @@
|
||||
"caption": "Info",
|
||||
"copy_raw": "Raw Text",
|
||||
"copy_github": "For GitHub",
|
||||
"description": "View info about your Home Assistant installation",
|
||||
"description": "Version, system health and links to documentation",
|
||||
"home_assistant_logo": "Home Assistant logo",
|
||||
"path_configuration": "Path to configuration.yaml: {path}",
|
||||
"developed_by": "Developed by a bunch of awesome people.",
|
||||
@@ -940,7 +958,7 @@
|
||||
},
|
||||
"lovelace": {
|
||||
"caption": "Lovelace Dashboards",
|
||||
"description": "Manage your Lovelace Dashboards",
|
||||
"description": "Create customized sets of cards to control your home",
|
||||
"dashboards": {
|
||||
"default_dashboard": "This is the default dashboard",
|
||||
"caption": "Dashboards",
|
||||
@@ -1031,7 +1049,7 @@
|
||||
"introduction": "Some parts of Home Assistant can reload without requiring a restart. Hitting reload will unload their current YAML configuration and load the new one.",
|
||||
"reload": "Reload {domain}",
|
||||
"core": "Reload location & customizations",
|
||||
"group": "Reload groups, group entities, and notify services",
|
||||
"group": "Reload groups, group entities, and group notify services",
|
||||
"automation": "Reload automations",
|
||||
"script": "Reload scripts",
|
||||
"scene": "Reload scenes",
|
||||
@@ -1044,7 +1062,7 @@
|
||||
"input_select": "Reload input selects",
|
||||
"template": "Reload template entities",
|
||||
"universal": "Reload universal media player entities",
|
||||
"rest": "Reload rest entities and notify services",
|
||||
"rest": "Reload rest entities, and rest notify services",
|
||||
"command_line": "Reload command line entities",
|
||||
"filter": "Reload filter entities",
|
||||
"statistics": "Reload statistics entities",
|
||||
@@ -1095,7 +1113,7 @@
|
||||
},
|
||||
"automation": {
|
||||
"caption": "Automations",
|
||||
"description": "Manage automations",
|
||||
"description": "Create custom behavior rules for your home",
|
||||
"picker": {
|
||||
"header": "Automation Editor",
|
||||
"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.",
|
||||
@@ -1130,7 +1148,7 @@
|
||||
},
|
||||
"editor": {
|
||||
"enable_disable": "Enable/Disable automation",
|
||||
"introduction": "Use automations to bring your home to live.",
|
||||
"introduction": "Use automations to bring your home to life.",
|
||||
"default_name": "New Automation",
|
||||
"load_error_not_editable": "Only automations in automations.yaml are editable.",
|
||||
"load_error_unknown": "Error loading automation ({err_no}).",
|
||||
@@ -1147,8 +1165,6 @@
|
||||
"header": "Blueprint",
|
||||
"blueprint_to_use": "Blueprint to use",
|
||||
"no_blueprints": "You don't have any blueprints",
|
||||
"manage_blueprints": "Manage Blueprints",
|
||||
"inputs": "Inputs",
|
||||
"no_inputs": "This blueprint doesn't have any inputs."
|
||||
},
|
||||
"modes": {
|
||||
@@ -1445,8 +1461,8 @@
|
||||
"description": "Manage blueprints",
|
||||
"overview": {
|
||||
"header": "Blueprint Editor",
|
||||
"introduction": "The blueprint editor allows you to create and edit blueprints.",
|
||||
"learn_more": "Learn more about blueprints",
|
||||
"introduction": "The blueprint configuration allows you to import and manage your blueprints.",
|
||||
"learn_more": "Learn more about using blueprints",
|
||||
"headers": {
|
||||
"name": "Name",
|
||||
"domain": "Domain",
|
||||
@@ -1456,26 +1472,28 @@
|
||||
"confirm_delete_text": "Are you sure you want to delete this blueprint?",
|
||||
"add_blueprint": "Import blueprint",
|
||||
"use_blueprint": "Create automation",
|
||||
"delete_blueprint": "Delete blueprint"
|
||||
"delete_blueprint": "Delete blueprint",
|
||||
"discover_more": "Discover more blueprints"
|
||||
},
|
||||
"add": {
|
||||
"header": "Add new blueprint",
|
||||
"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.",
|
||||
"header": "Import a blueprint",
|
||||
"import_header": "Blueprint \"{name}\"",
|
||||
"import_introduction_link": "You can import blueprints of other users from Github and the {community_link}. Enter the URL of the blueprint below.",
|
||||
"community_forums": "community forums",
|
||||
"url": "URL of the blueprint",
|
||||
"raw_blueprint": "Blueprint content",
|
||||
"importing": "Importing blueprint...",
|
||||
"import_btn": "Import blueprint",
|
||||
"saving": "Saving blueprint...",
|
||||
"save_btn": "Save blueprint",
|
||||
"importing": "Loading blueprint...",
|
||||
"import_btn": "Preview blueprint",
|
||||
"saving": "Importing blueprint...",
|
||||
"save_btn": "Import blueprint",
|
||||
"error_no_url": "Please enter the URL of the blueprint.",
|
||||
"unsupported_blueprint": "This blueprint is not supported",
|
||||
"file_name": "Local blueprint file name"
|
||||
"file_name": "Blueprint Path"
|
||||
}
|
||||
},
|
||||
"script": {
|
||||
"caption": "Scripts",
|
||||
"description": "Manage scripts",
|
||||
"description": "Execute a sequence of actions",
|
||||
"picker": {
|
||||
"header": "Script Editor",
|
||||
"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.",
|
||||
@@ -1525,7 +1543,7 @@
|
||||
},
|
||||
"scene": {
|
||||
"caption": "Scenes",
|
||||
"description": "Manage scenes",
|
||||
"description": "Capture device states and easily recall them later",
|
||||
"activated": "Activated scene {name}.",
|
||||
"picker": {
|
||||
"header": "Scene Editor",
|
||||
@@ -1544,7 +1562,7 @@
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"introduction": "Use scenes to bring your home to live.",
|
||||
"introduction": "Use scenes to bring your home to life.",
|
||||
"default_name": "New Scene",
|
||||
"load_error_not_editable": "Only scenes in scenes.yaml are editable.",
|
||||
"load_error_unknown": "Error loading scene ({err_no}).",
|
||||
@@ -1571,7 +1589,7 @@
|
||||
"cloud": {
|
||||
"description_login": "Logged in as {email}",
|
||||
"description_not_login": "Not logged in",
|
||||
"description_features": "Control away from home, integrate with Alexa and Google Assistant.",
|
||||
"description_features": "Control home when away and integrate with Alexa and Google Assistant",
|
||||
"login": {
|
||||
"title": "Cloud Login",
|
||||
"introduction": "Home Assistant Cloud provides you with a secure remote connection to your instance while away from home. It also allows you to connect with cloud-only services: Amazon Alexa and Google Assistant.",
|
||||
@@ -1738,18 +1756,27 @@
|
||||
"devices": {
|
||||
"add_prompt": "No {name} have been added using this device yet. You can add one by clicking the + button above.",
|
||||
"caption": "Devices",
|
||||
"description": "Manage connected devices",
|
||||
"description": "Manage configured devices",
|
||||
"device_info": "Device info",
|
||||
"unnamed_device": "Unnamed device",
|
||||
"unknown_error": "Unknown error",
|
||||
"name": "Name",
|
||||
"update": "Update",
|
||||
"no_devices": "No devices",
|
||||
"enabled_label": "Enable device",
|
||||
"enabled_cause": "The device is disabled by {cause}.",
|
||||
"disabled_by": {
|
||||
"user": "User",
|
||||
"integration": "Integration",
|
||||
"config_entry": "Config Entry"
|
||||
},
|
||||
"enabled_description": "Disabled devices will not be shown and entities belonging to the device will be disabled and not added to Home Assistant.",
|
||||
"automation": {
|
||||
"automations": "Automations",
|
||||
"no_automations": "No automations",
|
||||
"unknown_automation": "Unknown automation",
|
||||
"create": "Create automation with device",
|
||||
"create_disable": "Can't create automation with disabled device",
|
||||
"triggers": {
|
||||
"caption": "Do something when...",
|
||||
"no_triggers": "No triggers",
|
||||
@@ -1770,12 +1797,14 @@
|
||||
"script": {
|
||||
"scripts": "Scripts",
|
||||
"no_scripts": "No scripts",
|
||||
"create": "Create script with device"
|
||||
"create": "Create script with device",
|
||||
"create_disable": "Can't create script with disabled device"
|
||||
},
|
||||
"scene": {
|
||||
"scenes": "Scenes",
|
||||
"no_scenes": "No scenes",
|
||||
"create": "Create scene with device"
|
||||
"create": "Create scene with device",
|
||||
"create_disable": "Can't create scene with disabled device"
|
||||
},
|
||||
"cant_edit": "You can only edit items that are created in the UI.",
|
||||
"device_not_found": "Device not found.",
|
||||
@@ -1790,6 +1819,7 @@
|
||||
"scenes": "Scenes",
|
||||
"confirm_rename_entity_ids": "Do you also want to rename the entity IDs of your entities?",
|
||||
"confirm_rename_entity_ids_warning": "This will not change any configuration (like automations, scripts, scenes, dashboards) that is currently using these entities! You will have to update them yourself to use the new entity IDs!",
|
||||
"disabled": "Disabled",
|
||||
"data_table": {
|
||||
"device": "Device",
|
||||
"manufacturer": "Manufacturer",
|
||||
@@ -1797,11 +1827,19 @@
|
||||
"area": "Area",
|
||||
"integration": "Integration",
|
||||
"battery": "Battery",
|
||||
"no_devices": "No devices",
|
||||
"no_area": "No area"
|
||||
"no_devices": "No devices"
|
||||
},
|
||||
"delete": "Delete",
|
||||
"confirm_delete": "Are you sure you want to delete this device?"
|
||||
"confirm_delete": "Are you sure you want to delete this device?",
|
||||
"picker": {
|
||||
"search": "Search devices",
|
||||
"filter": {
|
||||
"filter": "Filter",
|
||||
"show_disabled": "Show disabled devices",
|
||||
"hidden_devices": "{number} hidden {number, plural,\n one {device}\n other {devices}\n}",
|
||||
"show_all": "Show all"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"caption": "Entities",
|
||||
@@ -1916,7 +1954,7 @@
|
||||
},
|
||||
"integrations": {
|
||||
"caption": "Integrations",
|
||||
"description": "Manage integrations",
|
||||
"description": "Manage integrations with services, devices, ...",
|
||||
"integration": "integration",
|
||||
"discovered": "Discovered",
|
||||
"attention": "Attention required",
|
||||
@@ -1989,7 +2027,7 @@
|
||||
},
|
||||
"users": {
|
||||
"caption": "Users",
|
||||
"description": "Manage users",
|
||||
"description": "Manage the Home Assistant user accounts",
|
||||
"users_privileges_note": "The user group feature is a work in progress. The user will be unable to administer the instance via the UI. We're still auditing all management API endpoints to ensure that they correctly limit access to administrators.",
|
||||
"picker": {
|
||||
"headers": {
|
||||
@@ -2022,7 +2060,8 @@
|
||||
"system_generated_users_not_removable": "Unable to remove system generated users.",
|
||||
"system_generated_users_not_editable": "Unable to update system generated users.",
|
||||
"unnamed_user": "Unnamed User",
|
||||
"confirm_user_deletion": "Are you sure you want to delete {name}?"
|
||||
"confirm_user_deletion": "Are you sure you want to delete {name}?",
|
||||
"active_tooltip": "Controls if user can login"
|
||||
},
|
||||
"add_user": {
|
||||
"caption": "Add user",
|
||||
@@ -2871,7 +2910,10 @@
|
||||
"new_password": "New Password",
|
||||
"confirm_new_password": "Confirm New Password",
|
||||
"error_required": "Required",
|
||||
"submit": "Submit"
|
||||
"submit": "Submit",
|
||||
"error_new_mismatch": "Entered new password values do not match",
|
||||
"error_new_is_old": "New password must be different than current password",
|
||||
"success": "Password changed successfully"
|
||||
},
|
||||
"mfa": {
|
||||
"header": "Multi-factor Authentication Modules",
|
||||
|
@@ -437,6 +437,7 @@
|
||||
"add_new": "إضافة منطقة جديدة ...",
|
||||
"area": "المنطقة",
|
||||
"clear": "مسح",
|
||||
"no_match": "لم يتم العثور على مناطق مطابقة",
|
||||
"show_areas": "إظهار المناطق"
|
||||
},
|
||||
"data-table": {
|
||||
@@ -449,6 +450,7 @@
|
||||
},
|
||||
"device-picker": {
|
||||
"no_area": "لا مجال",
|
||||
"no_match": "لم يتم العثور على أجهزة مطابقة",
|
||||
"toggle": "تبديل"
|
||||
},
|
||||
"entity": {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,13 @@
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Entrada de configuració",
|
||||
"device": "Dispositiu",
|
||||
"integration": "Integració",
|
||||
"user": "Usuari"
|
||||
}
|
||||
},
|
||||
"groups": {
|
||||
"owner": "Propietari",
|
||||
"system-admin": "Administradors",
|
||||
"system-read-only": "Usuaris de només lectura",
|
||||
"system-users": "Usuaris"
|
||||
@@ -545,12 +547,14 @@
|
||||
"add_new": "Afegir àrea nova...",
|
||||
"area": "Àrea",
|
||||
"clear": "Esborra",
|
||||
"no_areas": "No tens cap àrea",
|
||||
"no_match": "No s'han trobat àrees coincidents",
|
||||
"show_areas": "Mostra àrees"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
"add_user": "Afegeix usuari",
|
||||
"remove_user": "Elimina usuari",
|
||||
"select_blueprint": "Selecciona un plànol"
|
||||
"select_blueprint": "Selecciona un blueprint"
|
||||
},
|
||||
"data-table": {
|
||||
"no-data": "No hi ha dades",
|
||||
@@ -565,6 +569,8 @@
|
||||
"clear": "Esborra",
|
||||
"device": "Dispositiu",
|
||||
"no_area": "Sense àrees",
|
||||
"no_devices": "No tens cap dispositiu",
|
||||
"no_match": "No s'han trobat dispositius coincidents",
|
||||
"show_devices": "Mostra dispositius",
|
||||
"toggle": "Commuta"
|
||||
},
|
||||
@@ -576,6 +582,7 @@
|
||||
"entity-picker": {
|
||||
"clear": "Esborra",
|
||||
"entity": "Entitat",
|
||||
"no_match": "No s'han trobat entitats coincidents",
|
||||
"show_entities": "Mostra entitats"
|
||||
}
|
||||
},
|
||||
@@ -709,6 +716,16 @@
|
||||
"service-picker": {
|
||||
"service": "Servei"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_area_id": "Selecciona àrea",
|
||||
"add_device_id": "Selecciona dispositiu",
|
||||
"add_entity_id": "Selecciona entitat",
|
||||
"expand_area_id": "Expandeix aquesta àrea en els dispositius i entitats que conté. Després d'expandir-la, no s'actualitzaran els dispositius i les entitats quan l'àrea canviï.",
|
||||
"expand_device_id": "Expandeix aquest dispositiu en entitats separades. Després d'expandir-lo, no s'actualitzaran les entitats quan el dispositiu canviï.",
|
||||
"remove_area_id": "Elimina àrea",
|
||||
"remove_device_id": "Elimina dispositiu",
|
||||
"remove_entity_id": "Elimina entitat"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Afegeix usuari",
|
||||
"no_user": "Cap usuari",
|
||||
@@ -732,6 +749,7 @@
|
||||
"editor": {
|
||||
"confirm_delete": "Estàs segur que vols eliminar aquesta entrada?",
|
||||
"delete": "Elimina",
|
||||
"device_disabled": "El dispositiu d'aquesta entitat està desactivat.",
|
||||
"enabled_cause": "Desactivada per {cause}.",
|
||||
"enabled_delay_confirm": "Les entitats activades s'afegiran a Home Assistant d'aquí a {delay} segons",
|
||||
"enabled_description": "Les entitats desactivades no s'afegiran a Home Assistant.",
|
||||
@@ -742,6 +760,7 @@
|
||||
"icon_error": "Els icones han de tenir el format 'prefix:nom_icona', per exemple: 'mdi:home'",
|
||||
"name": "Nom",
|
||||
"note": "Nota: podria no funcionar amb alguna de les integracions.",
|
||||
"open_device_settings": "Obre la configuració del dispositiu",
|
||||
"unavailable": "Aquesta entitat no està disponible actualment.",
|
||||
"update": "Actualitza"
|
||||
},
|
||||
@@ -882,7 +901,7 @@
|
||||
"navigation": {
|
||||
"areas": "Àrees",
|
||||
"automation": "Automatització",
|
||||
"blueprint": "Plànols",
|
||||
"blueprint": "Blueprints",
|
||||
"core": "General",
|
||||
"customize": "Personalització",
|
||||
"devices": "Dispositius",
|
||||
@@ -1029,7 +1048,7 @@
|
||||
"confirmation_text": "Tots els dispositius d'aquesta àrea quedaran sense assignar.",
|
||||
"confirmation_title": "Estàs segur que vols eliminar aquesta àrea?"
|
||||
},
|
||||
"description": "Gestiona les àrees de la casa",
|
||||
"description": "Agrupa dispositius i entitats en àrees",
|
||||
"editor": {
|
||||
"area_id": "ID d'àrea",
|
||||
"create": "Crea",
|
||||
@@ -1051,10 +1070,10 @@
|
||||
},
|
||||
"automation": {
|
||||
"caption": "Automatització",
|
||||
"description": "Gestiona les automatitzacions",
|
||||
"description": "Crea regles de comportament personalitzades per a casa teva",
|
||||
"dialog_new": {
|
||||
"blueprint": {
|
||||
"use_blueprint": "Utilitza un plànol"
|
||||
"use_blueprint": "Utilitza un blueprint"
|
||||
},
|
||||
"header": "Creació d'una nova automatització",
|
||||
"how": "Com vols crear la nova automatització?",
|
||||
@@ -1147,12 +1166,12 @@
|
||||
},
|
||||
"alias": "Nom",
|
||||
"blueprint": {
|
||||
"blueprint_to_use": "Plànol a utilitzar",
|
||||
"header": "Plànol",
|
||||
"blueprint_to_use": "Blueprint a utilitzar",
|
||||
"header": "Blueprint",
|
||||
"inputs": "Entrades",
|
||||
"manage_blueprints": "Gestiona els plànols",
|
||||
"no_blueprints": "No tens plànols",
|
||||
"no_inputs": "Aquest plànol no té entrades."
|
||||
"manage_blueprints": "Gestiona els blueprints",
|
||||
"no_blueprints": "No tens blueprints",
|
||||
"no_inputs": "Aquest blueprint no té entrades."
|
||||
},
|
||||
"conditions": {
|
||||
"add": "Afegir condició",
|
||||
@@ -1239,7 +1258,7 @@
|
||||
"edit_ui": "Edita a través d'interfície",
|
||||
"edit_yaml": "Edita com a YAML",
|
||||
"enable_disable": "Activa/desactiva automatització",
|
||||
"introduction": "Utilitza les automatitzacions per donar més vida a la teva casa",
|
||||
"introduction": "Utilitza les automatitzacions per donar vida a casa teva.",
|
||||
"load_error_not_editable": "Només es poden editar les automatitzacions de l'arxiu automations.yaml.",
|
||||
"load_error_unknown": "Error en carregar l'automatització ({err_no}).",
|
||||
"max": {
|
||||
@@ -1398,29 +1417,38 @@
|
||||
},
|
||||
"blueprint": {
|
||||
"add": {
|
||||
"error_no_url": "Introdueix l'URL del plànol.",
|
||||
"header": "Afegiu plànol nou",
|
||||
"import_btn": "Importa plànol",
|
||||
"import_header": "Importa {name} ({domain})",
|
||||
"import_introduction": "Pots importar plànols d'altres usuaris des de Github i els fòrums de la comunitat. Introdueix, a sota, l'URL del plànol.",
|
||||
"importing": "Important plànol",
|
||||
"save_btn": "Desa plànol",
|
||||
"saving": "Desant plànol...",
|
||||
"unsupported_blueprint": "Aquest plànols no és compatible",
|
||||
"url": "URL del plànol"
|
||||
"community_forums": "fòrums de la comunitat",
|
||||
"error_no_url": "Introdueix l'URL del blueprint.",
|
||||
"file_name": "Directori del blueprint",
|
||||
"header": "Importa un blueprint nou",
|
||||
"import_btn": "Vista prèvia del blueprint",
|
||||
"import_header": "Blueprint \"{name}\"",
|
||||
"import_introduction": "Pots importar blueprints d'altres usuaris des de Github i els fòrums de la comunitat. Introdueix, a sota, l'URL del blueprint.",
|
||||
"import_introduction_link": "Pots importar blueprints d'altres usuaris des de Github i des dels {community_link}. Introdueix, a sota, l'URL del blueprint.",
|
||||
"importing": "Carregant blueprint...",
|
||||
"raw_blueprint": "Contingut del blueprint",
|
||||
"save_btn": "Importa blueprint",
|
||||
"saving": "Important blueprint...",
|
||||
"unsupported_blueprint": "Aquest blueprint no és compatible",
|
||||
"url": "URL del blueprint"
|
||||
},
|
||||
"caption": "Plànols",
|
||||
"description": "Gestiona els plànols",
|
||||
"caption": "Blueprints",
|
||||
"description": "Gestiona els blueprints",
|
||||
"overview": {
|
||||
"add_blueprint": "Afegiu plànol",
|
||||
"confirm_delete_header": "Eliminar aquest plànol?",
|
||||
"confirm_delete_text": "Segur que vols eliminar aquest plànol?",
|
||||
"header": "Editor de plànols",
|
||||
"add_blueprint": "Importa blueprint",
|
||||
"confirm_delete_header": "Eliminar aquest blueprint?",
|
||||
"confirm_delete_text": "Segur que vols eliminar aquest blueprint?",
|
||||
"delete_blueprint": "Elimina blueprint",
|
||||
"discover_more": "Descobreix més blueprints",
|
||||
"header": "Editor de blueprints",
|
||||
"headers": {
|
||||
"domain": "Domini",
|
||||
"file_name": "Nom de l'arxiu",
|
||||
"name": "Nom"
|
||||
},
|
||||
"introduction": "L'editor de plànols et permet crear i editar plànols.",
|
||||
"learn_more": "Més informació sobre els plànols"
|
||||
"introduction": "La configuració dels blueprints et permet importar-ne i gestionar-los.",
|
||||
"learn_more": "Més informació sobre l'ús dels blueprints",
|
||||
"use_blueprint": "Crea automatització"
|
||||
}
|
||||
},
|
||||
"cloud": {
|
||||
@@ -1503,7 +1531,7 @@
|
||||
"title": "Alexa"
|
||||
},
|
||||
"caption": "Home Assistant Cloud",
|
||||
"description_features": "Controla la casa des de fora, pots integrar Alexa i Google Assistant.",
|
||||
"description_features": "Controla la casa quan siguis fora i integra-hi Alexa i Google Assistant",
|
||||
"description_login": "Sessió iniciada com a {email}",
|
||||
"description_not_login": "No has iniciat sessió",
|
||||
"dialog_certificate": {
|
||||
@@ -1598,7 +1626,7 @@
|
||||
},
|
||||
"core": {
|
||||
"caption": "General",
|
||||
"description": "Canvia la configuració general de Home Assistant",
|
||||
"description": "Sistema d'unitats, ubicació, zona horària i altres paràmetres generals",
|
||||
"section": {
|
||||
"core": {
|
||||
"core_config": {
|
||||
@@ -1660,6 +1688,7 @@
|
||||
"unknown_condition": "Condició desconeguda"
|
||||
},
|
||||
"create": "Crea una automatització amb el dispositiu",
|
||||
"create_disable": "No es pot crear una automatització amb dispositius desactivats",
|
||||
"no_automations": "No hi ha automatitzacions",
|
||||
"no_device_automations": "No hi ha automatitzacions disponibles per a aquest dispositiu.",
|
||||
"triggers": {
|
||||
@@ -1685,9 +1714,18 @@
|
||||
"no_devices": "Sense dispositius"
|
||||
},
|
||||
"delete": "Elimina",
|
||||
"description": "Gestiona els dispositius connectats",
|
||||
"description": "Gestiona els dispositius configurats",
|
||||
"device_info": "Informació del dispositiu",
|
||||
"device_not_found": "Dispositiu no trobat.",
|
||||
"disabled": "Desactivat",
|
||||
"disabled_by": {
|
||||
"config_entry": "Entrada de configuració",
|
||||
"integration": "Integració",
|
||||
"user": "Usuari"
|
||||
},
|
||||
"enabled_cause": "El dispositiu està desactivat per {cause}.",
|
||||
"enabled_description": "Els dispositius desactivats no es mostraran i les entitats que hi pertanyin es desactivaran i no s'afegiran a Home Assistant.",
|
||||
"enabled_label": "Activa dispositiu",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Afegeix a Lovelace",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {entitat desabilitada}\n other {entitats desabilitades}\n}",
|
||||
@@ -1697,14 +1735,25 @@
|
||||
},
|
||||
"name": "Nom",
|
||||
"no_devices": "No hi ha dispositius",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Filtre",
|
||||
"hidden_devices": "{number} {number, plural,\n one {dispositiu amagat}\n other {dispositius amagats}\n}",
|
||||
"show_all": "Mostra-ho tot",
|
||||
"show_disabled": "Mostra dispositius desactivats"
|
||||
},
|
||||
"search": "Cerca dispositius"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Crea una escena amb el dispositiu",
|
||||
"create_disable": "No es pot crear una escena amb dispositius desactivats",
|
||||
"no_scenes": "No hi ha escenes",
|
||||
"scenes": "Escenes"
|
||||
},
|
||||
"scenes": "Escenes",
|
||||
"script": {
|
||||
"create": "Crea un programa (script) amb el dispositiu",
|
||||
"create_disable": "No es pot crear un script amb dispositius desactivats",
|
||||
"no_scripts": "No hi ha scripts",
|
||||
"scripts": "Scripts"
|
||||
},
|
||||
@@ -1737,6 +1786,7 @@
|
||||
},
|
||||
"header": "Entitats",
|
||||
"headers": {
|
||||
"area": "Àrea",
|
||||
"entity_id": "ID de l'entitat",
|
||||
"integration": "Integració",
|
||||
"name": "Nom",
|
||||
@@ -1769,7 +1819,7 @@
|
||||
"header": "Configuració de Home Assistant",
|
||||
"helpers": {
|
||||
"caption": "Ajudants",
|
||||
"description": "Gestiona elements útils per a construir automatitzacions",
|
||||
"description": "Elements útils per a construir automatitzacions",
|
||||
"dialog": {
|
||||
"add_helper": "Afegeix ajudant",
|
||||
"add_platform": "Afegeix {platform}",
|
||||
@@ -1801,7 +1851,7 @@
|
||||
"copy_github": "Per GitHub",
|
||||
"copy_raw": "Text en brut",
|
||||
"custom_uis": "Interfícies d'usuari personalitzades:",
|
||||
"description": "Consulta informació de la teva instal·lació de Home Assistant",
|
||||
"description": "Versió, estat del sistema i enllaços a la documentació",
|
||||
"developed_by": "Desenvolupat per un munt de gent fantàstica.",
|
||||
"documentation": "Documentació",
|
||||
"frontend": "frontend-ui",
|
||||
@@ -1907,7 +1957,7 @@
|
||||
},
|
||||
"configure": "Configurar",
|
||||
"configured": "Configurades",
|
||||
"description": "Gestiona les integracions",
|
||||
"description": "Gestiona les integracions amb serveis, dispositius, ...",
|
||||
"details": "Detalls de la integració",
|
||||
"discovered": "Descobertes",
|
||||
"home_assistant_website": "lloc web de Home Assistant",
|
||||
@@ -1992,7 +2042,7 @@
|
||||
"open": "Obrir"
|
||||
}
|
||||
},
|
||||
"description": "Gestiona els teus panells Lovelace",
|
||||
"description": "Crea conjunts de panells personalitzats per controlar la teva casa",
|
||||
"resources": {
|
||||
"cant_edit_yaml": "Estàs utilitzant Lovelace en mode YAML per tant no pots gestionar els recursos des de la interfície d'usuari. Els pots gestionar des del fitxer 'configuration.yaml'.",
|
||||
"caption": "Recursos",
|
||||
@@ -2135,7 +2185,7 @@
|
||||
"refresh_node": {
|
||||
"battery_note": "Si el node funciona amb bateria, assegura't de que estigui actiu abans de continuar",
|
||||
"button": "Actualitza node",
|
||||
"complete": "Actualització del node completa",
|
||||
"complete": "Actualització del node completada",
|
||||
"description": "Això farà que OpenZWave torni a consultar el node i n'actualitzi les classes de comandes, funcions i valors.",
|
||||
"node_status": "Estat del node",
|
||||
"refreshing_description": "Actualitzant la informació del node...",
|
||||
@@ -2191,7 +2241,7 @@
|
||||
"scene": {
|
||||
"activated": "Escena {name} activada.",
|
||||
"caption": "Escenes",
|
||||
"description": "Gestiona les escenes",
|
||||
"description": "Captura els estats dels dispositius i recorda'ls més tard",
|
||||
"editor": {
|
||||
"default_name": "Nova escena",
|
||||
"devices": {
|
||||
@@ -2209,7 +2259,7 @@
|
||||
"without_device": "Entitats sense dispositiu"
|
||||
},
|
||||
"icon": "Icona",
|
||||
"introduction": "Utilitza les escenes per donar més vida a la teva llar.",
|
||||
"introduction": "Utilitza les escenes per donar més vida a la teva casa.",
|
||||
"load_error_not_editable": "Només es poden editar les escenes de l'arxiu scenes.yaml.",
|
||||
"load_error_unknown": "Error en carregar l'escena ({err_no}).",
|
||||
"name": "Nom",
|
||||
@@ -2235,7 +2285,7 @@
|
||||
},
|
||||
"script": {
|
||||
"caption": "Programació (scripts)",
|
||||
"description": "Gestiona els programes (scripts)",
|
||||
"description": "Executa una seqüència d'accions",
|
||||
"editor": {
|
||||
"alias": "Nom",
|
||||
"default_name": "Nou script",
|
||||
@@ -2346,7 +2396,7 @@
|
||||
"confirm_remove": "Estàs segur que vols eliminar l'etiqueta {tag}?",
|
||||
"confirm_remove_title": "Elimina l'etiqueta?",
|
||||
"create_automation": "Crea una automatització amb una etiqueta",
|
||||
"description": "Gestiona les etiquetes",
|
||||
"description": "Dispara automatitzacions quan una etiqueta NFC, un codi QR, etc; s'escanegi",
|
||||
"detail": {
|
||||
"companion_apps": "aplicacions de companion",
|
||||
"create": "Crea",
|
||||
@@ -2381,10 +2431,11 @@
|
||||
"username": "Nom d'usuari"
|
||||
},
|
||||
"caption": "Usuaris",
|
||||
"description": "Gestiona els usuaris",
|
||||
"description": "Gestiona els comptes d'usuari de Home Assistant",
|
||||
"editor": {
|
||||
"activate_user": "Activar usuari",
|
||||
"active": "Actiu",
|
||||
"active_tooltip": "Controla si l'usuari pot iniciar sessió",
|
||||
"admin": "Administrador",
|
||||
"caption": "Mostra usuari",
|
||||
"change_password": "Canviar contrasenya",
|
||||
@@ -2393,7 +2444,7 @@
|
||||
"delete_user": "Eliminar usuari",
|
||||
"group": "Grup",
|
||||
"id": "ID",
|
||||
"name": "Nom",
|
||||
"name": "Nom de visualització",
|
||||
"new_password": "Nova contrasenya",
|
||||
"owner": "Propietari",
|
||||
"password_changed": "La contrasenya s'ha canviat correctament",
|
||||
@@ -2401,19 +2452,24 @@
|
||||
"system_generated_users_not_editable": "No es poden actualitzar usuaris generats pel sistema.",
|
||||
"system_generated_users_not_removable": "No es poden eliminar usuaris generats pel sistema.",
|
||||
"unnamed_user": "Usuari sense nom",
|
||||
"update_user": "Actualitza"
|
||||
"update_user": "Actualitza",
|
||||
"username": "Nom d'usuari"
|
||||
},
|
||||
"picker": {
|
||||
"add_user": "Afegeix usuari",
|
||||
"headers": {
|
||||
"group": "Grup",
|
||||
"name": "Nom",
|
||||
"system": "Sistema"
|
||||
"is_active": "Actiu",
|
||||
"is_owner": "Propietari",
|
||||
"name": "Nom de visualització",
|
||||
"system": "Generat pel sistema",
|
||||
"username": "Nom d'usuari"
|
||||
}
|
||||
},
|
||||
"users_privileges_note": "El grup d'usuaris encara no està del tot acabat. L'usuari no podrà administrar la instància a través de la interfície d'usuari. Encara estem verificant tots els punts de l'API de gestió per assegurar-nos que limiten correctament l'accés als administradors."
|
||||
},
|
||||
"zha": {
|
||||
"add_device": "Afegeix dispositiu",
|
||||
"add_device_page": {
|
||||
"discovered_text": "Els dispositius apareixeran aquí un cop descoberts.",
|
||||
"discovery_text": "Els dispositius descoberts apareixeran aquí. Segueix les instruccions del/s teu/s dispositiu/s i posa el dispositiu/s en mode d'emparellament.",
|
||||
@@ -2459,6 +2515,16 @@
|
||||
"value": "Valor"
|
||||
},
|
||||
"description": "Gestiona la xarxa domòtica Zigbee (ZHA)",
|
||||
"device_pairing_card": {
|
||||
"CONFIGURED": "Configuració completada",
|
||||
"CONFIGURED_status_text": "Inicialitzant",
|
||||
"INITIALIZED": "Inicialització completada",
|
||||
"INITIALIZED_status_text": "El dispositiu està llest per a utilitzar-se",
|
||||
"INTERVIEW_COMPLETE": "Consulta completada",
|
||||
"INTERVIEW_COMPLETE_status_text": "Configurant",
|
||||
"PAIRED": "Dispositiu trobat",
|
||||
"PAIRED_status_text": "Iniciant consulta"
|
||||
},
|
||||
"devices": {
|
||||
"header": "Domòtica Zigbee (ZHA) - Dispositiu"
|
||||
},
|
||||
@@ -2474,6 +2540,7 @@
|
||||
"unbind_button_label": "Desvincula grup"
|
||||
},
|
||||
"groups": {
|
||||
"add_group": "Afegeix grup",
|
||||
"add_members": "Afegeix membres",
|
||||
"adding_members": "Afegint membres",
|
||||
"caption": "Grups",
|
||||
@@ -2516,7 +2583,11 @@
|
||||
"hint_wakeup": "Alguns dispositius com els sensors Xiaomi tenen un botó per despertar-los que pots prémer a intervals de 5 segons per mantenir-los desperts mentre hi interactues.",
|
||||
"introduction": "Executa comandes ZHA que afecten un sol dispositiu. Tria un dispositiu per veure el seu llistat de comandes disponibles."
|
||||
},
|
||||
"title": "Domòtica Zigbee (ZHA)"
|
||||
"title": "Domòtica Zigbee (ZHA)",
|
||||
"visualization": {
|
||||
"caption": "Visualització",
|
||||
"header": "Visualització de xarxa"
|
||||
}
|
||||
},
|
||||
"zone": {
|
||||
"add_zone": "Afegeix zona",
|
||||
@@ -3116,7 +3187,7 @@
|
||||
"close": "Tanca",
|
||||
"empty_config": "Comença amb un panell buit",
|
||||
"header": "Pren el control de la interfície d'usuari Lovelace",
|
||||
"para": "Aquest panell Lovelace s'està gestionant per Home Assistant. S'actualitza automàticament quan hi ha noves entitats o nous components de Lovelace disponibles. Si prens el control, aquest panell no s'actualitzarà automàticament. Sempre pots crear un nou panell a configuració i fer-hi proves.",
|
||||
"para": "Aquest panell Lovelace està gestionat per Home Assistant. S'actualitza automàticament quan hi ha noves entitats o nous components de Lovelace disponibles. Si prens el control, aquest panell no s'actualitzarà automàticament. Sempre pots crear un nou panell a configuració i fer-hi proves.",
|
||||
"para_sure": "Estàs segur que vols prendre el control de la interfície d'usuari?",
|
||||
"save": "Prendre el control",
|
||||
"yaml_config": "Per ajudar a familiaritzar-te, aquí tens la configuració actual del teu panell Lovelace:",
|
||||
@@ -3383,10 +3454,13 @@
|
||||
"change_password": {
|
||||
"confirm_new_password": "Confirmar contrasenya nova",
|
||||
"current_password": "Contrasenya actual",
|
||||
"error_new_is_old": "La contrasenya nova ha de ser diferent de la contrasenya actual",
|
||||
"error_new_mismatch": "Els valors introduïts de la nova contrasenya no coincideixen",
|
||||
"error_required": "Obligatori",
|
||||
"header": "Canvi de contrasenya",
|
||||
"new_password": "Contrasenya nova",
|
||||
"submit": "Envia"
|
||||
"submit": "Envia",
|
||||
"success": "La contrasenya s'ha canviat correctament"
|
||||
},
|
||||
"current_user": "Has iniciat la sessió com a {fullName}.",
|
||||
"customize_sidebar": {
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Položka nastavení",
|
||||
"device": "Zařízení",
|
||||
"integration": "Integrace",
|
||||
"user": "Uživatel"
|
||||
}
|
||||
@@ -546,11 +547,14 @@
|
||||
"add_new": "Přidat novou oblast ...",
|
||||
"area": "Oblast",
|
||||
"clear": "Vymazat",
|
||||
"no_areas": "Nemáte žádné oblasti",
|
||||
"no_match": "Nebyly nalezeny žádné odpovídající oblasti",
|
||||
"show_areas": "Zobrazit oblasti"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
"add_user": "Přidat uživatele",
|
||||
"remove_user": "Odebrat uživatele"
|
||||
"remove_user": "Odebrat uživatele",
|
||||
"select_blueprint": "Vyberte šablonu"
|
||||
},
|
||||
"data-table": {
|
||||
"no-data": "Žádná data",
|
||||
@@ -565,6 +569,8 @@
|
||||
"clear": "Zrušit",
|
||||
"device": "Zařízení",
|
||||
"no_area": "Žádná oblast",
|
||||
"no_devices": "Nemáte žádná zařízení",
|
||||
"no_match": "Nebyla nalezena žádná odpovídající zařízení",
|
||||
"show_devices": "Zobrazit zařízení",
|
||||
"toggle": "Přepnout"
|
||||
},
|
||||
@@ -576,6 +582,7 @@
|
||||
"entity-picker": {
|
||||
"clear": "Zrušit",
|
||||
"entity": "Entita",
|
||||
"no_match": "Nebyly nalezeny žádné odpovídající entity",
|
||||
"show_entities": "Zobrazit entity"
|
||||
}
|
||||
},
|
||||
@@ -709,6 +716,16 @@
|
||||
"service-picker": {
|
||||
"service": "Služba"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_area_id": "Vyberte oblast",
|
||||
"add_device_id": "Vyberte zařízení",
|
||||
"add_entity_id": "Vyberte entitu",
|
||||
"expand_area_id": "Rozdělit tuto oblast na jednotlivá zařízení a entity, které obsahuje. Po rozdělení nebudou zařízení a entity aktualizovány, pokud dojde ke změnám oblasti.",
|
||||
"expand_device_id": "Rozdělit toto zařízení na jednotlivé entity. Po rozdělení nebudou entity aktualizovány, pokud dojde ke změnám zařízení.",
|
||||
"remove_area_id": "Odebrat oblast",
|
||||
"remove_device_id": "Odebrat zařízení",
|
||||
"remove_entity_id": "Odebrat entitu"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Přidat uživatele",
|
||||
"no_user": "Žádný uživatel",
|
||||
@@ -732,6 +749,7 @@
|
||||
"editor": {
|
||||
"confirm_delete": "Opravdu chcete tuto položku smazat?",
|
||||
"delete": "Odstranit",
|
||||
"device_disabled": "Zařízení této entity je zakázáno.",
|
||||
"enabled_cause": "Zakázáno {cause}.",
|
||||
"enabled_delay_confirm": "Povolené entity budou přidány do Home Assistant za {delay} sekund",
|
||||
"enabled_description": "Zakázané entity nebudou přidány do Home Assistant.",
|
||||
@@ -742,6 +760,7 @@
|
||||
"icon_error": "Ikony by měly být ve formátu 'prefix:nazevikony', např. 'mdi:home'",
|
||||
"name": "Jméno",
|
||||
"note": "Poznámka: U všech integrací to ještě nemusí fungovat.",
|
||||
"open_device_settings": "Otevřít nastavení zařízení",
|
||||
"unavailable": "Tato entita není momentálně k dispozici.",
|
||||
"update": "Aktualizovat"
|
||||
},
|
||||
@@ -882,6 +901,7 @@
|
||||
"navigation": {
|
||||
"areas": "Oblasti",
|
||||
"automation": "Automatizace",
|
||||
"blueprint": "Šablony",
|
||||
"core": "Obecné",
|
||||
"customize": "Přizpůsobení",
|
||||
"devices": "Zařízení",
|
||||
@@ -890,7 +910,7 @@
|
||||
"info": "Informace",
|
||||
"integrations": "Integrace",
|
||||
"logs": "Logy",
|
||||
"lovelace": "Lovelace Dashboardy",
|
||||
"lovelace": "Ovládací panely Lovelace",
|
||||
"navigate_to": "Přejít na {panel}",
|
||||
"navigate_to_config": "Přejít na nastavení {panel}",
|
||||
"person": "Osoby",
|
||||
@@ -953,7 +973,7 @@
|
||||
"zha_device_info": {
|
||||
"buttons": {
|
||||
"add": "Přidejte zařízení prostřednictvím tohoto zařízení",
|
||||
"clusters": "Clustery",
|
||||
"clusters": "Správa clusterů",
|
||||
"reconfigure": "Přenastavit zařízení",
|
||||
"remove": "Odebrat zařízení",
|
||||
"zigbee_information": "Podpis zařízení Zigbee"
|
||||
@@ -1028,7 +1048,7 @@
|
||||
"confirmation_text": "Všechna zařízení v této oblasti budou nastavena jako nepřiřazena.",
|
||||
"confirmation_title": "Opravdu chcete tuto oblast smazat?"
|
||||
},
|
||||
"description": "Správa oblastí ve vaší domácnosti",
|
||||
"description": "Seskupte zařízení a entity do oblastí",
|
||||
"editor": {
|
||||
"area_id": "ID oblasti",
|
||||
"create": "VYTVOŘIT",
|
||||
@@ -1050,11 +1070,14 @@
|
||||
},
|
||||
"automation": {
|
||||
"caption": "Automatizace",
|
||||
"description": "Správa automatizací",
|
||||
"description": "Vytvořte si pro svůj domov vlastní pravidla chování",
|
||||
"dialog_new": {
|
||||
"blueprint": {
|
||||
"use_blueprint": "Použít šablonu"
|
||||
},
|
||||
"header": "Vytvoření automatizace",
|
||||
"how": "Jak chcete vytvořit svou novou automatizaci?",
|
||||
"start_empty": "Začněte s prázdnou automatizací",
|
||||
"start_empty": "Začít s prázdnou automatizací",
|
||||
"thingtalk": {
|
||||
"create": "Vytvořit",
|
||||
"header": "Popište automatizaci, kterou chcete vytvořit",
|
||||
@@ -1087,8 +1110,8 @@
|
||||
"label": "Stav"
|
||||
},
|
||||
"delay": {
|
||||
"delay": "Zpoždění",
|
||||
"label": "Zpoždění"
|
||||
"delay": "Pozdržení",
|
||||
"label": "Pozdržení"
|
||||
},
|
||||
"device_id": {
|
||||
"action": "Akce",
|
||||
@@ -1143,7 +1166,12 @@
|
||||
},
|
||||
"alias": "Název",
|
||||
"blueprint": {
|
||||
"inputs": "Vstupy"
|
||||
"blueprint_to_use": "Šablona k použití",
|
||||
"header": "Šablona",
|
||||
"inputs": "Vstupy",
|
||||
"manage_blueprints": "Správa šablon",
|
||||
"no_blueprints": "Nemáme žádné šablony",
|
||||
"no_inputs": "Šablona nemá žádné vstupy."
|
||||
},
|
||||
"conditions": {
|
||||
"add": "Přidat podmínku",
|
||||
@@ -1389,24 +1417,38 @@
|
||||
},
|
||||
"blueprint": {
|
||||
"add": {
|
||||
"error_no_url": "Zadejte adresu URL šablonky konfigurace",
|
||||
"header": "Přidat novou šablonku konfigurace",
|
||||
"import_btn": "Importovat šablonku konfigurace",
|
||||
"import_header": "Importovat \"{name}\" (typ: {domain})",
|
||||
"import_introduction": "Z Githubu a komunitních fór můžete importovat šablonky konfigurace sdílené ostatními uživateli. Zadejte adresu URL šablonky konfigurace.",
|
||||
"importing": "Importuje se šablonka konfigurace",
|
||||
"save_btn": "Uložit šablonku konfigurace",
|
||||
"saving": "Ukládání konfigurační šablonky",
|
||||
"url": "URL šablonky konfigurace"
|
||||
"community_forums": "komunitních fór",
|
||||
"error_no_url": "Zadejte adresu URL adresu šablony",
|
||||
"file_name": "Cesta k šabloně",
|
||||
"header": "Import šablony",
|
||||
"import_btn": "Náhled šablony",
|
||||
"import_header": "Šablona \"{name}\"",
|
||||
"import_introduction": "Můžete importovat šablony od ostatních uživatelů z GitHubu a komunitních fór. Níže zadejte URL adresu šablony.",
|
||||
"import_introduction_link": "Můžete importovat šablony od ostatních uživatelů z GitHubu a {community_link}. Níže zadejte URL adresu šablony.",
|
||||
"importing": "Načítám šablonu...",
|
||||
"raw_blueprint": "Obsah šablony",
|
||||
"save_btn": "Importovat šablonu",
|
||||
"saving": "Importuji šablonu...",
|
||||
"unsupported_blueprint": "Tato šablona není podporována.",
|
||||
"url": "URL adresa šablony"
|
||||
},
|
||||
"caption": "Šablony",
|
||||
"description": "Správa šablon",
|
||||
"overview": {
|
||||
"confirm_delete_header": "Odstranit tuto šablonku konfigurace?",
|
||||
"add_blueprint": "Import šablony",
|
||||
"confirm_delete_header": "Odstranit tuto šablonu?",
|
||||
"confirm_delete_text": "Opravdu chcete smazat tuto šablonu?",
|
||||
"delete_blueprint": "Smazat šablonu",
|
||||
"discover_more": "Objevte další šablony",
|
||||
"header": "Editor šablon",
|
||||
"headers": {
|
||||
"domain": "Doména",
|
||||
"file_name": "Název souboru",
|
||||
"name": "Jméno"
|
||||
},
|
||||
"learn_more": "Další informace o šablonkách konfigurace"
|
||||
"introduction": "Nastavení šablon vám umožňuje importovat a spravovat vaše šablony.",
|
||||
"learn_more": "Další informace o používání šablon",
|
||||
"use_blueprint": "Vytvořit automatizaci"
|
||||
}
|
||||
},
|
||||
"cloud": {
|
||||
@@ -1419,7 +1461,7 @@
|
||||
"enable_state_reporting": "Povolit hlášení stavu",
|
||||
"info": "Díky integraci Alexa pro Home Assistant Cloud budete moci ovládat všechna zařízení v Home Assistant pomocí jakéhokoli zařízení podporujícího Alexa.",
|
||||
"info_state_reporting": "Pokud povolíte hlášení stavu, Home Assistant bude posílat veškeré změny stavů všech exponovaných entit do Amazonu. Toto vám umožní sledovat aktuální stavy entity v aplikaci Alexa a použít tyto stavy k vytvoření rutin.",
|
||||
"manage_entities": "Spravovat entity",
|
||||
"manage_entities": "Správa entit",
|
||||
"state_reporting_error": "Nelze {enable_disable} hlášení stavu.",
|
||||
"sync_entities": "Synchronizovat entity",
|
||||
"sync_entities_error": "Chyba při synchronizaci entit:",
|
||||
@@ -1448,7 +1490,7 @@
|
||||
"integrations_introduction": "Integrace pro Home Assistant Cloud vám umožní připojit se ke cloudovým službám, aniž byste museli veřejně zpřístupnit vaší instanci Home Assistant na internetu.",
|
||||
"integrations_introduction2": "Na webových stránkách najdete ",
|
||||
"integrations_link_all_features": " všechny dostupné funkce",
|
||||
"manage_account": "Spravovat účet",
|
||||
"manage_account": "Správa účtu",
|
||||
"nabu_casa_account": "Účet Nabu Casa",
|
||||
"not_connected": "Není připojeno",
|
||||
"remote": {
|
||||
@@ -1489,7 +1531,7 @@
|
||||
"title": "Alexa"
|
||||
},
|
||||
"caption": "Home Assistant Cloud",
|
||||
"description_features": "Ovládejte vzdáleně, integrace s Alexou a Google Assistant.",
|
||||
"description_features": "Ovládejte, i když nejste doma, a propojte s Alexou a Google Assistantem",
|
||||
"description_login": "Přihlášen jako {email}",
|
||||
"description_not_login": "Nepřihlášen",
|
||||
"dialog_certificate": {
|
||||
@@ -1584,7 +1626,7 @@
|
||||
},
|
||||
"core": {
|
||||
"caption": "Obecné",
|
||||
"description": "Změny obecného nastavení Home Assistant",
|
||||
"description": "Jednotkový systém, umístění, časové pásmo a další obecné parametry",
|
||||
"section": {
|
||||
"core": {
|
||||
"core_config": {
|
||||
@@ -1646,6 +1688,7 @@
|
||||
"unknown_condition": "Neznámá podmínka"
|
||||
},
|
||||
"create": "Vytvořit automatizaci se zařízením",
|
||||
"create_disable": "Nelze vytvořit automatizaci se zakázaným zařízením",
|
||||
"no_automations": "Žádné automatizace",
|
||||
"no_device_automations": "Pro toto zařízení nejsou k dispozici žádné automatizace.",
|
||||
"triggers": {
|
||||
@@ -1659,7 +1702,7 @@
|
||||
"caption": "Zařízení",
|
||||
"confirm_delete": "Opravdu chcete toto zařízení odstranit?",
|
||||
"confirm_rename_entity_ids": "Chcete také přejmenovat ID entit?",
|
||||
"confirm_rename_entity_ids_warning": "Žádná nastavení (např. automatizace, skripty, scény, dashboardy), která tyto entity aktuálně používá, nebudou změněna! Vše budete muset aktualizovat sami, aby se používaly nová ID entit!",
|
||||
"confirm_rename_entity_ids_warning": "Žádná nastavení (např. automatizace, skripty, scény, ovládací panely), která tyto entity aktuálně používá, nebudou změněna! Vše budete muset aktualizovat sami, aby se používaly nová ID entit!",
|
||||
"data_table": {
|
||||
"area": "Oblast",
|
||||
"battery": "Baterie",
|
||||
@@ -1674,6 +1717,15 @@
|
||||
"description": "Správa připojených zařízení",
|
||||
"device_info": "Informace o zařízení",
|
||||
"device_not_found": "Zařízení nebylo nalezeno.",
|
||||
"disabled": "Zakázáno",
|
||||
"disabled_by": {
|
||||
"config_entry": "Položka nastavení",
|
||||
"integration": "Integrace",
|
||||
"user": "Uživatel"
|
||||
},
|
||||
"enabled_cause": "Zařízení je zakázáno přes {cause}.",
|
||||
"enabled_description": "Zakázaná zařízení se nebudou zobrazovat a entity patřící k těmto zařízením budou zakázány a nebudou přidány do Home Assistant.",
|
||||
"enabled_label": "Povolit zařízení",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Přidat do Lovelace",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {zakázaná entita}\n other {zakázaných entit}\n}",
|
||||
@@ -1683,14 +1735,25 @@
|
||||
},
|
||||
"name": "Jméno",
|
||||
"no_devices": "Žádná zařízení",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Filtrovat",
|
||||
"hidden_devices": "{number} {number, plural,\n one {skryté zařízení}\n few {skrytá zařízení}\n other {skrytých zařízení}\n}",
|
||||
"show_all": "Zobrazit vše",
|
||||
"show_disabled": "Zobrazit zakázaná zařízení"
|
||||
},
|
||||
"search": "Hledat zařízení"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Vytvořit scénu se zařízením",
|
||||
"create_disable": "Nelze vytvořit scénu se zakázaným zařízením",
|
||||
"no_scenes": "Žádné scény",
|
||||
"scenes": "Scény"
|
||||
},
|
||||
"scenes": "Scény",
|
||||
"script": {
|
||||
"create": "Vytvořit skript se zařízením",
|
||||
"create_disable": "Nelze vytvořit skript se zakázaným zařízením",
|
||||
"no_scripts": "Žádné skripty",
|
||||
"scripts": "Skripty"
|
||||
},
|
||||
@@ -1756,7 +1819,7 @@
|
||||
"header": "Nastavení Home Assistant",
|
||||
"helpers": {
|
||||
"caption": "Pomocníci",
|
||||
"description": "Správa prvků, které mohou pomoci při vytváření automatizací",
|
||||
"description": "Prvky, které pomáhají vytvářet automatizace",
|
||||
"dialog": {
|
||||
"add_helper": "Přidat pomocníka",
|
||||
"add_platform": "Přidat {platform}",
|
||||
@@ -1774,7 +1837,7 @@
|
||||
},
|
||||
"types": {
|
||||
"counter": "Počítadlo",
|
||||
"input_boolean": "Přepnout",
|
||||
"input_boolean": "Přepínač",
|
||||
"input_datetime": "Datum a/nebo čas",
|
||||
"input_number": "Číslo",
|
||||
"input_select": "Výběr",
|
||||
@@ -1788,7 +1851,7 @@
|
||||
"copy_github": "Pro GitHub",
|
||||
"copy_raw": "Nezpracovaný text",
|
||||
"custom_uis": "Vlastní uživatelská rozhraní:",
|
||||
"description": "Informace o instalaci Home Assistant",
|
||||
"description": "Verze, stav systému a odkazy na dokumentaci",
|
||||
"developed_by": "Vyvinuto partou úžasných lidí.",
|
||||
"documentation": "Dokumentace",
|
||||
"frontend": "frontend-ui",
|
||||
@@ -1830,7 +1893,7 @@
|
||||
"virtualenv": "Virtuální prostředí"
|
||||
},
|
||||
"lovelace": {
|
||||
"dashboards": "Dashboardy",
|
||||
"dashboards": "Ovládací panely",
|
||||
"mode": "Režim",
|
||||
"resources": "Zdroje"
|
||||
}
|
||||
@@ -1894,7 +1957,7 @@
|
||||
},
|
||||
"configure": "Nastavit",
|
||||
"configured": "Nastaveno",
|
||||
"description": "Správa integrací",
|
||||
"description": "Správa integrací a jejich služeb, zařízení, ...",
|
||||
"details": "Podrobnosti o integraci",
|
||||
"discovered": "Objeveno",
|
||||
"home_assistant_website": "stránky Home Assistant",
|
||||
@@ -1938,24 +2001,24 @@
|
||||
"title": "Logy"
|
||||
},
|
||||
"lovelace": {
|
||||
"caption": "Lovelace Dashboardy",
|
||||
"caption": "Ovládací panely Lovelace",
|
||||
"dashboards": {
|
||||
"cant_edit_default": "Standardní Lovelace dashboard nelze upravovat z uživatelského rozhraní. Můžete jej skrýt nastavením jiného dashboardu jako výchozího.",
|
||||
"cant_edit_yaml": "Dashboardy definované v YAML nelze upravovat z uživatelského rozhraní. Změňte je v configuration.yaml.",
|
||||
"caption": "Dashboardy",
|
||||
"cant_edit_default": "Standardní ovládací panel Lovelace nelze upravovat z uživatelského rozhraní. Můžete jej skrýt nastavením jiného ovládacího panelu jako výchozího.",
|
||||
"cant_edit_yaml": "Ovládací panely definované v YAML nelze upravovat z uživatelského rozhraní. Změňte je v configuration.yaml.",
|
||||
"caption": "Ovládací panely",
|
||||
"conf_mode": {
|
||||
"storage": "Řízeno uživatelským rozhraním",
|
||||
"yaml": "Soubor YAML"
|
||||
},
|
||||
"confirm_delete": "Opravdu chcete odstranit tento dashboard?",
|
||||
"default_dashboard": "Toto je výchozí dashboard",
|
||||
"confirm_delete": "Opravdu chcete odstranit tento ovládací panel?",
|
||||
"default_dashboard": "Toto je výchozí ovládací panel",
|
||||
"detail": {
|
||||
"create": "Vytvořit",
|
||||
"delete": "Smazat",
|
||||
"dismiss": "Zavřít",
|
||||
"edit_dashboard": "Upravit dashboard",
|
||||
"edit_dashboard": "Upravit ovládací panel",
|
||||
"icon": "Ikona",
|
||||
"new_dashboard": "Přidat nový dashboard",
|
||||
"new_dashboard": "Přidat nový ovládací panel",
|
||||
"remove_default": "Odebrat jako výchozí na tomto zařízení",
|
||||
"require_admin": "Pouze správce",
|
||||
"set_default": "Nastavit jako výchozí na tomto zařízení",
|
||||
@@ -1967,7 +2030,7 @@
|
||||
"url_error_msg": "Adresa URL by měla obsahovat - a nesmí obsahovat mezery ani speciální znaky, s výjimkou _ a -"
|
||||
},
|
||||
"picker": {
|
||||
"add_dashboard": "Přidat dashboard",
|
||||
"add_dashboard": "Přidat ovládací panel",
|
||||
"headers": {
|
||||
"conf_mode": "Metoda nastavení",
|
||||
"default": "Výchozí",
|
||||
@@ -1979,7 +2042,7 @@
|
||||
"open": "Otevřít"
|
||||
}
|
||||
},
|
||||
"description": "Správa Lovelace Dashboardů",
|
||||
"description": "Vytvořte vlastní sady karet pro ovládání svého domova",
|
||||
"resources": {
|
||||
"cant_edit_yaml": "Používáte Lovelace v režimu YAML, proto nemůžete spravovat své zdroje prostřednictvím uživatelského rozhraní. Spravujte je v souboru configuration.yaml.",
|
||||
"caption": "Zdroje",
|
||||
@@ -2020,7 +2083,7 @@
|
||||
"description_publish": "Publikovat paket",
|
||||
"listening_to": "Naslouchám",
|
||||
"message_received": "Zpráva {id} přijata na {topic} v {time} :",
|
||||
"payload": "Obsah",
|
||||
"payload": "Obsah (povolena šablona)",
|
||||
"publish": "Publikovat",
|
||||
"start_listening": "Začít naslouchat",
|
||||
"stop_listening": "Přestat naslouchat",
|
||||
@@ -2049,7 +2112,7 @@
|
||||
"network": "Síť",
|
||||
"node": {
|
||||
"config": "Nastavení",
|
||||
"dashboard": "Dashboard"
|
||||
"dashboard": "Ovládací panel"
|
||||
},
|
||||
"nodes": "Uzly",
|
||||
"select_instance": "Vyberte instanci"
|
||||
@@ -2082,7 +2145,7 @@
|
||||
"node_config": {
|
||||
"header": "Nastavení uzlu",
|
||||
"help_source": "Popisy parametrů nastavení a text nápovědy poskytuje projekt OpenZWave.",
|
||||
"introduction": "Spravujte různé parametry nastavení uzlu Z-Wave.",
|
||||
"introduction": "Správa různých parametrů nastavení uzlu Z-Wave.",
|
||||
"wakeup_help": "Uzly napájené z baterie musí být vzhůru, aby mohly změnit své nastavení. Pokud uzel není vzhůru, OpenZWave se pokusí aktualizovat nastavení uzlu při příštím probuzení, což může být o několik hodin (nebo dní) později. Zařízení probudíte takto:"
|
||||
},
|
||||
"node_metadata": {
|
||||
@@ -2178,7 +2241,7 @@
|
||||
"scene": {
|
||||
"activated": "Aktivovaná scéna {name}.",
|
||||
"caption": "Scény",
|
||||
"description": "Správa scén",
|
||||
"description": "Zachyťte stavy zařízení a snadno je později vyvolejte",
|
||||
"editor": {
|
||||
"default_name": "Nová scéna",
|
||||
"devices": {
|
||||
@@ -2222,7 +2285,7 @@
|
||||
},
|
||||
"script": {
|
||||
"caption": "Skripty",
|
||||
"description": "Správa skriptů",
|
||||
"description": "Provádějte posloupnosti akcí",
|
||||
"editor": {
|
||||
"alias": "Název",
|
||||
"default_name": "Nový skript",
|
||||
@@ -2283,7 +2346,7 @@
|
||||
"generic": "Nově načíst entity integrace Generic IP camera",
|
||||
"generic_thermostat": "Nově načíst entity integrace Generic thermostat",
|
||||
"group": "Nově načíst skupiny, skupiny entit a notifikační služby",
|
||||
"heading": "Nastavení z YAML se načítá",
|
||||
"heading": "Nové načtení YAML konfigurace",
|
||||
"history_stats": "Nově načíst entity integrace History stats",
|
||||
"homekit": "Nově načíst entity integrace HomeKit",
|
||||
"input_boolean": "Nově načíst pomocníky - přepínače",
|
||||
@@ -2333,7 +2396,7 @@
|
||||
"confirm_remove": "Opravdu chcete odebrat štítek {tag}?",
|
||||
"confirm_remove_title": "Odebrat štítek?",
|
||||
"create_automation": "Vytvořit automatizaci se štítkem",
|
||||
"description": "Správa štítků",
|
||||
"description": "Spusťte automatizaci skenováním NFC tagu, QR kódu atd.",
|
||||
"detail": {
|
||||
"companion_apps": "doprovodné aplikace",
|
||||
"create": "Vytvořit",
|
||||
@@ -2368,10 +2431,11 @@
|
||||
"username": "Uživatelské jméno"
|
||||
},
|
||||
"caption": "Uživatelé",
|
||||
"description": "Správa uživatelů",
|
||||
"description": "Správa uživatelských účtů pro Home Assistant",
|
||||
"editor": {
|
||||
"activate_user": "Aktivovat uživatele",
|
||||
"active": "Aktivní",
|
||||
"active_tooltip": "Určuje, zda se uživatel může přihlásit",
|
||||
"admin": "Administrátor",
|
||||
"caption": "Zobrazit uživatele",
|
||||
"change_password": "Změnit heslo",
|
||||
@@ -2564,7 +2628,7 @@
|
||||
"value": "Hodnota",
|
||||
"wakeup_interval": "Interval probuzení"
|
||||
},
|
||||
"description": "Spravujte svou síť Z-Wave",
|
||||
"description": "Správa síťě Z-Wave",
|
||||
"learn_more": "Další informace o Z-Wave",
|
||||
"network_management": {
|
||||
"header": "Správa sítě Z-Wave",
|
||||
@@ -2703,11 +2767,11 @@
|
||||
},
|
||||
"templates": {
|
||||
"all_listeners": "Tato šablona naslouchá všem změnám stavu.",
|
||||
"description": "Šablony jsou vykreslovány pomocí Jinja2 šablonového enginu s některými specifickými rozšířeními pro Home Assistant.",
|
||||
"description": "Šablony jsou vykreslovány pomocí šablonovacího systému Jinja2 s některými specifickými rozšířeními pro Home Assistant.",
|
||||
"domain": "Doména",
|
||||
"editor": "Editor šablon",
|
||||
"entity": "Entita",
|
||||
"jinja_documentation": "Dokumentace šablony Jinja2",
|
||||
"jinja_documentation": "Dokumentace šablon Jinja2",
|
||||
"listeners": "Tato šablona naslouchá následujícím změnám stavu:",
|
||||
"no_listeners": "Tato šablona nenaslouchá žádným událostem a nebude automaticky aktualizována.",
|
||||
"reset": "Obnovit ukázkovou šablonu",
|
||||
@@ -2715,7 +2779,7 @@
|
||||
"template_extensions": "Rozšíření šablony Home Assistant",
|
||||
"time": "Tato šablona se aktualizuje na začátku každé minuty.",
|
||||
"title": "Šablony",
|
||||
"unknown_error_template": "Šablona vykreslování neznámých chyb"
|
||||
"unknown_error_template": "Neznámá chyba při vykreslení šablony"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2780,7 +2844,7 @@
|
||||
}
|
||||
},
|
||||
"changed_toast": {
|
||||
"message": "Nastavení Lovelace pro tento dashboard bylo aktualizováno. Chcete obnovit stránku?",
|
||||
"message": "Nastavení Lovelace pro tento ovládací panel bylo aktualizováno. Chcete obnovit stránku?",
|
||||
"refresh": "Obnovit"
|
||||
},
|
||||
"editor": {
|
||||
@@ -3121,17 +3185,17 @@
|
||||
"save_config": {
|
||||
"cancel": "Zahodit změnu",
|
||||
"close": "Zavřít",
|
||||
"empty_config": "Začít s prázdným dashboardem",
|
||||
"empty_config": "Začít s prázdným ovládacím panel",
|
||||
"header": "Převzít kontrolu nad vaší Lovelace UI",
|
||||
"para": "Tento dashboard momentálně spravuje Home Assistant. Je automaticky aktualizován při přidání nové entity nebo Lovelace komponenty. Pokud převezmete kontrolu, nebudeme již provádět změny automaticky za vás. Vždy si můžete vytvořit nový dashboard na hraní.",
|
||||
"para": "Tento ovládací panel momentálně spravuje Home Assistant. Je automaticky aktualizován při přidání nové entity nebo Lovelace komponenty. Pokud převezmete kontrolu, nebudeme již provádět změny automaticky za vás. Vždy si můžete vytvořit nový ovládací panel na hraní.",
|
||||
"para_sure": "Opravdu chcete převzít kontrolu nad uživalským rozhraním ?",
|
||||
"save": "Převzít kontrolu",
|
||||
"yaml_config": "Abyste mohli snadněji začít, zde je aktuální nastavení tohoto dashboardu:",
|
||||
"yaml_control": "Chcete-li převzít kontrolu v režimu YAML, vytvořte soubor YAML s názvem, který jste uvedli ve svém nastavení pro tento dashboard, nebo výchozí \"ui-lovelace.yaml\".",
|
||||
"yaml_config": "Abyste mohli snadněji začít, zde je aktuální nastavení tohoto ovládacího panelu:",
|
||||
"yaml_control": "Chcete-li převzít kontrolu v režimu YAML, vytvořte soubor YAML s názvem, který jste uvedli ve svém nastavení pro tento ovládací panel, nebo výchozí \"ui-lovelace.yaml\".",
|
||||
"yaml_mode": "Používáte režim YAML, což znamená, že nemůžete změnit nastavení Lovelace z uživatelského rozhraní. Pokud chcete měnit Lovelace z uživatelského rozhraní, odstraňte \"mode: yaml\" z vašeho nastavení Lovelace v \"configuration.yaml\"."
|
||||
},
|
||||
"select_view": {
|
||||
"dashboard_label": "Dashboard",
|
||||
"dashboard_label": "Ovládací panel",
|
||||
"header": "Vyberte pohled"
|
||||
},
|
||||
"sub-element-editor": {
|
||||
@@ -3156,7 +3220,7 @@
|
||||
},
|
||||
"menu": {
|
||||
"close": "Zavřít",
|
||||
"configure_ui": "Upravit Dashboard",
|
||||
"configure_ui": "Upravit ovládací panel",
|
||||
"exit_edit_mode": "Ukončit režim úprav uživatelského rozhraní",
|
||||
"help": "Nápověda",
|
||||
"refresh": "Obnovit",
|
||||
@@ -3390,10 +3454,13 @@
|
||||
"change_password": {
|
||||
"confirm_new_password": "Potvrďte nové heslo",
|
||||
"current_password": "Současné heslo",
|
||||
"error_new_is_old": "Nové heslo se musí lišit od aktuálního hesla",
|
||||
"error_new_mismatch": "Zadaná nová hesla se neshodují",
|
||||
"error_required": "Povinný",
|
||||
"header": "Změnit heslo",
|
||||
"new_password": "Nové heslo",
|
||||
"submit": "Odeslat"
|
||||
"submit": "Odeslat",
|
||||
"success": "Heslo bylo úspěšně změněno"
|
||||
},
|
||||
"current_user": "Nyní jste přihlášeni jako {fullName}.",
|
||||
"customize_sidebar": {
|
||||
@@ -3402,9 +3469,9 @@
|
||||
"header": "Změna pořadí a skrytí položek postranního panelu"
|
||||
},
|
||||
"dashboard": {
|
||||
"description": "Vyberte výchozí dashboard pro toto zařízení.",
|
||||
"dropdown_label": "Dashboard",
|
||||
"header": "Dashboard"
|
||||
"description": "Vyberte výchozí ovládací panel pro toto zařízení.",
|
||||
"dropdown_label": "Ovládací panel",
|
||||
"header": "Ovládací panel"
|
||||
},
|
||||
"enable_shortcuts": {
|
||||
"description": "Povolte nebo zakažte klávesové zkratky pro provádění různých akcí v uživatelském rozhraní.",
|
||||
|
@@ -2,11 +2,13 @@
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Konfigurationstilstand",
|
||||
"device": "Enhed",
|
||||
"integration": "Integration",
|
||||
"user": "Bruger"
|
||||
}
|
||||
},
|
||||
"groups": {
|
||||
"owner": "Ejer",
|
||||
"system-admin": "Administratorer",
|
||||
"system-read-only": "Skrivebeskyttede brugere",
|
||||
"system-users": "Brugere"
|
||||
@@ -501,6 +503,8 @@
|
||||
"continue": "Fortsæt",
|
||||
"copied": "Kopieret",
|
||||
"delete": "Slet",
|
||||
"disable": "Deaktiver",
|
||||
"enable": "Aktiver",
|
||||
"error_required": "Påkrævet",
|
||||
"loading": "Indlæser",
|
||||
"menu": "Menu",
|
||||
@@ -509,6 +513,8 @@
|
||||
"overflow_menu": "Overløbsmenu",
|
||||
"previous": "Forrige",
|
||||
"refresh": "Opdater",
|
||||
"remove": "Fjern",
|
||||
"rename": "Omdøb",
|
||||
"save": "Gem",
|
||||
"successfully_deleted": "Slettet",
|
||||
"successfully_saved": "Gemt",
|
||||
@@ -529,6 +535,10 @@
|
||||
"clear": "Ryd",
|
||||
"show_areas": "Vis områder"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
"add_user": "Tilføj bruger",
|
||||
"remove_user": "Fjern bruger"
|
||||
},
|
||||
"data-table": {
|
||||
"no-data": "Ingen data",
|
||||
"search": "Søg"
|
||||
@@ -542,6 +552,7 @@
|
||||
"clear": "Ryd",
|
||||
"device": "Enhed",
|
||||
"no_area": "Intet område",
|
||||
"no_devices": "Du har ingen enheder",
|
||||
"show_devices": "Vis enheder",
|
||||
"toggle": "Til/fra"
|
||||
},
|
||||
@@ -618,6 +629,10 @@
|
||||
"service-picker": {
|
||||
"service": "Tjeneste"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_device_id": "Vælg enhed",
|
||||
"remove_device_id": "Fjern enhed"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Tilføj bruger",
|
||||
"no_user": "Ingen bruger",
|
||||
@@ -759,6 +774,15 @@
|
||||
"description": "Indstillingerne blev gemt."
|
||||
}
|
||||
},
|
||||
"quick-bar": {
|
||||
"commands": {
|
||||
"server_control": {
|
||||
"perform_action": "{action} server",
|
||||
"restart": "Genstart",
|
||||
"stop": "Stop"
|
||||
}
|
||||
}
|
||||
},
|
||||
"voice_command": {
|
||||
"did_not_hear": "Home Assistant hørte ikke noget",
|
||||
"error": "Ups, der er opstået en fejl",
|
||||
@@ -867,6 +891,14 @@
|
||||
"automation": {
|
||||
"caption": "Automatiseringer",
|
||||
"description": "Administrer automatiseringer",
|
||||
"dialog_new": {
|
||||
"thingtalk": {
|
||||
"create": "Opret",
|
||||
"header": "Beskriv automationen du vil lave",
|
||||
"input_label": "Hvad skal denne automation gøre?",
|
||||
"intro": "Og vi vil forsøge at skabe den for dig. For eksempel: Sluk lyset, når jeg forlader hjemmet."
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"actions": {
|
||||
"add": "Tilføj handling",
|
||||
@@ -1006,6 +1038,7 @@
|
||||
},
|
||||
"unsupported_condition": "Ikke-understøttet betingelse: {condition}"
|
||||
},
|
||||
"copy_to_clipboard": "Kopier til udklipsholder",
|
||||
"default_name": "Ny automatisering",
|
||||
"description": {
|
||||
"label": "Beskrivelse",
|
||||
@@ -1146,6 +1179,25 @@
|
||||
"only_editable": "Kun automatiseringer, der er defineret i 'automations.yaml', er redigerbare.",
|
||||
"pick_automation": "Vælg automatisering for at redigere",
|
||||
"show_info_automation": "Vis info om automatisering"
|
||||
},
|
||||
"thingtalk": {
|
||||
"create": "Opret automation",
|
||||
"task_selection": {
|
||||
"header": "Opret en ny automation",
|
||||
"introduction": "Skriv nedenfor, hvad denne automation skal gøre, og vi vil forsøge at konvertere den til en Home Assistant automation."
|
||||
}
|
||||
}
|
||||
},
|
||||
"blueprint": {
|
||||
"add": {
|
||||
"import_introduction": "Du kan importere skabeloner af andre brugere fra Github og {community_link} . Indtast URL'en til skabelonen nedenfor.",
|
||||
"import_introduction_link": "Du kan importere tegninger af andre brugere fra Github og {community_link} . Indtast webadressen til tegningen nedenfor."
|
||||
},
|
||||
"overview": {
|
||||
"headers": {
|
||||
"domain": "Domæne",
|
||||
"file_name": "Filnavn"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cloud": {
|
||||
@@ -1360,13 +1412,16 @@
|
||||
"devices": {
|
||||
"automation": {
|
||||
"actions": {
|
||||
"caption": "Når noget udløses..."
|
||||
"caption": "Når noget udløses...",
|
||||
"no_actions": "Ingen handlinger",
|
||||
"unknown_action": "Ukendt handling"
|
||||
},
|
||||
"automations": "Automatiseringer",
|
||||
"conditions": {
|
||||
"caption": "Gør kun noget, hvis..."
|
||||
},
|
||||
"create": "Opret automatisering med enhed",
|
||||
"create_disable": "Kan ikke oprette automation med deaktiveret enhed",
|
||||
"no_automations": "Ingen automatiseringer",
|
||||
"no_device_automations": "Der er ingen automatiseringer til rådighed for denne enhed.",
|
||||
"triggers": {
|
||||
@@ -1391,6 +1446,12 @@
|
||||
"description": "Administrer tilsluttede enheder",
|
||||
"device_info": "Enhedsoplysninger",
|
||||
"device_not_found": "Enhed blev ikke fundet.",
|
||||
"disabled": "Deaktiveret",
|
||||
"disabled_by": {
|
||||
"integration": "Integration",
|
||||
"user": "Bruger"
|
||||
},
|
||||
"enabled_label": "Aktiver enhed",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Tilføj til Lovelace",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {deaktiveret entitet}\n other {deaktiverede entiteter}\n}",
|
||||
@@ -1400,14 +1461,24 @@
|
||||
},
|
||||
"name": "Navn",
|
||||
"no_devices": "Ingen enheder",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Filtrer",
|
||||
"show_all": "Vis alle",
|
||||
"show_disabled": "Vis deaktiverede enheder"
|
||||
},
|
||||
"search": "Søg efter enheder"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Opret scene med enhed",
|
||||
"create_disable": "Kan ikke oprette scene med deaktiveret enhed",
|
||||
"no_scenes": "Ingen scener",
|
||||
"scenes": "Scener"
|
||||
},
|
||||
"scenes": "Scener",
|
||||
"script": {
|
||||
"create": "Opret script med enhed",
|
||||
"create_disable": "Kan ikke oprette script med deaktiveret enhed",
|
||||
"no_scripts": "Ingen scripts",
|
||||
"scripts": "Scripts"
|
||||
},
|
||||
@@ -1432,12 +1503,14 @@
|
||||
},
|
||||
"filter": {
|
||||
"filter": "Filtrer",
|
||||
"show_all": "Vis alle",
|
||||
"show_disabled": "Vis deaktiverede entiteter",
|
||||
"show_readonly": "Vis skrivebeskyttede entiteter",
|
||||
"show_unavailable": "Vis utilgængelige entiteter"
|
||||
},
|
||||
"header": "Entiteter",
|
||||
"headers": {
|
||||
"area": "Område",
|
||||
"entity_id": "Entitets-id",
|
||||
"integration": "Integration",
|
||||
"name": "Navn",
|
||||
@@ -1497,6 +1570,7 @@
|
||||
"info": {
|
||||
"built_using": "Bygget ved hjælp af",
|
||||
"caption": "Oplysninger",
|
||||
"copy_raw": "Rå tekst",
|
||||
"custom_uis": "Tilpassede brugergrænseflader:",
|
||||
"description": "Se oplysninger om din Home Assistant-installation",
|
||||
"developed_by": "Udviklet af en masse fantastiske mennesker.",
|
||||
@@ -1512,6 +1586,21 @@
|
||||
"server": "server",
|
||||
"source": "Kilde:",
|
||||
"system_health_error": "System Health-komponenten er ikke indlæst. Føj 'system_health:' til 'config.yaml'",
|
||||
"system_health": {
|
||||
"checks": {
|
||||
"homeassistant": {
|
||||
"dev": "Udvikling",
|
||||
"docker": "Docker",
|
||||
"hassio": "HassOS",
|
||||
"installation_type": "Installationstype",
|
||||
"os_version": "Styresystem version",
|
||||
"python_version": "Python version",
|
||||
"timezone": "Tidszone",
|
||||
"version": "Version"
|
||||
}
|
||||
},
|
||||
"manage": "Administrer"
|
||||
},
|
||||
"title": "Info"
|
||||
},
|
||||
"integration_panel_move": {
|
||||
@@ -1914,18 +2003,23 @@
|
||||
"system_generated_users_not_editable": "Systemoprettede brugere kan ikke opdateres.",
|
||||
"system_generated_users_not_removable": "Kan ikke fjerne systemgenererede brugere.",
|
||||
"unnamed_user": "Unavngiven bruger",
|
||||
"update_user": "Opdater"
|
||||
"update_user": "Opdater",
|
||||
"username": "Brugernavn"
|
||||
},
|
||||
"picker": {
|
||||
"headers": {
|
||||
"group": "Gruppe",
|
||||
"is_active": "Aktiv",
|
||||
"is_owner": "Ejer",
|
||||
"name": "Navn",
|
||||
"system": "System"
|
||||
"system": "System",
|
||||
"username": "Brugernavn"
|
||||
}
|
||||
},
|
||||
"users_privileges_note": "Bruger-gruppen stadig under udvikling. Brugeren vil ikke være i stand til at administrere instansen via brugerfladen. Vi kigger stadig alle administrations-API-slutpunkter igennem for at sikre, at de korrekt begrænser adgangen til administratorer."
|
||||
},
|
||||
"zha": {
|
||||
"add_device": "Tilføj enhed",
|
||||
"add_device_page": {
|
||||
"discovered_text": "Enheder vil dukke op her, når de er fundet.",
|
||||
"discovery_text": "Fundne enheder vil dukke op her. Følg instruktionerne for din enhed(er) og sæt enhed(erne) i parringstilstand.",
|
||||
@@ -1971,6 +2065,9 @@
|
||||
"value": "Værdi"
|
||||
},
|
||||
"description": "Zigbee Home Automation-opsætning",
|
||||
"device_pairing_card": {
|
||||
"INITIALIZED_status_text": "Enheden er klar til brug"
|
||||
},
|
||||
"devices": {
|
||||
"header": "Zigbee Home Automation - Enhed"
|
||||
},
|
||||
@@ -1986,6 +2083,7 @@
|
||||
"unbind_button_label": "Fjern sammenføjning af gruppe"
|
||||
},
|
||||
"groups": {
|
||||
"add_group": "Tilføj gruppe",
|
||||
"add_members": "Tilføj medlemmer",
|
||||
"adding_members": "Tilføjer medlemmer",
|
||||
"caption": "Grupper",
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Konfigurationseintrag",
|
||||
"device": "Gerät",
|
||||
"integration": "Integration",
|
||||
"user": "Benutzer"
|
||||
}
|
||||
@@ -531,7 +532,7 @@
|
||||
"stay": "Bleiben",
|
||||
"successfully_deleted": "Erfolgreich gelöscht",
|
||||
"successfully_saved": "Erfolgreich gespeichert",
|
||||
"undo": "Rückgängig machen",
|
||||
"undo": "Rückgängig",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"components": {
|
||||
@@ -546,12 +547,14 @@
|
||||
"add_new": "Neuen Bereich hinzufügen...",
|
||||
"area": "Bereich",
|
||||
"clear": "Löschen",
|
||||
"no_areas": "Du hast keine Bereiche",
|
||||
"no_match": "Keine übereinstimmende Bereiche gefunden",
|
||||
"show_areas": "Bereiche anzeigen"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
"add_user": "Benutzer hinzufügen",
|
||||
"remove_user": "Benutzer entfernen",
|
||||
"select_blueprint": "Wähle einen Bauplan aus"
|
||||
"select_blueprint": "Wähle eine Vorlage aus"
|
||||
},
|
||||
"data-table": {
|
||||
"no-data": "Keine Daten",
|
||||
@@ -566,6 +569,8 @@
|
||||
"clear": "Löschen",
|
||||
"device": "Gerät",
|
||||
"no_area": "Kein Bereich",
|
||||
"no_devices": "Du hast keine Geräte",
|
||||
"no_match": "Keine übereinstimmende Geräte gefunden",
|
||||
"show_devices": "Geräte anzeigen",
|
||||
"toggle": "Umschalten"
|
||||
},
|
||||
@@ -577,6 +582,7 @@
|
||||
"entity-picker": {
|
||||
"clear": "Löschen",
|
||||
"entity": "Entität",
|
||||
"no_match": "Keine übereinstimmende Entitäten gefunden",
|
||||
"show_entities": "Entitäten anzeigen"
|
||||
}
|
||||
},
|
||||
@@ -593,7 +599,7 @@
|
||||
"changed_to_state": "wechselte zu {state}",
|
||||
"cleared_device_class": "gelöscht (keine {device_class} erkannt)",
|
||||
"detected_device_class": "erkannt {device_class}",
|
||||
"rose": "gestiegen",
|
||||
"rose": "aufgegangen",
|
||||
"set": "einstellen",
|
||||
"turned_off": "ausgeschaltet",
|
||||
"turned_on": "eingeschaltet",
|
||||
@@ -656,7 +662,7 @@
|
||||
"media-player-browser": "Medien-Browser",
|
||||
"no_items": "Keine Einträge",
|
||||
"no_local_media_found": "Keine lokalen Medien gefunden",
|
||||
"no_media_folder": "Es sieht so aus, als hätten Sie noch kein Medienverzeichnis erstellt.",
|
||||
"no_media_folder": "Es sieht so aus, als hättest du noch kein Medienverzeichnis erstellt.",
|
||||
"pick": "Auswählen",
|
||||
"pick-media": "Medien auswählen",
|
||||
"play": "Abspielen",
|
||||
@@ -710,6 +716,16 @@
|
||||
"service-picker": {
|
||||
"service": "Dienst"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_area_id": "Bereich auswählen",
|
||||
"add_device_id": "Gerät auswählen",
|
||||
"add_entity_id": "Entität auswählen",
|
||||
"expand_area_id": "Erweitere diesen Bereich in einzelne Geräte und Entitäten. Nach der Erweiterung werden die Geräte und Entitäten nicht aktualisiert, wenn sich der Bereich ändert.",
|
||||
"expand_device_id": "Erweitern Sie dieses Gerät in separate Entitäten. Nach dem Erweitern werden die Entitäten nicht aktualisiert, wenn sich das Gerät ändert.",
|
||||
"remove_area_id": "Bereich entfernen",
|
||||
"remove_device_id": "Gerät entfernen",
|
||||
"remove_entity_id": "Entität entfernen"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Benutzer hinzufügen",
|
||||
"no_user": "Kein Benutzer",
|
||||
@@ -733,6 +749,7 @@
|
||||
"editor": {
|
||||
"confirm_delete": "Möchtest du diesen Eintrag wirklich löschen?",
|
||||
"delete": "Löschen",
|
||||
"device_disabled": "Das Gerät dieser Entität ist deaktiviert.",
|
||||
"enabled_cause": "Deaktiviert durch {cause}.",
|
||||
"enabled_delay_confirm": "Die aktivierten Entitäten werden in {delay} Sekunden zu Home Assistant hinzugefügt",
|
||||
"enabled_description": "Deaktivierte Entitäten werden nicht zu Home Assistant hinzugefügt.",
|
||||
@@ -743,6 +760,7 @@
|
||||
"icon_error": "Symbole sollten das Format 'Präfix:iconname' haben, z. B. 'mdi:home'",
|
||||
"name": "Namen",
|
||||
"note": "Hinweis: Dies funktioniert möglicherweise noch nicht bei allen Integrationen.",
|
||||
"open_device_settings": "Geräteeinstellungen öffnen",
|
||||
"unavailable": "Diese Entität ist derzeit nicht verfügbar.",
|
||||
"update": "Aktualisieren"
|
||||
},
|
||||
@@ -798,7 +816,7 @@
|
||||
"pattern": "Regex-Muster für die clientseitige Validierung",
|
||||
"text": "Text"
|
||||
},
|
||||
"platform_not_loaded": "Die {platform} -Komponente ist nicht geladen. Füge sie bitte deiner Konfiguration hinzu. Entweder durch Hinzufügen von 'default_config:' oder ''{platform}:''.",
|
||||
"platform_not_loaded": "Die {platform}-Integration ist nicht geladen. Bitte füge sie deiner Konfiguration hinzu, indem du entweder 'default_config:' oder ''{platform}:'' einfügst.",
|
||||
"required_error_msg": "Dieses Feld ist erforderlich",
|
||||
"timer": {
|
||||
"duration": "Dauer"
|
||||
@@ -822,7 +840,7 @@
|
||||
"edit": "Entität bearbeiten",
|
||||
"history": "Verlauf",
|
||||
"last_changed": "Zuletzt geändert",
|
||||
"last_updated": "Letztes Update",
|
||||
"last_updated": "Zuletzt aktualisiert",
|
||||
"person": {
|
||||
"create_zone": "Zone vom aktuellen Standort erstellen"
|
||||
},
|
||||
@@ -883,7 +901,7 @@
|
||||
"navigation": {
|
||||
"areas": "Bereiche",
|
||||
"automation": "Automatisierungen",
|
||||
"blueprint": "Baupläne",
|
||||
"blueprint": "Vorlagen",
|
||||
"core": "Allgemein",
|
||||
"customize": "Anpassungen",
|
||||
"devices": "Geräte",
|
||||
@@ -905,13 +923,13 @@
|
||||
},
|
||||
"reload": {
|
||||
"automation": "Automationen neu laden",
|
||||
"command_line": "Komandozeilen Entätien neu laden",
|
||||
"core": "Positionsdaten & Anpassungen neu laden",
|
||||
"command_line": "Komandozeilenentätien neu laden",
|
||||
"core": "Positionsdaten und Anpassungen neu laden",
|
||||
"filesize": "Dateigröße-Entitäten neu laden",
|
||||
"filter": "Filter Entitäten neu laden",
|
||||
"generic": "Allgemeine IP Kamera Entitäten neu laden",
|
||||
"generic_thermostat": "Allgemeine Thermostat Entitäte neu laden",
|
||||
"group": "Gruppen, Gruppen Entitäten und Benachrichtigungsservices neu laden",
|
||||
"filter": "Filterentitäten neu laden",
|
||||
"generic": "Allgemeine IP-Kamera-Entitäten neu laden",
|
||||
"generic_thermostat": "Allgemeine Thermostat-Entitäten neu laden",
|
||||
"group": "Gruppen, Gruppenentitäten und Benachrichtigungsservices neu laden",
|
||||
"history_stats": "Verlaufsstatistiken neu laden",
|
||||
"homekit": "HomeKit neu laden",
|
||||
"input_boolean": "Input-Booleans neu laden",
|
||||
@@ -924,16 +942,16 @@
|
||||
"person": "Personen neu laden",
|
||||
"ping": "Binäre-Ping-Entitäten neu laden",
|
||||
"reload": "{domain} neu laden",
|
||||
"rest": "Rest Entitäten und Benachrichtigunsdienste neu laden",
|
||||
"rest": "REST-Entitäten und Benachrichtigunsdienste neu laden",
|
||||
"rpi_gpio": "Raspberry Pi GPIO Entitäten neu laden",
|
||||
"scene": "Szenen neu laden",
|
||||
"script": "Skripte neu laden",
|
||||
"smtp": "SMTP-Benachrichtigungsdienst neu laden",
|
||||
"statistics": "Statistik Entitäten neu laden",
|
||||
"statistics": "Statistikentitäten neu laden",
|
||||
"telegram": "Telegram-Benachrichtigungsdienst neu laden",
|
||||
"template": "Templates neu laden",
|
||||
"trend": "Trend Entitäten neu laden",
|
||||
"universal": "Universelle Medien Player Entitäten neu laden",
|
||||
"trend": "Trend-Entitäten neu laden",
|
||||
"universal": "Universelle Medien-Player-Entitäten neu laden",
|
||||
"zone": "Zonen neu laden"
|
||||
},
|
||||
"server_control": {
|
||||
@@ -1021,16 +1039,16 @@
|
||||
"link_profile_page": "deine Profilseite"
|
||||
},
|
||||
"areas": {
|
||||
"caption": "Bereichsregister",
|
||||
"caption": "Bereiche",
|
||||
"data_table": {
|
||||
"area": "Bereich",
|
||||
"devices": "Geräte"
|
||||
},
|
||||
"delete": {
|
||||
"confirmation_text": "Alle Geräte in diesem Bereich werden nicht mehr zugewiesen sein.",
|
||||
"confirmation_text": "Die Zuordnung aller Geräte zu diesem Bereich wird aufgelöst.",
|
||||
"confirmation_title": "Möchtest du diesen Bereich wirklich löschen?"
|
||||
},
|
||||
"description": "Bereiche in deinem Zuhause verwalten",
|
||||
"description": "Geräte und Entitäten in Bereiche gruppieren",
|
||||
"editor": {
|
||||
"area_id": "Bereich-ID",
|
||||
"create": "Erstellen",
|
||||
@@ -1047,15 +1065,15 @@
|
||||
"integrations_page": "Integrationsseite",
|
||||
"introduction": "In Bereichen wird festgelegt, wo sich Geräte befinden. Diese Informationen werden in Home Assistant verwendet, um Sie bei der Organisation Ihrer Benutzeroberfläche, Berechtigungen und Integrationen mit anderen Systemen zu unterstützen.",
|
||||
"introduction2": "Um Geräte in einem Bereich zu platzieren, navigiere mit dem Link unten zur Integrationsseite und klicke dann auf eine konfigurierte Integration, um zu den Gerätekarten zu gelangen.",
|
||||
"no_areas": "Sieht aus, als hätten Sie noch keine Bereiche!"
|
||||
"no_areas": "Sieht aus als hättest du noch keine Bereiche!"
|
||||
}
|
||||
},
|
||||
"automation": {
|
||||
"caption": "Automatisierung",
|
||||
"description": "Automatisierungen verwalten",
|
||||
"caption": "Automatisierungen",
|
||||
"description": "Individuelle Regeln für dein Zuhause erstellen",
|
||||
"dialog_new": {
|
||||
"blueprint": {
|
||||
"use_blueprint": "Einen Bauplan benutzen"
|
||||
"use_blueprint": "Eine Vorlage verwenden"
|
||||
},
|
||||
"header": "Erstelle eine neue Automatisierung",
|
||||
"how": "Wie möchtest du deine neue Automatisierung erstellen?",
|
||||
@@ -1064,7 +1082,7 @@
|
||||
"create": "Erstellen",
|
||||
"header": "Beschreibe die Automatisierung, die du erstellen möchtest",
|
||||
"input_label": "Was soll diese Automatisierung tun?",
|
||||
"intro": "Und wir werden versuchen, es für dich zu erstellen. Zum Beispiel: Schalten das Licht aus, wenn ich gehe."
|
||||
"intro": "Und wir werden versuchen, sie für dich zu erstellen. Zum Beispiel: Schalte das Licht aus, wenn ich gehe."
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
@@ -1116,11 +1134,11 @@
|
||||
"label": "Anzahl"
|
||||
},
|
||||
"until": {
|
||||
"conditions": "Bis Bedingungen",
|
||||
"conditions": "Bis-Bedingungen",
|
||||
"label": "Bis"
|
||||
},
|
||||
"while": {
|
||||
"conditions": "Während Bedingungen",
|
||||
"conditions": "Während-Bedingungen",
|
||||
"label": "Während"
|
||||
}
|
||||
}
|
||||
@@ -1148,12 +1166,12 @@
|
||||
},
|
||||
"alias": "Name",
|
||||
"blueprint": {
|
||||
"blueprint_to_use": "Zu verwendender Bauplan",
|
||||
"header": "Bauplan",
|
||||
"blueprint_to_use": "Zu verwendende Vorlage",
|
||||
"header": "Vorlage",
|
||||
"inputs": "Eingänge",
|
||||
"manage_blueprints": "Baupläne verwalten",
|
||||
"no_blueprints": "Du hast keine Baupläne",
|
||||
"no_inputs": "Dieser Bauplan hat keine Eingänge."
|
||||
"manage_blueprints": "Vorlagen verwalten",
|
||||
"no_blueprints": "Du hast keine Vorlagen",
|
||||
"no_inputs": "Diese Vorlage hat keine Eingänge."
|
||||
},
|
||||
"conditions": {
|
||||
"add": "Bedingung hinzufügen",
|
||||
@@ -1248,7 +1266,7 @@
|
||||
"queued": "Länge der Warteschlange"
|
||||
},
|
||||
"modes": {
|
||||
"description": "Der Modus steuert, was passiert, wenn ein Skript aufgerufen wird, während es noch von einem oder mehreren vorherigen Aufrufen ausgeführt wird. Überprüfen Sie den {documentation_link} für weitere Informationen.",
|
||||
"description": "Der Modus steuert, was passiert, wenn ein Skript aufgerufen wird, während es noch von einem oder mehreren vorherigen Aufrufen ausgeführt wird. Lies {documentation_link} für weitere Informationen.",
|
||||
"documentation": "Automatisierungs-Dokumentation",
|
||||
"label": "Modus",
|
||||
"parallel": "Parallel",
|
||||
@@ -1342,7 +1360,7 @@
|
||||
"time": {
|
||||
"at": "Um",
|
||||
"label": "Zeit",
|
||||
"type_input": "Wert eines Datum/Zeit-Helfers",
|
||||
"type_input": "Wert eines Datums-/Zeit-Helfers",
|
||||
"type_value": "Feste Zeit"
|
||||
},
|
||||
"webhook": {
|
||||
@@ -1399,31 +1417,37 @@
|
||||
},
|
||||
"blueprint": {
|
||||
"add": {
|
||||
"error_no_url": "Bitte gebe die URL des Bauplans ein.",
|
||||
"header": "Neuen Bauplan hinzufügen",
|
||||
"import_btn": "Bauplan importieren",
|
||||
"import_header": "{name}({domain}) importieren",
|
||||
"import_introduction": "Du kannst Baupläne anderer Benutzer aus GitHub und den Community-Foren importieren. Gib die URL des Bauplans unten ein.",
|
||||
"importing": "Bauplan wird importiert...",
|
||||
"save_btn": "Bauplan speichern",
|
||||
"saving": "Bauplan wir gespeichert...",
|
||||
"unsupported_blueprint": "Dieser Bauplan wird nicht unterstützt",
|
||||
"url": "URL des Bauplans"
|
||||
"community_forums": "Community-Foren",
|
||||
"error_no_url": "Bitte gebe die URL der Vorlage ein.",
|
||||
"file_name": "Vorlagenpfad",
|
||||
"header": "Vorlage importieren",
|
||||
"import_btn": "Vorschau Vorlage",
|
||||
"import_header": "Vorlage \"{name}\"",
|
||||
"import_introduction": "Du kannst Vorlagen anderer Benutzer aus GitHub und den Community-Foren importieren. Gib die URL der Vorlage unten ein.",
|
||||
"import_introduction_link": "Du kannst Vorlagen anderer Benutzer aus GitHub und den {community_link} importieren. Gib unten die URL der Vorlage ein.",
|
||||
"importing": "Vorlage wird geladen...",
|
||||
"raw_blueprint": "Inhalt der Vorlage",
|
||||
"save_btn": "Vorlage importieren",
|
||||
"saving": "Vorlage wird importiert...",
|
||||
"unsupported_blueprint": "Diese Vorlage wird nicht unterstützt",
|
||||
"url": "URL der Vorlage"
|
||||
},
|
||||
"caption": "Baupläne",
|
||||
"description": "Baupläne verwalten",
|
||||
"caption": "Vorlagen",
|
||||
"description": "Vorlagen verwalten",
|
||||
"overview": {
|
||||
"add_blueprint": "Bauplan hinzufügen",
|
||||
"confirm_delete_header": "Diesen Bauplan löschen?",
|
||||
"confirm_delete_text": "Bist du sicher, dass du diesen Bauplan löschen möchtest?",
|
||||
"header": "Bauplan-Editor",
|
||||
"add_blueprint": "Vorlage hinzufügen",
|
||||
"confirm_delete_header": "Diese Vorlage löschen?",
|
||||
"confirm_delete_text": "Bist du sicher, dass du diese Vorlage löschen möchtest?",
|
||||
"delete_blueprint": "Vorlage löschen",
|
||||
"discover_more": "Entdecke weitere Vorlagen",
|
||||
"header": "Vorlagen-Editor",
|
||||
"headers": {
|
||||
"domain": "Domain",
|
||||
"file_name": "Dateiname",
|
||||
"name": "Name"
|
||||
},
|
||||
"introduction": "Mit dem Bauplan-Editor kannst du Baupläne erstellen und bearbeiten.",
|
||||
"learn_more": "Erfahre mehr über Baupläne",
|
||||
"introduction": "Mit der Vorlagenkonfiguration kannst du deine Vorlagen importieren und verwalten.",
|
||||
"learn_more": "Erfahre mehr über die Benutzung von Vorlagen",
|
||||
"use_blueprint": "Automatisierung erstellen"
|
||||
}
|
||||
},
|
||||
@@ -1507,7 +1531,7 @@
|
||||
"title": "Alexa"
|
||||
},
|
||||
"caption": "Home Assistant Cloud",
|
||||
"description_features": "Fernsteuerung und Integration mit Alexa und Google Assistant.",
|
||||
"description_features": "Fernsteuerung und Integration mit Alexa und Google Assistant",
|
||||
"description_login": "Angemeldet als {email}",
|
||||
"description_not_login": "Nicht angemeldet",
|
||||
"dialog_certificate": {
|
||||
@@ -1602,7 +1626,7 @@
|
||||
},
|
||||
"core": {
|
||||
"caption": "Allgemein",
|
||||
"description": "Bearbeite die allgemeine Konfiguration von Home Assistant",
|
||||
"description": "Mengeneinheiten, Standort, Zeitzone & andere allgemeine Parameter",
|
||||
"section": {
|
||||
"core": {
|
||||
"core_config": {
|
||||
@@ -1634,7 +1658,7 @@
|
||||
"attributes_override": "Du kannst sie überschreiben, wenn du möchtest.",
|
||||
"attributes_set": "Die folgenden Attribute der Entität sind programmatisch festgelegt.",
|
||||
"caption": "Anpassung",
|
||||
"description": "Elemente anpassen",
|
||||
"description": "Entitäten individuell anpassen",
|
||||
"different_include": "Möglich über eine Domain, einen Glob oder einen anderen Include.",
|
||||
"pick_attribute": "Wähle ein Attribut zum Überschreiben aus.",
|
||||
"picker": {
|
||||
@@ -1664,6 +1688,7 @@
|
||||
"unknown_condition": "Unbekannte Bedingung"
|
||||
},
|
||||
"create": "Automatisierung mit Gerät erstellen",
|
||||
"create_disable": "Kann keine Automatisierung mit deaktiviertem Gerät erstellen",
|
||||
"no_automations": "Keine Automatisierungen",
|
||||
"no_device_automations": "Für dieses Gerät sind keine Automatisierungen verfügbar.",
|
||||
"triggers": {
|
||||
@@ -1677,7 +1702,7 @@
|
||||
"caption": "Geräte",
|
||||
"confirm_delete": "Möchtest du dieses Gerät wirklich löschen?",
|
||||
"confirm_rename_entity_ids": "Möchten Sie auch die Entitäts-IDs Ihrer Entitäten umbenennen?",
|
||||
"confirm_rename_entity_ids_warning": "Dies ändert keine Konfiguration (wie Automatisierungen, Skripte, Szenen, Dashboards), die derzeit diese Entitäten verwendet! Sie müssen sie selbst aktualisieren, um die neuen Entitäts-IDs zu verwenden!",
|
||||
"confirm_rename_entity_ids_warning": "Dies ändert keine Konfiguration (wie Automatisierungen, Skripte, Szenen, Dashboards), die derzeit diese Entitäten verwendet! Du musst sie selbst aktualisieren, um die neuen Entitäts-IDs zu verwenden!",
|
||||
"data_table": {
|
||||
"area": "Bereich",
|
||||
"battery": "Batterie",
|
||||
@@ -1692,23 +1717,43 @@
|
||||
"description": "Verbundene Geräte verwalten",
|
||||
"device_info": "Geräteinformationen",
|
||||
"device_not_found": "Gerät nicht gefunden.",
|
||||
"disabled": "Deaktiviert",
|
||||
"disabled_by": {
|
||||
"config_entry": "Konfigurationseintrag",
|
||||
"integration": "Integration",
|
||||
"user": "Benutzer"
|
||||
},
|
||||
"enabled_cause": "Das Gerät ist durch {cause} deaktiviert.",
|
||||
"enabled_description": "Deaktivierte Geräte werden nicht angezeigt und zum Gerät gehörende Entitäten werden deaktiviert und nicht zum Home Assistant hinzugefügt.",
|
||||
"enabled_label": "Gerät aktivieren",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Zu Lovelace hinzufügen",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {deaktivierte Entität}\n other {deaktivierte Entitäten}\n}",
|
||||
"entities": "Entitäten",
|
||||
"hide_disabled": "Ausblenden deaktiviert",
|
||||
"hide_disabled": "Deaktivierte ausblenden",
|
||||
"none": "Dieses Gerät hat keine Entitäten"
|
||||
},
|
||||
"name": "Name",
|
||||
"no_devices": "Keine Geräte",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Filter",
|
||||
"hidden_devices": "{number} {number, plural,\n one {verstecktes Gerät}\n other {versteckte Geräte}\n}",
|
||||
"show_all": "Alle anzeigen",
|
||||
"show_disabled": "Deaktivierte Geräte anzeigen"
|
||||
},
|
||||
"search": "Geräte suchen"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Szene mit Gerät erstellen",
|
||||
"create_disable": "Kann keine Szene mit deaktiviertem Gerät erstellen",
|
||||
"no_scenes": "Keine Szenen",
|
||||
"scenes": "Szenen"
|
||||
},
|
||||
"scenes": "Szenen",
|
||||
"script": {
|
||||
"create": "Szene mit Gerät erstellen",
|
||||
"create_disable": "Kann kein Skript mit deaktiviertem Gerät erstellen",
|
||||
"no_scripts": "Keine Skripte",
|
||||
"scripts": "Skripte"
|
||||
},
|
||||
@@ -1774,7 +1819,7 @@
|
||||
"header": "Home Assistant konfigurieren",
|
||||
"helpers": {
|
||||
"caption": "Helfer",
|
||||
"description": "Elemente verwalten, die beim Aufbau von Automatisierungen helfen können.",
|
||||
"description": "Elemente verwalten, die beim Aufbau von Automatisierungen helfen",
|
||||
"dialog": {
|
||||
"add_helper": "Helfer hinzufügen",
|
||||
"add_platform": "{platform} hinzufügen",
|
||||
@@ -1806,7 +1851,7 @@
|
||||
"copy_github": "Für GitHub",
|
||||
"copy_raw": "Roher Text",
|
||||
"custom_uis": "Benutzerdefinierte UIs:",
|
||||
"description": "Informationen über deine Home Assistant Installation",
|
||||
"description": "Version, Systemzustand und Links zur Dokumentation",
|
||||
"developed_by": "Entwickelt von einem Haufen toller Leute.",
|
||||
"documentation": "Dokumentation",
|
||||
"frontend": "Frontend-UI",
|
||||
@@ -1886,7 +1931,7 @@
|
||||
"options": "Optionen",
|
||||
"reload": "Neu laden",
|
||||
"reload_confirm": "Die Integration wurde neu geladen",
|
||||
"reload_restart_confirm": "Home Assistant neustarten, um das Neuladen dieser Integration abzuschließen",
|
||||
"reload_restart_confirm": "Home Assistant neu starten, um das Neuladen dieser Integration abzuschließen",
|
||||
"rename": "Umbenennen",
|
||||
"restart_confirm": "Starte Home Assistant neu, um das Entfernen dieser Integration abzuschließen",
|
||||
"services": "{count} {count, plural,\n one {Dienst}\n other {Dienste}\n}",
|
||||
@@ -1912,7 +1957,7 @@
|
||||
},
|
||||
"configure": "Konfigurieren",
|
||||
"configured": "Konfiguriert",
|
||||
"description": "Verbundene Integrationen verwalten",
|
||||
"description": "Integrationen zu Diensten, Geräten, usw. verwalten",
|
||||
"details": "Details zur Integration",
|
||||
"discovered": "Entdeckt",
|
||||
"home_assistant_website": "Home Assistant Website",
|
||||
@@ -1930,7 +1975,7 @@
|
||||
"integration": "Integration",
|
||||
"integration_not_found": "Integration nicht gefunden.",
|
||||
"new": "Richte eine neue Integration ein",
|
||||
"no_integrations": "Du hast anscheinend noch keine Integrationen konfiguriert. Klicke auf die Schaltfläche unten, um Deine erste Integration hinzuzufügen!",
|
||||
"no_integrations": "Du hast anscheinend noch keine Integrationen konfiguriert. Klicke auf die Schaltfläche unten, um eine erste Integration hinzuzufügen!",
|
||||
"none": "Noch nichts konfiguriert",
|
||||
"none_found": "Keine Integrationen gefunden",
|
||||
"none_found_detail": "Passe deine Suchkriterien an.",
|
||||
@@ -1945,7 +1990,7 @@
|
||||
"logs": {
|
||||
"caption": "Logs",
|
||||
"clear": "Leeren",
|
||||
"description": "Die Home Assistant Logs anschauen",
|
||||
"description": "Home Assistant Logs einsehen",
|
||||
"details": "Protokolldetails ( {level} )",
|
||||
"load_full_log": "Vollständiges Home Assistant-Protokoll laden",
|
||||
"loading_log": "Fehlerprotokoll wird geladen...",
|
||||
@@ -1962,7 +2007,7 @@
|
||||
"cant_edit_yaml": "In YAML definierte Dashboards können nicht über die Benutzeroberfläche bearbeitet werden. Du kannst sie aber in der configuration.yaml ändern.",
|
||||
"caption": "Dashboards",
|
||||
"conf_mode": {
|
||||
"storage": "UI gesteuert",
|
||||
"storage": "Grafischer Editor",
|
||||
"yaml": "YAML-Datei"
|
||||
},
|
||||
"confirm_delete": "Bist du sicher, dass du dieses Dashboard löschen möchtest?",
|
||||
@@ -1990,14 +2035,14 @@
|
||||
"conf_mode": "Konfigurationsmethode",
|
||||
"default": "Standard",
|
||||
"filename": "Dateiname",
|
||||
"require_admin": "Nur für Administratoren",
|
||||
"require_admin": "Nur Admin",
|
||||
"sidebar": "In der Seitenleiste anzeigen",
|
||||
"title": "Titel"
|
||||
},
|
||||
"open": "Öffnen"
|
||||
}
|
||||
},
|
||||
"description": "Konfiguriere deine Lovelace-Dashboards",
|
||||
"description": "Erstelle individuelle Oberflächen, um dein Zuhause zu steuern",
|
||||
"resources": {
|
||||
"cant_edit_yaml": "Du verwendest Lovelace im YAML-Modus. Daher kannst du deine Ressourcen nicht über die Benutzeroberfläche verwalten. Verwalte sie in der configuration.yaml.",
|
||||
"caption": "Ressourcen",
|
||||
@@ -2012,7 +2057,7 @@
|
||||
"url": "URL",
|
||||
"url_error_msg": "URL ist ein Pflichtfeld",
|
||||
"warning_header": "Sei vorsichtig!",
|
||||
"warning_text": "Das Hinzufügen von Ressourcen kann gefährlich sein. Stelle sicher, dass du die Quelle der Ressource kennst und ihr vertraust. Schlechte Ressourcen können dein System ernsthaft beschädigen."
|
||||
"warning_text": "Das Hinzufügen von Ressourcen kann gefährlich sein. Stelle sicher, dass du die Quelle der Ressource kennst und ihr vertraust. Ressourcen aus bösartigen Quellen können dein System ernsthaft beschädigen."
|
||||
},
|
||||
"picker": {
|
||||
"add_resource": "Ressource hinzufügen",
|
||||
@@ -2055,7 +2100,7 @@
|
||||
"node_id": "Knoten-ID",
|
||||
"ozw_instance": "OpenZWave-Instanz",
|
||||
"query_stage": "Abfragephase",
|
||||
"wakeup_instructions": "Weckanleitung",
|
||||
"wakeup_instructions": "Aufweckanleitung",
|
||||
"zwave": "Z-Wave"
|
||||
},
|
||||
"device_info": {
|
||||
@@ -2094,12 +2139,12 @@
|
||||
},
|
||||
"network": {
|
||||
"header": "Netzwerkverwaltung",
|
||||
"introduction": "Verwalten Sie netzwerkweite Funktionen.",
|
||||
"introduction": "Verwalten netzwerkweiter Funktionen.",
|
||||
"node_count": "{count} Knoten"
|
||||
},
|
||||
"node_config": {
|
||||
"header": "Knotenkonfiguration",
|
||||
"help_source": "Konfigurationsparameterbeschreibungen und Hilfetexte werden vom OpenZWave-Projekt bereitgestellt.",
|
||||
"help_source": "Hilfetexte und Beschreibungen der Konfigurationsparameter stellt das OpenZWave-Projekt zur Verfügung.",
|
||||
"introduction": "Verwalten Sie die verschiedenen Konfigurationsparameter für einen Z-Wave Knoten.",
|
||||
"wakeup_help": "Batteriebetriebene Knoten müssen wach sein, um ihre Konfiguration zu ändern. Wenn der Knoten nicht aktiv ist, versucht OpenZWave beim nächsten Aufwachen, die Konfiguration des Knotens zu aktualisieren. Dies kann mehrere Stunden (oder Tage) später sein. Führen Sie die folgenden Schritte aus, um Ihr Gerät zu aktivieren:"
|
||||
},
|
||||
@@ -2152,8 +2197,8 @@
|
||||
},
|
||||
"select_instance": {
|
||||
"header": "OpenZWave Instanz auswählen",
|
||||
"introduction": "Sie haben mehr als eine OpenZWave-Instanz ausgeführt. Welche Instanz möchten Sie verwalten?",
|
||||
"none_found": "Wir haben keine OpenZWave-Instanz gefunden. Wenn Sie der Meinung sind, dass dies nicht korrekt ist, überprüfen Sie Ihre OpenZWave- und MQTT-Setups und stellen Sie sicher, dass der Home Assistant mit Ihrem MQTT-Broker kommunizieren kann."
|
||||
"introduction": "Du hast mehr als eine aktive OpenZWave-Instanz. Welche möchtest du verwalten?",
|
||||
"none_found": "Wir haben keine OpenZWave-Instanz gefunden. Wenn du der Meinung bist, dass dies nicht korrekt ist, überprüfe deine OpenZWave- und MQTT-Setups und stelle sicher, dass der Home Assistant mit dem MQTT-Broker kommunizieren kann."
|
||||
},
|
||||
"services": {
|
||||
"add_node": "Knoten hinzufügen",
|
||||
@@ -2167,11 +2212,11 @@
|
||||
"confirm_delete": "Möchtest du diese Person wirklich löschen?",
|
||||
"confirm_delete2": "Alle Geräte, die zu dieser Person gehören, werden nicht mehr zugeordnet.",
|
||||
"create_person": "Person erstellen",
|
||||
"description": "Personen verwalten, denen Home Assistant folgt.",
|
||||
"description": "Personen verwalten, denen Home Assistant folgt",
|
||||
"detail": {
|
||||
"admin": "Administrator",
|
||||
"allow_login": "Erlauben Sie dieser Person, sich einzuloggen.",
|
||||
"confirm_delete_user": "Bist Du sicher, dass Du das Benutzerkonto von {name} löschen möchtest? Du kannst der Person immer noch folgen, aber sie kann sich nicht mehr anmelden.",
|
||||
"allow_login": "Erlaube dieser Person, sich einzuloggen.",
|
||||
"confirm_delete_user": "Bist Du sicher, dass Du das Benutzerkonto für {name} löschen möchtest? Du kannst der Person immer noch folgen, aber sie kann sich nicht mehr anmelden.",
|
||||
"create": "Erstellen",
|
||||
"delete": "Löschen",
|
||||
"device_tracker_intro": "Wähle die Geräte, die dieser Person gehören.",
|
||||
@@ -2196,7 +2241,7 @@
|
||||
"scene": {
|
||||
"activated": "Aktivierte Szene {name}.",
|
||||
"caption": "Szenen",
|
||||
"description": "Szenen verwalten",
|
||||
"description": "Gerätezustände erfassen und später einfach wieder abrufen",
|
||||
"editor": {
|
||||
"default_name": "Neue Szene",
|
||||
"devices": {
|
||||
@@ -2214,7 +2259,7 @@
|
||||
"without_device": "Entitäten ohne Gerät"
|
||||
},
|
||||
"icon": "Symbol",
|
||||
"introduction": "Benutze Szenen um deinem Zuhause Leben einzuhauchen.",
|
||||
"introduction": "Benutze Szenen, um deinem Zuhause Leben einzuhauchen.",
|
||||
"load_error_not_editable": "Nur Szenen in der scenes.yaml sind editierbar.",
|
||||
"load_error_unknown": "Fehler beim Laden der Szene ({err_no}).",
|
||||
"name": "Name",
|
||||
@@ -2239,8 +2284,8 @@
|
||||
}
|
||||
},
|
||||
"script": {
|
||||
"caption": "Skript",
|
||||
"description": "Skripte verwalten",
|
||||
"caption": "Skripte",
|
||||
"description": "Eine Sequenz aus Aktionen ausführen",
|
||||
"editor": {
|
||||
"alias": "Name",
|
||||
"default_name": "Neues Skript",
|
||||
@@ -2259,7 +2304,7 @@
|
||||
"queued": "Länge der Warteschlange"
|
||||
},
|
||||
"modes": {
|
||||
"description": "Der Modus steuert, was passiert, wenn ein Skript aufgerufen wird, während es noch von einem oder mehreren vorherigen Aufrufen ausgeführt wird. Überprüfen Sie den {documentation_link} für weitere Informationen.",
|
||||
"description": "Der Modus steuert, was passiert, wenn ein Skript aufgerufen wird, während es noch von einem oder mehreren vorherigen Aufrufen ausgeführt wird. Lies {documentation_link} für weitere Informationen.",
|
||||
"documentation": "Skript-Dokumentation",
|
||||
"label": "Modus",
|
||||
"parallel": "Parallel",
|
||||
@@ -2313,7 +2358,7 @@
|
||||
"min_max": "Min/Max-Entitäten neu laden",
|
||||
"mqtt": "Lade manuell konfigurierte MQTT-Entitäten neu",
|
||||
"person": "Personen neu laden",
|
||||
"ping": "Binäre Ping-Sensorentitäten neu laden",
|
||||
"ping": "Binäre Ping Sensorentitäten neu laden",
|
||||
"reload": "{domain} neu laden",
|
||||
"rest": "Rest Entitäten und Benachrichtigungsdienste neu laden",
|
||||
"rpi_gpio": "Raspberry Pi GPIO Entitäten neu laden",
|
||||
@@ -2323,7 +2368,7 @@
|
||||
"statistics": "Statistik-Entitäten neu laden",
|
||||
"telegram": "Telegram-Benachrichtigungsdienste neu laden",
|
||||
"template": "Vorlagenentitäten neu laden",
|
||||
"trend": "Trendentitäten neu laden",
|
||||
"trend": "Trend-Entitäten neu laden",
|
||||
"universal": "Universelle Media Player-Entitäten neu laden",
|
||||
"zone": "Zonen neu laden"
|
||||
},
|
||||
@@ -2339,7 +2384,7 @@
|
||||
"check_config": "Konfiguration prüfen",
|
||||
"heading": "Konfiguration überprüfen",
|
||||
"introduction": "Überprüfen Sie Ihre Konfiguration, wenn Sie kürzlich Änderungen vorgenommen haben und sicherstellen möchten, dass alle Änderungen gültig sind",
|
||||
"invalid": "Konfiguration ungültig",
|
||||
"invalid": "Konfiguration fehlerhaft",
|
||||
"valid": "Konfiguration in Ordnung"
|
||||
}
|
||||
}
|
||||
@@ -2351,7 +2396,7 @@
|
||||
"confirm_remove": "Möchtest du den Tag {tag} wirklich entfernen?",
|
||||
"confirm_remove_title": "Tag entfernen?",
|
||||
"create_automation": "Automatisierung mit NFC Tag erstellen",
|
||||
"description": "NFC Tags verwalten",
|
||||
"description": "Automatisierungen auslösen wenn NFC Tag, QR Code, usw. gescannt wird",
|
||||
"detail": {
|
||||
"companion_apps": "Mobile Apps",
|
||||
"create": "Erstellen",
|
||||
@@ -2363,7 +2408,7 @@
|
||||
"tag_id": "NFC Tag ID",
|
||||
"tag_id_placeholder": "Automatisch generiert, wenn leer gelassen",
|
||||
"update": "Aktualisieren",
|
||||
"usage": "Ein Tag kann eine Automatisierung auslösen, wenn er gescannt wird. Sie können NFC-Tags, QR-Codes oder jede andere Art von Tags verwenden. Verwenden Sie unsere {companion_link}, um diesen Tag in ein programmierbares NFC-Tag zu schreiben oder einen QR-Code zu erstellen."
|
||||
"usage": "Ein Tag kann eine Automatisierung auslösen, wenn er gescannt wird. Du kannst NFC-Tags, QR-Codes oder jede andere Art von Tags verwenden. Verwende unsere {companion_link}, um diesen Tag in ein programmierbares NFC-Tag zu schreiben oder einen QR-Code zu erstellen."
|
||||
},
|
||||
"edit": "Bearbeiten",
|
||||
"headers": {
|
||||
@@ -2386,10 +2431,11 @@
|
||||
"username": "Benutzername"
|
||||
},
|
||||
"caption": "Benutzer",
|
||||
"description": "Benutzer verwalten",
|
||||
"description": "Home Assistant Benutzerkonten verwalten",
|
||||
"editor": {
|
||||
"activate_user": "Benutzer aktivieren",
|
||||
"active": "Aktiv",
|
||||
"active_tooltip": "Steuert, ob sich der Benutzer anmelden kann",
|
||||
"admin": "Administrator",
|
||||
"caption": "Benutzer anzeigen",
|
||||
"change_password": "Passwort ändern",
|
||||
@@ -2398,14 +2444,14 @@
|
||||
"delete_user": "Benutzer löschen",
|
||||
"group": "Gruppe",
|
||||
"id": "ID",
|
||||
"name": "Name",
|
||||
"name": "Anzeigename",
|
||||
"new_password": "Neues Passwort",
|
||||
"owner": "Besitzer",
|
||||
"password_changed": "Das Passwort wurde erfolgreich geändert",
|
||||
"system_generated": "System generiert",
|
||||
"system_generated": "Systemgeneriert",
|
||||
"system_generated_users_not_editable": "Systemgenerierte Benutzer können nicht aktualisiert werden.",
|
||||
"system_generated_users_not_removable": "Vom System generierte Benutzer können nicht entfernt werden.",
|
||||
"unnamed_user": "Unbenannter Benutzer",
|
||||
"system_generated_users_not_removable": "Systemgenerierte Benutzer können nicht entfernt werden.",
|
||||
"unnamed_user": "Namenloser Benutzer",
|
||||
"update_user": "Aktualisieren",
|
||||
"username": "Benutzername"
|
||||
},
|
||||
@@ -2415,12 +2461,12 @@
|
||||
"group": "Gruppe",
|
||||
"is_active": "Aktiv",
|
||||
"is_owner": "Besitzer",
|
||||
"name": "Name",
|
||||
"system": "System",
|
||||
"name": "Anzeigename",
|
||||
"system": "System generiert",
|
||||
"username": "Benutzername"
|
||||
}
|
||||
},
|
||||
"users_privileges_note": "Benutzergruppen sind derzeit noch in Entwicklung. Der Benutzer wird nicht in der Lage sein, Änderungen an der Instanz über das UI vorzunehmen. Derzeit überprüfen wir noch alle API Endpunkte um sicherzustellen dass diese nur von Administratoren genutzt werden können."
|
||||
"users_privileges_note": "Benutzergruppen befinden sich derzeit noch in Entwicklung. Der Benutzer wird nicht in der Lage sein, Änderungen an der Instanz über die Benutzeroberfläche vorzunehmen. Derzeit überprüfen wir noch alle API Endpunkte und stellen sicher, dass diese nur von Administratoren genutzt werden können."
|
||||
},
|
||||
"zha": {
|
||||
"add_device": "Gerät hinzufügen",
|
||||
@@ -2474,8 +2520,10 @@
|
||||
"CONFIGURED_status_text": "Initialisieren",
|
||||
"INITIALIZED": "Initialisierung abgeschlossen",
|
||||
"INITIALIZED_status_text": "Das Gerät ist einsatzbereit",
|
||||
"INTERVIEW_COMPLETE": "Interview abgeschlossen",
|
||||
"INTERVIEW_COMPLETE_status_text": "Konfigurieren",
|
||||
"PAIRED": "Gerät gefunden"
|
||||
"PAIRED": "Gerät gefunden",
|
||||
"PAIRED_status_text": "Interview starten"
|
||||
},
|
||||
"devices": {
|
||||
"header": "Zigbee Home Automation - Gerät"
|
||||
@@ -2547,7 +2595,7 @@
|
||||
"configured_in_yaml": "Zonen, die über configuration.yaml konfiguriert wurden, können nicht über die Benutzeroberfläche bearbeitet werden.",
|
||||
"confirm_delete": "Möchtest du diesen Bereich wirklich löschen?",
|
||||
"create_zone": "Zone erstellen",
|
||||
"description": "Verwalte die Zonen, in denen du Personen folgen möchtest.",
|
||||
"description": "Verwalte die Zonen, in denen du Personen folgen möchtest",
|
||||
"detail": {
|
||||
"create": "Erstellen",
|
||||
"delete": "Löschen",
|
||||
@@ -2608,12 +2656,12 @@
|
||||
"add_to_group": "Zur Gruppe hinzufügen",
|
||||
"entities": "Entitäten dieses Knotens",
|
||||
"entity_info": "Entitätsinformationen",
|
||||
"exclude_entity": "Schließe diese Entität vom Home Assistant aus",
|
||||
"exclude_entity": "Entität von Home Assistant ausschließen",
|
||||
"group": "Gruppe",
|
||||
"header": "Z-Wave-Knotenverwaltung",
|
||||
"introduction": "Führe Z-Wave-Befehle aus, die einen einzelnen Knoten betreffen. Wähle einen Knoten aus, um eine Liste der verfügbaren Befehle anzuzeigen.",
|
||||
"max_associations": "Max Assoziationen:",
|
||||
"node_group_associations": "Knotengruppenzuordnungen",
|
||||
"max_associations": "Maximale Zuordnungen:",
|
||||
"node_group_associations": "Zuordnungen zu Kontengruppen",
|
||||
"node_protection": "Knotenschutz",
|
||||
"node_to_control": "Zu steuernder Knoten",
|
||||
"nodes": "Knoten",
|
||||
@@ -2708,8 +2756,8 @@
|
||||
"filter_attributes": "Attribute filtern",
|
||||
"filter_entities": "Entitäten filtern",
|
||||
"filter_states": "Zustände filtern",
|
||||
"last_changed": "Letzte Änderung",
|
||||
"last_updated": "Letzte Aktualisierung",
|
||||
"last_changed": "Zuletzt geändert",
|
||||
"last_updated": "Zuletzt aktualisiert",
|
||||
"more_info": "Mehr Info",
|
||||
"no_entities": "Keine Entitäten",
|
||||
"set_state": "Status setzen",
|
||||
@@ -2802,7 +2850,7 @@
|
||||
"editor": {
|
||||
"action-editor": {
|
||||
"actions": {
|
||||
"call-service": "Dienst ausführen",
|
||||
"call-service": "Dienst aufrufen",
|
||||
"default_action": "Standardaktion",
|
||||
"more-info": "Mehr Info",
|
||||
"navigate": "Navigieren",
|
||||
@@ -2817,11 +2865,11 @@
|
||||
"card": {
|
||||
"alarm-panel": {
|
||||
"available_states": "Verfügbare Zustände",
|
||||
"description": "Mit der Alarmzentralen-Karte kannst du die Integrationen Ihrer Alarmzentrale aktivieren und deaktivieren.",
|
||||
"description": "Mit der Alarmzentralen-Karte kannst du integrierte Alarmzentralen scharfschalten oder deaktivieren.",
|
||||
"name": "Alarmpanel"
|
||||
},
|
||||
"button": {
|
||||
"default_action_help": "Die Standardaktion hängt von den Funktionen der Entität ab, sie wird entweder umgeschaltet oder die weiteren Informationen werden angezeigt.",
|
||||
"default_action_help": "Die Standardaktion hängt von den Funktionen der Entität ab: sie wird entweder umgeschaltet oder die weiteren Informationen werden angezeigt.",
|
||||
"description": "Mit der Schaltflächen-Karte kannst du Schaltflächen hinzufügen, um Aufgaben auszuführen.",
|
||||
"name": "Schaltfläche"
|
||||
},
|
||||
@@ -2873,9 +2921,9 @@
|
||||
"last-changed": "Zuletzt geändert",
|
||||
"last-triggered": "Zuletzt ausgelöst",
|
||||
"last-updated": "Zuletzt aktualisiert",
|
||||
"none": "Keine Sekundärinformatrionen",
|
||||
"none": "Keine Sekundärinformation",
|
||||
"position": "Position",
|
||||
"tilt-position": "Neigungsposition"
|
||||
"tilt-position": "Neigung"
|
||||
},
|
||||
"show_header_toggle": "Schalter anzeigen?",
|
||||
"special_row": "spezielle Reihe",
|
||||
@@ -2886,7 +2934,7 @@
|
||||
"name": "Entität Filter"
|
||||
},
|
||||
"entity": {
|
||||
"description": "Mit der Entitätskarte erhältst du einen schnellen Überblick über den Status Ihrer Entität.",
|
||||
"description": "Mit der Entitätskarte erhältst du einen schnellen Überblick über den Status einer Entität.",
|
||||
"name": "Entität"
|
||||
},
|
||||
"gauge": {
|
||||
@@ -2968,7 +3016,7 @@
|
||||
"map": {
|
||||
"dark_mode": "Dunkler Modus?",
|
||||
"default_zoom": "Standard-Zoom",
|
||||
"description": "Mit der Map-Karte kannst du Objekte auf einer Karte anzeigen lassen.",
|
||||
"description": "Mit der Map-Karte kannst du Objekte auf einer Landkarte anzeigen lassen.",
|
||||
"geo_location_sources": "Geolocation-Quellen",
|
||||
"hours_to_show": "Zu zeigende Stunden",
|
||||
"name": "Karte",
|
||||
@@ -2984,7 +3032,7 @@
|
||||
"name": "Mediensteuerung"
|
||||
},
|
||||
"picture-elements": {
|
||||
"description": "Die Bilder-Karte ist eine der vielseitigsten Arten von Karten. Mit den Karten kannst du Symbole, Text und sogar Dienste positionieren! Auf einem Bild basierend auf Koordinaten.",
|
||||
"description": "Die Bilder-Karte ist eine der vielseitigsten Karten. Hier kannst du Symbole, Texte und sogar Dienste basierend auf Bildkoordinaten positionieren.",
|
||||
"name": "Picture Elements"
|
||||
},
|
||||
"picture-entity": {
|
||||
@@ -3082,7 +3130,7 @@
|
||||
"header_name": "{name} Konfiguration anzeigen",
|
||||
"move_left": "Ansicht nach links verschieben",
|
||||
"move_right": "Ansicht nach rechts verschieben",
|
||||
"tab_badges": "Abzeichen",
|
||||
"tab_badges": "Plaketten",
|
||||
"tab_settings": "Einstellungen",
|
||||
"tab_visibility": "Sichtbarkeit",
|
||||
"visibility": {
|
||||
@@ -3143,8 +3191,8 @@
|
||||
"para_sure": "Bist du dir sicher, dass du die Benutzeroberfläche selbst verwalten möchtest?",
|
||||
"save": "Kontrolle übernehmen",
|
||||
"yaml_config": "Um dir den Einstieg zu erleichtern, findest du hier die aktuelle Konfiguration dieses Dashboards:",
|
||||
"yaml_control": "Um die Kontrolle im YAML-Modus zu übernehmen, erstelle eine YAML-Datei mit dem Namen, den du in Deiner Konfiguration für dieses Dashboard angegeben hast, oder mit der Standardeinstellung 'ui-lovelace.yaml'.",
|
||||
"yaml_mode": "Du verwendest den YAML-Modus für dieses Dashboard. Dies bedeutet, dass Du Deine Lovelace-Konfiguration nicht über die Benutzeroberfläche ändern kannst. Wenn du dieses Dashboard über die Benutzeroberfläche verwalten möchtest, entferne \"mode: yaml\" aus Deiner Lovelace-Konfiguration in \"configuration.yaml\"."
|
||||
"yaml_control": "Um die Kontrolle im YAML-Modus zu übernehmen, erstelle eine YAML-Datei mit dem Namen, den du in deiner Konfiguration für dieses Dashboard angegeben hast, oder mit der Standardeinstellung 'ui-lovelace.yaml'.",
|
||||
"yaml_mode": "Du verwendest den YAML-Modus für dieses Dashboard. Dies bedeutet, dass du deine Lovelace-Konfiguration nicht über die Benutzeroberfläche ändern kannst. Wenn du dieses Dashboard über die Benutzeroberfläche verwalten möchtest, entferne \"mode: yaml\" aus Deiner Lovelace-Konfiguration in \"configuration.yaml\"."
|
||||
},
|
||||
"select_view": {
|
||||
"dashboard_label": "Dashboard",
|
||||
@@ -3164,7 +3212,7 @@
|
||||
},
|
||||
"view": {
|
||||
"panel_mode": {
|
||||
"description": "Dadurch wird die erste Karte in voller Breite angezeigt. Andere Karten und Marker in dieser Ansicht werden nicht angezeigt.",
|
||||
"description": "Hiermit wird die erste Karte in voller Breite angezeigt. Andere Karten und Marker in dieser Ansicht werden nicht angezeigt.",
|
||||
"title": "Panel-Modus?",
|
||||
"warning_multiple_cards": "Diese Ansicht enthält mehr als eine Karte, in einer Bedienfeldansicht kann jedoch nur eine Karte angezeigt werden."
|
||||
}
|
||||
@@ -3377,8 +3425,8 @@
|
||||
"intro": "Sind Sie bereit, dein Zuhause zu wecken, Ihre Privatsphäre zurückzugewinnen und einer weltweiten Gemeinschaft von Tüftlern beizutreten?",
|
||||
"restore": {
|
||||
"description": "Alternativ kannst du von einem vorherigen Snapshot wiederherstellen.",
|
||||
"hide_log": "Vollständiges Log verstecken",
|
||||
"in_progress": "Wiederherstellung im Prozess",
|
||||
"hide_log": "Vollständiges Protokoll ausblenden",
|
||||
"in_progress": "Wiederherstellung im Gange",
|
||||
"show_log": "Vollständiges Protokoll anzeigen"
|
||||
},
|
||||
"user": {
|
||||
@@ -3399,17 +3447,20 @@
|
||||
},
|
||||
"profile": {
|
||||
"advanced_mode": {
|
||||
"description": "Home Assistent verbirgt standardmäßig erweiterte Funktionen und Optionen. Mache diese Funktionen zugänglich, indem diese Option aktiviert wird. Dies ist eine benutzerspezifische Einstellung, die sich nicht auf andere Benutzer auswirkt, die Home Assistant verwenden.",
|
||||
"description": "Home Assistant verbirgt standardmäßig erweiterte Funktionen und Optionen. Mache diese Funktionen zugänglich, indem diese Option aktiviert wird. Dies ist eine benutzerspezifische Einstellung, die sich nicht auf andere Benutzer auswirkt, die Home Assistant verwenden.",
|
||||
"link_promo": "Mehr erfahren",
|
||||
"title": "Erweiterter Modus"
|
||||
},
|
||||
"change_password": {
|
||||
"confirm_new_password": "Neues Passwort Bestätigen",
|
||||
"current_password": "Aktuelles Passwort",
|
||||
"error_new_is_old": "Das neue Passwort muss sich von dem aktuellen Passwort unterscheiden.",
|
||||
"error_new_mismatch": "Eingegebene neue Passwörter stimmen nicht überein",
|
||||
"error_required": "Erforderlich",
|
||||
"header": "Passwort ändern",
|
||||
"new_password": "Neues Passwort",
|
||||
"submit": "Absenden"
|
||||
"submit": "Absenden",
|
||||
"success": "Passwort wurde erfolgreich geändert"
|
||||
},
|
||||
"current_user": "Du bist derzeit als {fullName} angemeldet.",
|
||||
"customize_sidebar": {
|
||||
@@ -3449,7 +3500,7 @@
|
||||
"description": "Erstelle langlebige Zugriffstoken, damit deine Skripte mit deiner Home Assistant-Instanz interagieren können. Jedes Token ist ab der Erstellung für 10 Jahre gültig. Die folgenden langlebigen Zugriffstoken sind derzeit aktiv.",
|
||||
"empty_state": "Sie haben noch keine langlebigen Zugangs-Token.",
|
||||
"header": "Langlebige Zugangs-Token",
|
||||
"last_used": "Zuletzt verwendet am {date} in {location}",
|
||||
"last_used": "Zuletzt verwendet {date} von {location}",
|
||||
"learn_auth_requests": "Erfahre, wie du authentifizierte Anfragen stellen kannst.",
|
||||
"name": "Name",
|
||||
"not_used": "Wurde noch nie benutzt",
|
||||
@@ -3472,7 +3523,7 @@
|
||||
"push_notifications": {
|
||||
"add_device_prompt": {
|
||||
"input_label": "Gerätename",
|
||||
"title": "Wie sollte dieses Gerät genannt werden?"
|
||||
"title": "Wie soll dieses Gerät genannt werden?"
|
||||
},
|
||||
"description": "Sende Benachrichtigungen an dieses Gerät.",
|
||||
"error_load_platform": "Konfiguriere notify.html5.",
|
||||
@@ -3488,7 +3539,7 @@
|
||||
"delete_failed": "Fehler beim Löschen das Aktualisierungs-Token.",
|
||||
"description": "Jedes Aktualisierungs-Token stellt eine Anmeldesitzung dar. Aktualisierungs-Token werden automatisch entfernt, wenn Sie Abmelden klicken. Die folgenden Aktualisierungs-Token sind derzeit für Ihr Konto aktiv.",
|
||||
"header": "Aktualisierungs-Tokens",
|
||||
"last_used": "Zuletzt verwendet am {date} in {location}",
|
||||
"last_used": "Zuletzt verwendet {date} von {location}",
|
||||
"not_used": "Wurde noch nie benutzt",
|
||||
"token_title": "Aktualisierungs-Token für {clientId}"
|
||||
},
|
||||
|
@@ -2,11 +2,13 @@
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Παράμετρος διαμόρφωσης",
|
||||
"device": "Συσκευή",
|
||||
"integration": "Ενσωμάτωση",
|
||||
"user": "Χρήστης"
|
||||
}
|
||||
},
|
||||
"groups": {
|
||||
"owner": "Ιδιοκτήτης",
|
||||
"system-admin": "Διαχειριστές",
|
||||
"system-read-only": "Χρήστες μόνο για ανάγνωση",
|
||||
"system-users": "Χρήστες"
|
||||
@@ -545,8 +547,15 @@
|
||||
"add_new": "Προσθήκη νέας περιοχής...",
|
||||
"area": "Περιοχή",
|
||||
"clear": "Εκκαθάριση",
|
||||
"no_areas": "Δεν έχετε περιοχές",
|
||||
"no_match": "Δεν βρέθηκαν περιοχές που να ταιριάζουν",
|
||||
"show_areas": "Εμφάνιση περιοχών"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
"add_user": "Προσθήκη χρήστη",
|
||||
"remove_user": "Κατάργηση χρήστη",
|
||||
"select_blueprint": "Επιλέξτε ένα σχεδιάγραμμα"
|
||||
},
|
||||
"data-table": {
|
||||
"no-data": "Δεν υπάρχουν δεδομένα",
|
||||
"search": "Αναζήτηση"
|
||||
@@ -560,6 +569,8 @@
|
||||
"clear": "Καθαρός",
|
||||
"device": "Συσκευή",
|
||||
"no_area": "Καμία περιοχή",
|
||||
"no_devices": "Δεν έχετε συσκευές",
|
||||
"no_match": "Δεν βρέθηκαν συσκευές που να ταιριάζουν",
|
||||
"show_devices": "Εμφάνιση συσκευών",
|
||||
"toggle": "Εναλλαγή"
|
||||
},
|
||||
@@ -571,6 +582,7 @@
|
||||
"entity-picker": {
|
||||
"clear": "Καθαρισμός",
|
||||
"entity": "Οντότητα",
|
||||
"no_match": "Δεν βρέθηκαν οντότητες που να ταιριάζουν",
|
||||
"show_entities": "Εμφάνιση οντοτήτων"
|
||||
}
|
||||
},
|
||||
@@ -587,8 +599,8 @@
|
||||
"changed_to_state": "άλλαξε σε {state}",
|
||||
"cleared_device_class": "παραγράφηκε (δεν εντοπίστηκε {device_class} )",
|
||||
"detected_device_class": "εντόπισε {device_class}",
|
||||
"rose": "αυξήθηκε",
|
||||
"set": "ορίστηκε",
|
||||
"rose": "ανέτειλε",
|
||||
"set": "έδυσε",
|
||||
"turned_off": "απενεργοποιήθηκε",
|
||||
"turned_on": "ενεργοποιήθηκε",
|
||||
"was_at_home": "ήταν στο σπίτι",
|
||||
@@ -704,6 +716,16 @@
|
||||
"service-picker": {
|
||||
"service": "Υπηρεσία"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_area_id": "Επιλέξτε περιοχή",
|
||||
"add_device_id": "Επιλέξτε συσκευή",
|
||||
"add_entity_id": "Διαλέξτε οντότητα",
|
||||
"expand_area_id": "Αναπτύξτε αυτήν την περιοχή στις ξεχωριστές συσκευές και οντότητες που περιέχει. Μετά την επέκταση δεν θα ενημερώσει τις συσκευές και τις οντότητες όταν αλλάζει η περιοχή.",
|
||||
"expand_device_id": "Αναπτύξτε αυτήν τη συσκευή σε ξεχωριστές οντότητες. Μετά την επέκταση, δεν θα ενημερώσει τις οντότητες όταν αλλάξει η συσκευή.",
|
||||
"remove_area_id": "Κατάργηση περιοχής",
|
||||
"remove_device_id": "Αφαίρεση συσκευής",
|
||||
"remove_entity_id": "Αφαίρεση οντότητας"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Προσθήκη χρήστη",
|
||||
"no_user": "Κανένας χρήστης",
|
||||
@@ -727,6 +749,7 @@
|
||||
"editor": {
|
||||
"confirm_delete": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτήν την καταχώριση;",
|
||||
"delete": "Διαγραφή",
|
||||
"device_disabled": "Η συσκευή αυτής της οντότητας είναι απενεργοποιημένη.",
|
||||
"enabled_cause": "Απενεργοποιήθηκε από {cause}.",
|
||||
"enabled_delay_confirm": "Τα ενεργοποιημένα στοιχεία θα προστεθούν στο Home Assistant σε {delay} δευτερόλεπτα",
|
||||
"enabled_description": "Οι απενεργοποιημένες οντότητες δεν θα προστεθούν στον Home Assistant.",
|
||||
@@ -737,6 +760,7 @@
|
||||
"icon_error": "Το εικονίδιο πρέπει να είναι στη μορφή 'πρόθεμα:όνομα_εικόνας', για παράδειγμα: 'mdi:home'",
|
||||
"name": "Όνομα",
|
||||
"note": "Σημείωση: Αυτό μπορεί να μην λειτουργεί ακόμη με όλες τις ενσωματώσεις.",
|
||||
"open_device_settings": "Άνοιγμα ρυθμίσεων συσκευής",
|
||||
"unavailable": "Αυτή η οντότητα δεν είναι προς το παρόν διαθέσιμη.",
|
||||
"update": "Ενημέρωση"
|
||||
},
|
||||
@@ -877,6 +901,7 @@
|
||||
"navigation": {
|
||||
"areas": "Περιοχές",
|
||||
"automation": "Αυτοματισμοί",
|
||||
"blueprint": "Σχεδιαγράμματα",
|
||||
"core": "Γενικά",
|
||||
"customize": "Μορφοποιήσεις",
|
||||
"devices": "Συσκευές",
|
||||
@@ -1046,6 +1071,20 @@
|
||||
"automation": {
|
||||
"caption": "Αυτοματισμοί",
|
||||
"description": "Διαχείριση αυτοματισμών",
|
||||
"dialog_new": {
|
||||
"blueprint": {
|
||||
"use_blueprint": "Χρησιμοποιήστε ένα σχεδιάγραμμα"
|
||||
},
|
||||
"header": "Δημιουργία νέου αυτοματισμού",
|
||||
"how": "Πώς θέλετε να δημιουργήσετε τον νέο σας αυτοματισμό;",
|
||||
"start_empty": "Ξεκινήστε με έναν κενό αυτοματισμό",
|
||||
"thingtalk": {
|
||||
"create": "Δημιουργία",
|
||||
"header": "Περιγράψτε τον αυτοματισμό που θέλετε να δημιουργήσετε",
|
||||
"input_label": "Τι πρέπει να κάνει αυτός ο αυτοματισμός;",
|
||||
"intro": "Και θα προσπαθήσουμε να το δημιουργήσουμε για εσάς. Για παράδειγμα: Σβήσε τα φώτα όταν φεύγω."
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"actions": {
|
||||
"add": "Προσθήκη ενέργειας",
|
||||
@@ -1126,6 +1165,14 @@
|
||||
"unsupported_action": "Χωρίς υποστήριξη διεπαφής χρήστη για ενέργεια: {action}"
|
||||
},
|
||||
"alias": "Όνομα",
|
||||
"blueprint": {
|
||||
"blueprint_to_use": "Σχεδιάγραμμα για χρήση",
|
||||
"header": "Σχεδιάγραμμα",
|
||||
"inputs": "Είσοδοι",
|
||||
"manage_blueprints": "Διαχείριση σχεδιαγραμμάτων",
|
||||
"no_blueprints": "Δεν έχετε σχεδιαγράμματα",
|
||||
"no_inputs": "Αυτό το σχεδιάγραμμα δεν έχει καμία εισαγωγή."
|
||||
},
|
||||
"conditions": {
|
||||
"add": "Προσθήκη όρου",
|
||||
"delete": "Διαγραφή",
|
||||
@@ -1368,6 +1415,42 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"blueprint": {
|
||||
"add": {
|
||||
"community_forums": "κοινοτικά φόρουμ",
|
||||
"error_no_url": "Εισαγάγετε τη διεύθυνση URL του σχεδιαγράμματος.",
|
||||
"file_name": "Διαδρομή σχεδιαγράμματος",
|
||||
"header": "Εισαγωγή σχεδιαγράμματος",
|
||||
"import_btn": "Προεπισκόπηση σχεδιαγράμματος",
|
||||
"import_header": "Σχεδιάγραμμα \"{name}\"",
|
||||
"import_introduction": "Μπορείτε να εισαγάγετε σχεδιαγράμματα άλλων χρηστών από το Github και τα φόρουμ της κοινότητας. Εισαγάγετε τη διεύθυνση URL του σχεδιαγράμματος παρακάτω.",
|
||||
"import_introduction_link": "Μπορείτε να εισαγάγετε σχεδιαγράμματα άλλων χρηστών από το Github και το {community_link} . Εισαγάγετε τη διεύθυνση URL του σχεδιαγράμματος παρακάτω.",
|
||||
"importing": "Φόρτωση σχεδιαγράμματος...",
|
||||
"raw_blueprint": "Περιεχόμενο σχεδιαγράμματος",
|
||||
"save_btn": "Εισαγωγή σχεδιαγράμματος",
|
||||
"saving": "Εισαγωγή σχεδιαγράμματος...",
|
||||
"unsupported_blueprint": "Αυτό το σχεδιάγραμμα δεν υποστηρίζεται",
|
||||
"url": "Διεύθυνση URL του σχεδιαγράμματος"
|
||||
},
|
||||
"caption": "Σχεδιαγράμματα",
|
||||
"description": "Διαχείριση σχεδιαγραμμάτων",
|
||||
"overview": {
|
||||
"add_blueprint": "Εισαγωγή σχεδιαγράμματος",
|
||||
"confirm_delete_header": "Διαγραφή αυτού του σχεδιαγράμματος;",
|
||||
"confirm_delete_text": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το σχεδιάγραμμα;",
|
||||
"delete_blueprint": "Διαγραφή σχεδιαγράμματος",
|
||||
"discover_more": "Ανακαλύψτε περισσότερα σχεδιαγράμματα",
|
||||
"header": "Πρόγραμμα επεξεργασίας σχεδιαγραμμάτων",
|
||||
"headers": {
|
||||
"domain": "Τομέας",
|
||||
"file_name": "Ονομα αρχείου",
|
||||
"name": "Όνομα"
|
||||
},
|
||||
"introduction": "Η διαμόρφωση του σχεδιαγράμματος σας επιτρέπει να εισάγετε και να διαχειρίζεστε τα σχεδιαγράμματά σας.",
|
||||
"learn_more": "Μάθετε περισσότερα σχετικά με τη χρήση σχεδιαγραμμάτων",
|
||||
"use_blueprint": "Δημιουργία αυτοματισμού"
|
||||
}
|
||||
},
|
||||
"cloud": {
|
||||
"account": {
|
||||
"alexa": {
|
||||
@@ -1605,6 +1688,7 @@
|
||||
"unknown_condition": "Άγνωστη κατάσταση"
|
||||
},
|
||||
"create": "Δημιουργία αυτοματισμού με τη συσκευή",
|
||||
"create_disable": "Δεν είναι δυνατή η δημιουργία αυτοματισμού με απενεργοποιημένη συσκευή",
|
||||
"no_automations": "Δεν υπάρχουν αυτοματισμοί",
|
||||
"no_device_automations": "Δεν υπάρχουν διαθέσιμοι αυτοματισμοί για αυτήν τη συσκευή.",
|
||||
"triggers": {
|
||||
@@ -1633,6 +1717,15 @@
|
||||
"description": "Διαχείριση συνδεδεμένων συσκευών",
|
||||
"device_info": "Πληροφορίες συσκευής",
|
||||
"device_not_found": "Η συσκευή δε βρέθηκε.",
|
||||
"disabled": "Απενεργοποιημένο",
|
||||
"disabled_by": {
|
||||
"config_entry": "Παράμετρος διαμόρφωσης",
|
||||
"integration": "Ενσωμάτωση",
|
||||
"user": "Χρήστης"
|
||||
},
|
||||
"enabled_cause": "Η συσκευή απενεργοποιείται από το {cause}.",
|
||||
"enabled_description": "Οι απενεργοποιημένες συσκευές δεν θα εμφανίζονται και οι οντότητες που ανήκουν στη συσκευή θα απενεργοποιούνται και δεν θα προστίθενται στο Home Assistant.",
|
||||
"enabled_label": "Ενεργοποίηση συσκευής",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Προσθήκη στο Lovelace",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {απενεργοποιημένη οντότηταy}\n other {απενεργοποιημένες οντότητες}\n}",
|
||||
@@ -1642,14 +1735,25 @@
|
||||
},
|
||||
"name": "Όνομα",
|
||||
"no_devices": "Δεν υπάρχουν συσκευές",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Φίλτρο",
|
||||
"hidden_devices": "{number} κρυφή {number, plural,\n one {συσκευή}\n other {συσκευές}\n}",
|
||||
"show_all": "Εμφάνιση όλων",
|
||||
"show_disabled": "Εμφάνιση απενεργοποιημένων συσκευών"
|
||||
},
|
||||
"search": "Αναζήτηση συσκευών"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Δημιουργία σκηνής με τη συσκευή",
|
||||
"create_disable": "Δεν είναι δυνατή η δημιουργία σκηνής με απενεργοποιημένη συσκευή",
|
||||
"no_scenes": "Καμία σκηνή",
|
||||
"scenes": "Σκηνές"
|
||||
},
|
||||
"scenes": "Σκηνές",
|
||||
"script": {
|
||||
"create": "Δημιουργία σεναρίου με συσκευή",
|
||||
"create_disable": "Δεν είναι δυνατή η δημιουργία σεναρίου με απενεργοποιημένη συσκευή",
|
||||
"no_scripts": "Χωρίς δέσμες ενεργειών",
|
||||
"scripts": "Δέσμες ενεργειών"
|
||||
},
|
||||
@@ -1682,6 +1786,7 @@
|
||||
},
|
||||
"header": "Μητρώο οντοτήτων",
|
||||
"headers": {
|
||||
"area": "Περιοχή",
|
||||
"entity_id": "Αναγνωριστικό οντότητας",
|
||||
"integration": "Ενσωμάτωση",
|
||||
"name": "Όνομα",
|
||||
@@ -2330,6 +2435,7 @@
|
||||
"editor": {
|
||||
"activate_user": "Ενεργοποίηση χρήστη",
|
||||
"active": "Ενεργό",
|
||||
"active_tooltip": "Ελέγχει εάν ο χρήστης μπορεί να συνδεθεί",
|
||||
"admin": "Διαχειριστής",
|
||||
"caption": "Προβολή χρήστη",
|
||||
"change_password": "Αλλαγή Κωδικού",
|
||||
@@ -2346,19 +2452,24 @@
|
||||
"system_generated_users_not_editable": "Δεν είναι δυνατή η ενημέρωση των χρηστών που δημιουργούνται από το σύστημα.",
|
||||
"system_generated_users_not_removable": "Δεν είναι δυνατή η διαγραφή χρηστών που δημιουργήθηκαν από το σύστημα",
|
||||
"unnamed_user": "Χρήστης χωρίς όνομα",
|
||||
"update_user": "Ενημέρωση"
|
||||
"update_user": "Ενημέρωση",
|
||||
"username": "Όνομα χρήστη"
|
||||
},
|
||||
"picker": {
|
||||
"add_user": "Προσθήκη χρήστη",
|
||||
"headers": {
|
||||
"group": "Ομάδα",
|
||||
"is_active": "Ενεργό",
|
||||
"is_owner": "Ιδιοκτήτης",
|
||||
"name": "Ονομασία",
|
||||
"system": "Σύστημα"
|
||||
"system": "Σύστημα",
|
||||
"username": "Όνομα χρήστη"
|
||||
}
|
||||
},
|
||||
"users_privileges_note": "Η ομάδα χρηστών είναι ένα έργο σε εξέλιξη. Ο χρήστης δεν θα μπορεί να διαχειριστεί την παρουσία μέσω της διεπαφής χρήστη. Εξακολουθούμε να ελέγχουμε όλα τα τελικά σημεία API διαχείρισης για να διασφαλίσουμε ότι περιορίζουν σωστά την πρόσβαση στους διαχειριστές."
|
||||
},
|
||||
"zha": {
|
||||
"add_device": "Προσθήκη συσκευής",
|
||||
"add_device_page": {
|
||||
"discovered_text": "Οι συσκευές θα εμφανιστούν εδώ μόλις ανακαλυφθούν.",
|
||||
"discovery_text": "Οι ανακαλυφθείσες συσκευές θα εμφανιστούν εδώ. Ακολουθήστε τις οδηγίες για τις συσκευές σας και τοποθετήστε τις συσκευές στη λειτουργία αντιστοίχισης.",
|
||||
@@ -2404,6 +2515,16 @@
|
||||
"value": "Τιμή"
|
||||
},
|
||||
"description": "Διαχείριση του δικτύου Zigbee Home Automation",
|
||||
"device_pairing_card": {
|
||||
"CONFIGURED": "Η διαμόρφωση ολοκληρώθηκε",
|
||||
"CONFIGURED_status_text": "Αρχικοποίηση",
|
||||
"INITIALIZED": "Η προετοιμασία ολοκληρώθηκε",
|
||||
"INITIALIZED_status_text": "Η συσκευή είναι έτοιμη για χρήση",
|
||||
"INTERVIEW_COMPLETE": "Η συνέντευξη ολοκληρώθηκε",
|
||||
"INTERVIEW_COMPLETE_status_text": "Διαμόρφωση",
|
||||
"PAIRED": "Βρέθηκε συσκευή",
|
||||
"PAIRED_status_text": "Έναρξη συνέντευξης"
|
||||
},
|
||||
"devices": {
|
||||
"header": "Zigbee Home Automation - Συσκευή"
|
||||
},
|
||||
@@ -2419,6 +2540,7 @@
|
||||
"unbind_button_label": "Αποσύνδεση ομάδας"
|
||||
},
|
||||
"groups": {
|
||||
"add_group": "Προσθήκη ομάδας",
|
||||
"add_members": "Προσθήκη Μελών",
|
||||
"adding_members": "Προσθήκη Μελών",
|
||||
"caption": "Ομάδες",
|
||||
@@ -2461,7 +2583,11 @@
|
||||
"hint_wakeup": "Μερικές συσκευές όπως οι αισθητήρες Xiaomi έχουν ένα κουμπί αφύπνισης το οποίο μπορείτε να πιέσετε για διαστήματα των ~5 δευτερολέπτων ώστε να κρατήσετε τις συσκευές αφυπνισμένες ενώ αλληλεπιδράτε μαζί τους.",
|
||||
"introduction": "Εκτελέστε εντολές ZHA που επηρεάζουν μια μόνο συσκευή. Επιλέξτε μια συσκευή για να δείτε μια λίστα διαθέσιμων εντολών."
|
||||
},
|
||||
"title": "Οικιακός Αυτοματισμός Zigbee"
|
||||
"title": "Οικιακός Αυτοματισμός Zigbee",
|
||||
"visualization": {
|
||||
"caption": "Απεικόνιση",
|
||||
"header": "Απεικόνιση δικτύου"
|
||||
}
|
||||
},
|
||||
"zone": {
|
||||
"add_zone": "Προσθήκη ζώνης",
|
||||
@@ -2915,7 +3041,8 @@
|
||||
},
|
||||
"picture-glance": {
|
||||
"description": "Η κάρτα \"Ματιά εικόνας\" εμφανίζει μια εικόνα και τις αντίστοιχες καταστάσεις οντότητας ως εικονίδιο. Οι οντότητες στη δεξιά πλευρά επιτρέπουν ενέργειες εναλλαγής, ενώ άλλες εμφανίζουν το παράθυρο διαλόγου περισσότερων πληροφοριών.",
|
||||
"name": "Στιγμιότυπο εικόνας"
|
||||
"name": "Στιγμιότυπο εικόνας",
|
||||
"state_entity": "Κρατική οντότητα"
|
||||
},
|
||||
"picture": {
|
||||
"description": "Η κάρτα Εικόνας σάς επιτρέπει να ορίσετε μια εικόνα που θα χρησιμοποιείται για πλοήγηση σε διάφορες διαδρομές στη διεπαφή σας ή να καλείτε μια υπηρεσία.",
|
||||
@@ -3327,10 +3454,13 @@
|
||||
"change_password": {
|
||||
"confirm_new_password": "Επιβεβαιώστε τον καινούριο κωδικό",
|
||||
"current_password": "Τρέχων κωδικός",
|
||||
"error_new_is_old": "Ο νέος κωδικός πρόσβασης πρέπει να είναι διαφορετικός από τον τρέχοντα κωδικό πρόσβασης",
|
||||
"error_new_mismatch": "Οι νέες τιμές κωδικού πρόσβασης που έχουν εισαχθεί δεν ταιριάζουν",
|
||||
"error_required": "Απαιτείται",
|
||||
"header": "Αλλαγή Κωδικού",
|
||||
"new_password": "Νέος κωδικός",
|
||||
"submit": "Υποβολή"
|
||||
"submit": "Υποβολή",
|
||||
"success": "Ο κωδικός άλλαξε επιτυχώς"
|
||||
},
|
||||
"current_user": "Αυτήν τη στιγμή είστε συνδεδεμένος ως {fullName}.",
|
||||
"customize_sidebar": {
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Config Entry",
|
||||
"device": "Device",
|
||||
"integration": "Integration",
|
||||
"user": "User"
|
||||
}
|
||||
@@ -546,6 +547,8 @@
|
||||
"add_new": "Add new area…",
|
||||
"area": "Area",
|
||||
"clear": "Clear",
|
||||
"no_areas": "You don't have any areas",
|
||||
"no_match": "No matching areas found",
|
||||
"show_areas": "Show areas"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
@@ -566,6 +569,8 @@
|
||||
"clear": "Clear",
|
||||
"device": "Device",
|
||||
"no_area": "No area",
|
||||
"no_devices": "You don't have any devices",
|
||||
"no_match": "No matching devices found",
|
||||
"show_devices": "Show devices",
|
||||
"toggle": "Toggle"
|
||||
},
|
||||
@@ -577,6 +582,7 @@
|
||||
"entity-picker": {
|
||||
"clear": "Clear",
|
||||
"entity": "Entity",
|
||||
"no_match": "No matching entities found",
|
||||
"show_entities": "Show entities"
|
||||
}
|
||||
},
|
||||
@@ -710,6 +716,16 @@
|
||||
"service-picker": {
|
||||
"service": "Service"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_area_id": "Pick area",
|
||||
"add_device_id": "Pick device",
|
||||
"add_entity_id": "Pick entity",
|
||||
"expand_area_id": "Expand this area in the seperate devices and entities that it contains. After expanding it will not update the devices and entities when the area changes.",
|
||||
"expand_device_id": "Expand this device in seperate entities. After expanding it will not update the entities when the device changes.",
|
||||
"remove_area_id": "Remove area",
|
||||
"remove_device_id": "Remove device",
|
||||
"remove_entity_id": "Remove entity"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Add user",
|
||||
"no_user": "No user",
|
||||
@@ -733,6 +749,7 @@
|
||||
"editor": {
|
||||
"confirm_delete": "Are you sure you want to delete this entry?",
|
||||
"delete": "Delete",
|
||||
"device_disabled": "The device of this entity is disabled.",
|
||||
"enabled_cause": "Disabled by {cause}.",
|
||||
"enabled_delay_confirm": "The enabled entities will be added to Home Assistant in {delay} seconds",
|
||||
"enabled_description": "Disabled entities will not be added to Home Assistant.",
|
||||
@@ -743,6 +760,7 @@
|
||||
"icon_error": "Icons should be in the format 'prefix:iconname', e.g. 'mdi:home'",
|
||||
"name": "Name",
|
||||
"note": "Note: This might not work yet with all integrations.",
|
||||
"open_device_settings": "Open device settings",
|
||||
"unavailable": "This entity is not currently available.",
|
||||
"update": "Update"
|
||||
},
|
||||
@@ -1030,7 +1048,7 @@
|
||||
"confirmation_text": "All devices in this area will become unassigned.",
|
||||
"confirmation_title": "Are you sure you want to delete this area?"
|
||||
},
|
||||
"description": "Manage areas in your home",
|
||||
"description": "Group devices and entities into areas",
|
||||
"editor": {
|
||||
"area_id": "Area ID",
|
||||
"create": "Create",
|
||||
@@ -1052,7 +1070,7 @@
|
||||
},
|
||||
"automation": {
|
||||
"caption": "Automations",
|
||||
"description": "Manage automations",
|
||||
"description": "Create custom behavior rules for your home",
|
||||
"dialog_new": {
|
||||
"blueprint": {
|
||||
"use_blueprint": "Use a blueprint"
|
||||
@@ -1240,7 +1258,7 @@
|
||||
"edit_ui": "Edit with UI",
|
||||
"edit_yaml": "Edit as YAML",
|
||||
"enable_disable": "Enable/Disable automation",
|
||||
"introduction": "Use automations to bring your home to live.",
|
||||
"introduction": "Use automations to bring your home to life.",
|
||||
"load_error_not_editable": "Only automations in automations.yaml are editable.",
|
||||
"load_error_unknown": "Error loading automation ({err_no}).",
|
||||
"max": {
|
||||
@@ -1399,16 +1417,18 @@
|
||||
},
|
||||
"blueprint": {
|
||||
"add": {
|
||||
"community_forums": "community forums",
|
||||
"error_no_url": "Please enter the URL of the blueprint.",
|
||||
"file_name": "Local blueprint file name",
|
||||
"header": "Add new blueprint",
|
||||
"import_btn": "Import blueprint",
|
||||
"import_header": "Import \"{name}\" (type: {domain})",
|
||||
"file_name": "Blueprint Path",
|
||||
"header": "Import a blueprint",
|
||||
"import_btn": "Preview blueprint",
|
||||
"import_header": "Blueprint \"{name}\"",
|
||||
"import_introduction": "You can import blueprints of other users from Github and the community forums. Enter the URL of the blueprint below.",
|
||||
"importing": "Importing blueprint...",
|
||||
"import_introduction_link": "You can import blueprints of other users from Github and the {community_link}. Enter the URL of the blueprint below.",
|
||||
"importing": "Loading blueprint...",
|
||||
"raw_blueprint": "Blueprint content",
|
||||
"save_btn": "Save blueprint",
|
||||
"saving": "Saving blueprint...",
|
||||
"save_btn": "Import blueprint",
|
||||
"saving": "Importing blueprint...",
|
||||
"unsupported_blueprint": "This blueprint is not supported",
|
||||
"url": "URL of the blueprint"
|
||||
},
|
||||
@@ -1419,14 +1439,15 @@
|
||||
"confirm_delete_header": "Delete this blueprint?",
|
||||
"confirm_delete_text": "Are you sure you want to delete this blueprint?",
|
||||
"delete_blueprint": "Delete blueprint",
|
||||
"discover_more": "Discover more Blueprints",
|
||||
"header": "Blueprint Editor",
|
||||
"headers": {
|
||||
"domain": "Domain",
|
||||
"file_name": "File name",
|
||||
"name": "Name"
|
||||
},
|
||||
"introduction": "The blueprint editor allows you to create and edit blueprints.",
|
||||
"learn_more": "Learn more about blueprints",
|
||||
"introduction": "The blueprint configuration allows you to import and manage your blueprints.",
|
||||
"learn_more": "Learn more about using blueprints",
|
||||
"use_blueprint": "Create automation"
|
||||
}
|
||||
},
|
||||
@@ -1510,7 +1531,7 @@
|
||||
"title": "Alexa"
|
||||
},
|
||||
"caption": "Home Assistant Cloud",
|
||||
"description_features": "Control away from home, integrate with Alexa and Google Assistant.",
|
||||
"description_features": "Control home when away and integrate with Alexa and Google Assistant",
|
||||
"description_login": "Logged in as {email}",
|
||||
"description_not_login": "Not logged in",
|
||||
"dialog_certificate": {
|
||||
@@ -1605,7 +1626,7 @@
|
||||
},
|
||||
"core": {
|
||||
"caption": "General",
|
||||
"description": "Change your general Home Assistant configuration",
|
||||
"description": "Unit system, location, time zone & other general parameters",
|
||||
"section": {
|
||||
"core": {
|
||||
"core_config": {
|
||||
@@ -1667,6 +1688,7 @@
|
||||
"unknown_condition": "Unknown condition"
|
||||
},
|
||||
"create": "Create automation with device",
|
||||
"create_disable": "Can't create automation with disabled device",
|
||||
"no_automations": "No automations",
|
||||
"no_device_automations": "There are no automations available for this device.",
|
||||
"triggers": {
|
||||
@@ -1692,9 +1714,18 @@
|
||||
"no_devices": "No devices"
|
||||
},
|
||||
"delete": "Delete",
|
||||
"description": "Manage connected devices",
|
||||
"description": "Manage configured devices",
|
||||
"device_info": "Device info",
|
||||
"device_not_found": "Device not found.",
|
||||
"disabled": "Disabled",
|
||||
"disabled_by": {
|
||||
"config_entry": "Config Entry",
|
||||
"integration": "Integration",
|
||||
"user": "User"
|
||||
},
|
||||
"enabled_cause": "The device is disabled by {cause}.",
|
||||
"enabled_description": "Disabled devices will not be shown and entities belonging to the device will be disabled and not added to Home Assistant.",
|
||||
"enabled_label": "Enable device",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Add to Lovelace",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {disabled entity}\n other {disabled entities}\n}",
|
||||
@@ -1704,14 +1735,25 @@
|
||||
},
|
||||
"name": "Name",
|
||||
"no_devices": "No devices",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Filter",
|
||||
"hidden_devices": "{number} hidden {number, plural,\n one {device}\n other {devices}\n}",
|
||||
"show_all": "Show all",
|
||||
"show_disabled": "Show disabled devices"
|
||||
},
|
||||
"search": "Search devices"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Create scene with device",
|
||||
"create_disable": "Can't create scene with disabled device",
|
||||
"no_scenes": "No scenes",
|
||||
"scenes": "Scenes"
|
||||
},
|
||||
"scenes": "Scenes",
|
||||
"script": {
|
||||
"create": "Create script with device",
|
||||
"create_disable": "Can't create script with disabled device",
|
||||
"no_scripts": "No scripts",
|
||||
"scripts": "Scripts"
|
||||
},
|
||||
@@ -1777,7 +1819,7 @@
|
||||
"header": "Configure Home Assistant",
|
||||
"helpers": {
|
||||
"caption": "Helpers",
|
||||
"description": "Manage elements that help build automations",
|
||||
"description": "Elements that help build automations",
|
||||
"dialog": {
|
||||
"add_helper": "Add helper",
|
||||
"add_platform": "Add {platform}",
|
||||
@@ -1809,7 +1851,7 @@
|
||||
"copy_github": "For GitHub",
|
||||
"copy_raw": "Raw Text",
|
||||
"custom_uis": "Custom UIs:",
|
||||
"description": "View info about your Home Assistant installation",
|
||||
"description": "Version, system health and links to documentation",
|
||||
"developed_by": "Developed by a bunch of awesome people.",
|
||||
"documentation": "Documentation",
|
||||
"frontend": "frontend-ui",
|
||||
@@ -1915,7 +1957,7 @@
|
||||
},
|
||||
"configure": "Configure",
|
||||
"configured": "Configured",
|
||||
"description": "Manage integrations",
|
||||
"description": "Manage integrations with services, devices, ...",
|
||||
"details": "Integration details",
|
||||
"discovered": "Discovered",
|
||||
"home_assistant_website": "Home Assistant website",
|
||||
@@ -2000,7 +2042,7 @@
|
||||
"open": "Open"
|
||||
}
|
||||
},
|
||||
"description": "Manage your Lovelace Dashboards",
|
||||
"description": "Create customized sets of cards to control your home",
|
||||
"resources": {
|
||||
"cant_edit_yaml": "You are using Lovelace in YAML mode, therefore you cannot manage your resources through the UI. Manage them in configuration.yaml.",
|
||||
"caption": "Resources",
|
||||
@@ -2199,7 +2241,7 @@
|
||||
"scene": {
|
||||
"activated": "Activated scene {name}.",
|
||||
"caption": "Scenes",
|
||||
"description": "Manage scenes",
|
||||
"description": "Capture device states and easily recall them later",
|
||||
"editor": {
|
||||
"default_name": "New Scene",
|
||||
"devices": {
|
||||
@@ -2243,7 +2285,7 @@
|
||||
},
|
||||
"script": {
|
||||
"caption": "Scripts",
|
||||
"description": "Manage scripts",
|
||||
"description": "Execute a sequence of actions",
|
||||
"editor": {
|
||||
"alias": "Name",
|
||||
"default_name": "New Script",
|
||||
@@ -2354,7 +2396,7 @@
|
||||
"confirm_remove": "Are you sure you want to remove tag {tag}?",
|
||||
"confirm_remove_title": "Remove tag?",
|
||||
"create_automation": "Create automation with tag",
|
||||
"description": "Manage tags",
|
||||
"description": "Trigger automations when a NFC tag, QR code, etc. is scanned",
|
||||
"detail": {
|
||||
"companion_apps": "companion apps",
|
||||
"create": "Create",
|
||||
@@ -2389,10 +2431,11 @@
|
||||
"username": "Username"
|
||||
},
|
||||
"caption": "Users",
|
||||
"description": "Manage users",
|
||||
"description": "Manage the Home Assistant user accounts",
|
||||
"editor": {
|
||||
"activate_user": "Activate user",
|
||||
"active": "Active",
|
||||
"active_tooltip": "Controls if user can login",
|
||||
"admin": "Administrator",
|
||||
"caption": "View user",
|
||||
"change_password": "Change password",
|
||||
@@ -3411,10 +3454,13 @@
|
||||
"change_password": {
|
||||
"confirm_new_password": "Confirm New Password",
|
||||
"current_password": "Current Password",
|
||||
"error_new_is_old": "New password must be different than current password",
|
||||
"error_new_mismatch": "Entered new password values do not match",
|
||||
"error_required": "Required",
|
||||
"header": "Change Password",
|
||||
"new_password": "New Password",
|
||||
"submit": "Submit"
|
||||
"submit": "Submit",
|
||||
"success": "Password changed successfully"
|
||||
},
|
||||
"current_user": "You are currently logged in as {fullName}.",
|
||||
"customize_sidebar": {
|
||||
|
@@ -666,6 +666,16 @@
|
||||
"service-picker": {
|
||||
"service": "Servicio"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_area_id": "Seleccionar área",
|
||||
"add_device_id": "Seleccionar dispositivo",
|
||||
"add_entity_id": "Seleccionar entidad",
|
||||
"expand_area_id": "Expanda esta área en los dispositivos y entidades independientes que contiene. Después de expandirlo no actualizará los dispositivos y entidades cuando cambie el área.",
|
||||
"expand_device_id": "Expanda este dispositivo en entidades independientes. Después de expandirlo no actualizará las entidades cuando cambie el dispositivo.",
|
||||
"remove_area_id": "Eliminar área",
|
||||
"remove_device_id": "Eliminar dispositivo",
|
||||
"remove_entity_id": "Eliminar entidad"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Agregar usuario",
|
||||
"no_user": "Sin usuario",
|
||||
@@ -689,6 +699,7 @@
|
||||
"editor": {
|
||||
"confirm_delete": "¿Está seguro de que desea eliminar esta entrada?",
|
||||
"delete": "Eliminar",
|
||||
"device_disabled": "El dispositivo de esta entidad está deshabilitado.",
|
||||
"enabled_cause": "Deshabilitado por {cause}.",
|
||||
"enabled_delay_confirm": "Las entidades habilitadas se agregarán a Home Assistant en {delay} segundos",
|
||||
"enabled_description": "Las entidades deshabilitadas no serán agregadas a Home Assistant.",
|
||||
@@ -699,6 +710,7 @@
|
||||
"icon_error": "Los iconos deben estar en el formato 'prefijo:nombre del icono', por ejemplo, 'mdi: home'",
|
||||
"name": "Sustituir nombre",
|
||||
"note": "Nota: esto podría no funcionar todavía con todas las integraciones.",
|
||||
"open_device_settings": "Abrir la configuración del dispositivo",
|
||||
"unavailable": "Esta entidad no está disponible actualmente.",
|
||||
"update": "Actualizar"
|
||||
},
|
||||
@@ -1489,6 +1501,7 @@
|
||||
"unknown_condition": "Condición desconocida"
|
||||
},
|
||||
"create": "Crear automatización con dispositivo",
|
||||
"create_disable": "No se puede crear automatización con un dispositivo deshabilitado",
|
||||
"no_automations": "Sin automatizaciones",
|
||||
"no_device_automations": "No hay automatizaciones disponibles para este dispositivo.",
|
||||
"triggers": {
|
||||
@@ -1515,6 +1528,14 @@
|
||||
"description": "Administrar dispositivos conectados",
|
||||
"device_info": "Información del dispositivo",
|
||||
"device_not_found": "Dispositivo no encontrado.",
|
||||
"disabled": "Deshabilitado",
|
||||
"disabled_by": {
|
||||
"config_entry": "Entrada de configuración",
|
||||
"integration": "Integración",
|
||||
"user": "Usuario"
|
||||
},
|
||||
"enabled_description": "Los dispositivos deshabilitados no se mostrarán y las entidades que pertenecen al dispositivo se deshabilitarán y no se agregarán a Home Assistant.",
|
||||
"enabled_label": "Habilitar dispositivo",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Agregar a Lovelace",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {entidad deshabilitada}\n other {entidades deshabilitadas}\n}",
|
||||
@@ -1524,14 +1545,24 @@
|
||||
},
|
||||
"name": "Nombre",
|
||||
"no_devices": "Sin dispositivos",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Filtrar",
|
||||
"show_all": "Mostrar todo",
|
||||
"show_disabled": "Mostrar los dispositivos deshabilitadas"
|
||||
},
|
||||
"search": "Mostrar dispositivos"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Crear escena con dispositivo",
|
||||
"create_disable": "No se puede crear una escena con un dispositivo deshabilitado",
|
||||
"no_scenes": "Sin escenas",
|
||||
"scenes": "Escenas"
|
||||
},
|
||||
"scenes": "Escenas",
|
||||
"script": {
|
||||
"create": "Crear script con dispositivo",
|
||||
"create_disable": "No se puede crear un script con un dispositivo deshabilitado",
|
||||
"no_scripts": "Sin scripts",
|
||||
"scripts": "Scripts"
|
||||
},
|
||||
@@ -2168,6 +2199,7 @@
|
||||
"editor": {
|
||||
"activate_user": "Activar usuario",
|
||||
"active": "Activo",
|
||||
"active_tooltip": "Controla si el usuario puede iniciar sesión",
|
||||
"admin": "Administrador",
|
||||
"caption": "Ver usuario",
|
||||
"change_password": "Cambiar contraseña",
|
||||
@@ -3136,10 +3168,13 @@
|
||||
"change_password": {
|
||||
"confirm_new_password": "Confirmar nueva contraseña",
|
||||
"current_password": "Contraseña actual",
|
||||
"error_new_is_old": "La nueva contraseña debe ser diferente a la contraseña actual",
|
||||
"error_new_mismatch": "Las contraseñas no coinciden",
|
||||
"error_required": "Necesario",
|
||||
"header": "Cambiar contraseña",
|
||||
"new_password": "Nueva contraseña",
|
||||
"submit": "Enviar"
|
||||
"submit": "Enviar",
|
||||
"success": "La contraseña se cambió con éxito"
|
||||
},
|
||||
"current_user": "Actualmente estás conectado como {fullName} .",
|
||||
"customize_sidebar": {
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Entrada de configuración",
|
||||
"device": "Dispositivo",
|
||||
"integration": "Integración",
|
||||
"user": "Usuario"
|
||||
}
|
||||
@@ -546,6 +547,8 @@
|
||||
"add_new": "Añade una nueva área ...",
|
||||
"area": "Área",
|
||||
"clear": "Limpiar",
|
||||
"no_areas": "No tienes áreas",
|
||||
"no_match": "No se han encontrado áreas coincidentes",
|
||||
"show_areas": "Mostrar áreas"
|
||||
},
|
||||
"blueprint-picker": {
|
||||
@@ -566,6 +569,8 @@
|
||||
"clear": "Limpiar",
|
||||
"device": "Dispositivo",
|
||||
"no_area": "Ningún área",
|
||||
"no_devices": "No tienes ningún dispositivo",
|
||||
"no_match": "No se han encontrado dispositivos coincidentes",
|
||||
"show_devices": "Mostrar dispositivos",
|
||||
"toggle": "Interruptor"
|
||||
},
|
||||
@@ -577,6 +582,7 @@
|
||||
"entity-picker": {
|
||||
"clear": "Limpiar",
|
||||
"entity": "Entidad",
|
||||
"no_match": "No se han encontrado entidades coincidentes",
|
||||
"show_entities": "Mostrar entidades"
|
||||
}
|
||||
},
|
||||
@@ -700,16 +706,26 @@
|
||||
"never": "Nunca",
|
||||
"past": "Hace {time}",
|
||||
"past_duration": {
|
||||
"day": "hace {count} {count, plural,\none {día}\nother {días}\n}",
|
||||
"hour": "hace {count} {count, plural,\none {hora}\nother {horas}\n}",
|
||||
"minute": "hace {count} {count, plural,\none {minuto}\nother {minutos}\n}",
|
||||
"second": "hace {count} {count, plural,\none {segundo}\nother {segundos}\n}",
|
||||
"day": "Hace {count} {count, plural,\none {día}\nother {días}\n}",
|
||||
"hour": "Hace {count} {count, plural,\none {hora}\nother {horas}\n}",
|
||||
"minute": "Hace {count} {count, plural,\none {minuto}\nother {minutos}\n}",
|
||||
"second": "Hace {count} {count, plural,\none {segundo}\nother {segundos}\n}",
|
||||
"week": "hace {count} {count, plural,\none {semana}\nother {semanas}\n}"
|
||||
}
|
||||
},
|
||||
"service-picker": {
|
||||
"service": "Servicio"
|
||||
},
|
||||
"target-picker": {
|
||||
"add_area_id": "Seleccionar área",
|
||||
"add_device_id": "Seleccionar dispositivo",
|
||||
"add_entity_id": "Seleccionar entidad",
|
||||
"expand_area_id": "Expande este área en los dispositivos y entidades independientes que contiene. Después de expandirse, no actualizará los dispositivos y entidades cuando cambie el área.",
|
||||
"expand_device_id": "Expande este dispositivo en entidades separadas. Después de expandirse, no actualizará las entidades cuando cambie el dispositivo.",
|
||||
"remove_area_id": "Eliminar área",
|
||||
"remove_device_id": "Eliminar dispositivo",
|
||||
"remove_entity_id": "Eliminar entidad"
|
||||
},
|
||||
"user-picker": {
|
||||
"add_user": "Añadir usuario",
|
||||
"no_user": "Sin usuario",
|
||||
@@ -733,6 +749,7 @@
|
||||
"editor": {
|
||||
"confirm_delete": "¿Estás seguro de que quieres eliminar este elemento?",
|
||||
"delete": "Eliminar",
|
||||
"device_disabled": "El dispositivo de esta entidad está deshabilitado.",
|
||||
"enabled_cause": "Desactivado por {cause}.",
|
||||
"enabled_delay_confirm": "Las entidades habilitadas se agregarán a Home Assistant en {delay} segundos",
|
||||
"enabled_description": "Las entidades deshabilitadas no se agregarán a Home Assistant.",
|
||||
@@ -743,6 +760,7 @@
|
||||
"icon_error": "Los iconos deben tener el formato 'prefijo:nombreicono', por ejemplo, 'mdi:home'",
|
||||
"name": "Nombre",
|
||||
"note": "Nota: puede que esto no funcione todavía con todas las integraciones",
|
||||
"open_device_settings": "Abrir la configuración del dispositivo",
|
||||
"unavailable": "Esta entidad no está disponible actualmente.",
|
||||
"update": "Actualizar"
|
||||
},
|
||||
@@ -1030,7 +1048,7 @@
|
||||
"confirmation_text": "Todos los dispositivos en esta área quedarán sin asignar.",
|
||||
"confirmation_title": "¿Estás seguro de que deseas eliminar esta área?"
|
||||
},
|
||||
"description": "Administra áreas en tu hogar",
|
||||
"description": "Agrupa dispositivos y entidades en áreas",
|
||||
"editor": {
|
||||
"area_id": "ID de área",
|
||||
"create": "Crear",
|
||||
@@ -1052,7 +1070,7 @@
|
||||
},
|
||||
"automation": {
|
||||
"caption": "Automatizaciones",
|
||||
"description": "Administra las automatizaciones",
|
||||
"description": "Crea reglas de comportamiento personalizadas para tu hogar",
|
||||
"dialog_new": {
|
||||
"blueprint": {
|
||||
"use_blueprint": "Usa un plano"
|
||||
@@ -1075,7 +1093,7 @@
|
||||
"duplicate": "Duplicar",
|
||||
"header": "Acciones",
|
||||
"introduction": "Las acciones son lo que hará Home Assistant cuando se desencadene la automatización.",
|
||||
"learn_more": "Saber más sobre las acciones.",
|
||||
"learn_more": "Aprende más sobre las acciones.",
|
||||
"name": "Acción",
|
||||
"type_select": "Tipo de acción",
|
||||
"type": {
|
||||
@@ -1151,7 +1169,7 @@
|
||||
"blueprint_to_use": "Plano a usar",
|
||||
"header": "Plano",
|
||||
"inputs": "Entradas",
|
||||
"manage_blueprints": "Administrar planos",
|
||||
"manage_blueprints": "Administra los planos",
|
||||
"no_blueprints": "No tienes ningún plano",
|
||||
"no_inputs": "Este plano no tiene ninguna entrada."
|
||||
},
|
||||
@@ -1162,7 +1180,7 @@
|
||||
"duplicate": "Duplicar",
|
||||
"header": "Condiciones",
|
||||
"introduction": "Las condiciones son opcionales e impedirán cualquier\nejecución posterior a menos que se cumplan todas las condiciones.",
|
||||
"learn_more": "Saber más sobre las condiciones",
|
||||
"learn_more": "Aprende más sobre las condiciones",
|
||||
"name": "Condición",
|
||||
"type_select": "Tipo de condición",
|
||||
"type": {
|
||||
@@ -1266,7 +1284,7 @@
|
||||
"duplicate": "Duplicar",
|
||||
"header": "Desencadenantes",
|
||||
"introduction": "Los desencadenantes son los que inician el funcionamiento de una regla de automatización. Es posible especificar varios desencadenantes para la misma regla. Una vez que se inicia un desencadenante, Home Assistant comprobará las condiciones, si las hubiere, y ejecutará la acción.",
|
||||
"learn_more": "Saber más sobre los desencadenantes",
|
||||
"learn_more": "Aprende más sobre los desencadenantes",
|
||||
"name": "Desencadenante",
|
||||
"type_select": "Tipo de desencadenante",
|
||||
"type": {
|
||||
@@ -1374,7 +1392,7 @@
|
||||
"name": "Nombre"
|
||||
},
|
||||
"introduction": "El editor de automatización te permite crear y editar automatizaciones. En el enlace siguiente puedes leer las instrucciones para asegurarte de que has configurado correctamente Home Assistant.",
|
||||
"learn_more": "Saber más sobre las automatizaciones",
|
||||
"learn_more": "Aprende más sobre las automatizaciones",
|
||||
"no_automations": "No pudimos encontrar ninguna automatización editable",
|
||||
"only_editable": "Solo las automatizaciones definidas en automations.yaml son editables.",
|
||||
"pick_automation": "Elije la automatización para editar",
|
||||
@@ -1399,34 +1417,37 @@
|
||||
},
|
||||
"blueprint": {
|
||||
"add": {
|
||||
"community_forums": "foros de la comunidad",
|
||||
"error_no_url": "Por favor, introduce la URL del plano.",
|
||||
"file_name": "Nombre de archivo del plano local",
|
||||
"header": "Añadir nuevo plano",
|
||||
"import_btn": "Importar plano",
|
||||
"import_header": "Importar {name} (tipo: {domain})",
|
||||
"file_name": "Ruta del plano",
|
||||
"header": "Importar un plano",
|
||||
"import_btn": "Vista previa del plano",
|
||||
"import_header": "Plano \"{name}\"",
|
||||
"import_introduction": "Puedes importar planos de otros usuarios desde Github y los foros de la comunidad. Introduce la URL del plano a continuación.",
|
||||
"importing": "Importando plano...",
|
||||
"import_introduction_link": "Puedes importar planos de otros usuarios desde Github y {community_link}. Introduce la URL del plano a continuación.",
|
||||
"importing": "Cargando plano...",
|
||||
"raw_blueprint": "Contenido del plano",
|
||||
"save_btn": "Guardar plano",
|
||||
"saving": "Guardando plano...",
|
||||
"save_btn": "Importar plano",
|
||||
"saving": "Importando plano...",
|
||||
"unsupported_blueprint": "Este plano no es compatible",
|
||||
"url": "URL del plano"
|
||||
},
|
||||
"caption": "Planos",
|
||||
"description": "Administrar planos",
|
||||
"description": "Administra los planos",
|
||||
"overview": {
|
||||
"add_blueprint": "Importar plano",
|
||||
"confirm_delete_header": "¿Eliminar este plano?",
|
||||
"confirm_delete_text": "¿Estás seguro de que quieres borrar este plano?",
|
||||
"delete_blueprint": "Eliminar plano",
|
||||
"discover_more": "Descubre más planos",
|
||||
"header": "Editor de planos",
|
||||
"headers": {
|
||||
"domain": "Dominio",
|
||||
"file_name": "Nombre de archivo",
|
||||
"name": "Nombre"
|
||||
},
|
||||
"introduction": "El editor de planos te permite crear y editar planos.",
|
||||
"learn_more": "Más información sobre planos",
|
||||
"introduction": "La configuración de planos te permite importar y administrar tus planos.",
|
||||
"learn_more": "Aprende más sobre el uso de planos",
|
||||
"use_blueprint": "Crear automatización"
|
||||
}
|
||||
},
|
||||
@@ -1486,7 +1507,7 @@
|
||||
"webhooks": {
|
||||
"disable_hook_error_msg": "No se pudo deshabilitar el webhook:",
|
||||
"info": "Cualquier cosa que esté configurada para ser activada por un webhook puede recibir una URL de acceso público para permitirte enviar datos a Home Assistant desde cualquier lugar, sin exponer tu instancia a Internet.",
|
||||
"link_learn_more": "Saber más sobre la creación de automatizaciones basadas en webhook.",
|
||||
"link_learn_more": "Aprende más sobre la creación de automatizaciones basadas en webhook.",
|
||||
"loading": "Cargando ...",
|
||||
"manage": "Administrar",
|
||||
"no_hooks_yet": "Parece que aún no tienes webhooks. Comienza configurando un",
|
||||
@@ -1510,7 +1531,7 @@
|
||||
"title": "Alexa"
|
||||
},
|
||||
"caption": "Nube Home Assistant",
|
||||
"description_features": "Control fuera de casa, integración con Alexa y Google Assistant.",
|
||||
"description_features": "Controla tu hogar cuando estés fuera e intégralo con Alexa y Google Assistant",
|
||||
"description_login": "Has iniciado sesión como {email}",
|
||||
"description_not_login": "No has iniciado sesión",
|
||||
"dialog_certificate": {
|
||||
@@ -1566,7 +1587,7 @@
|
||||
"introduction2": "Este servicio está a cargo de nuestro socio.",
|
||||
"introduction2a": ", una compañía fundada por los fundadores de Home Assistant y Hass.io.",
|
||||
"introduction3": "Home Assistant Cloud es un servicio de suscripción con una prueba gratuita de un mes. No se necesita información de pago.",
|
||||
"learn_more_link": "Saber más sobre Home Assistant Cloud",
|
||||
"learn_more_link": "Aprende más sobre Home Assistant Cloud",
|
||||
"password": "Contraseña",
|
||||
"password_error_msg": "Las contraseñas tienen al menos 8 caracteres.",
|
||||
"sign_in": "Inicia sesión",
|
||||
@@ -1605,7 +1626,7 @@
|
||||
},
|
||||
"core": {
|
||||
"caption": "Configuración general",
|
||||
"description": "Cambia la configuración general de Home Assistant",
|
||||
"description": "Sistema de unidades, ubicación, zona horaria y otros parámetros generales",
|
||||
"section": {
|
||||
"core": {
|
||||
"core_config": {
|
||||
@@ -1667,6 +1688,7 @@
|
||||
"unknown_condition": "Condición desconocida"
|
||||
},
|
||||
"create": "Crear automatización con el dispositivo",
|
||||
"create_disable": "No se puede crear una automatización con un dispositivo deshabilitado",
|
||||
"no_automations": "Sin automatizaciones",
|
||||
"no_device_automations": "No hay automatizaciones disponibles para este dispositivo.",
|
||||
"triggers": {
|
||||
@@ -1692,9 +1714,18 @@
|
||||
"no_devices": "Sin dispositivos"
|
||||
},
|
||||
"delete": "Eliminar",
|
||||
"description": "Administrar dispositivos conectados",
|
||||
"description": "Administra dispositivos configurados",
|
||||
"device_info": "Información del dispositivo",
|
||||
"device_not_found": "Dispositivo no encontrado.",
|
||||
"disabled": "Deshabilitado",
|
||||
"disabled_by": {
|
||||
"config_entry": "Entrada de configuración",
|
||||
"integration": "Integración",
|
||||
"user": "Usuario"
|
||||
},
|
||||
"enabled_cause": "El dispositivo está deshabilitado por {cause} .",
|
||||
"enabled_description": "Los dispositivos deshabilitados no se mostrarán y las entidades que pertenecen al dispositivo se deshabilitarán y no se añadirán a Home Assistant.",
|
||||
"enabled_label": "Habilitar dispositivo",
|
||||
"entities": {
|
||||
"add_entities_lovelace": "Añadir a Lovelace",
|
||||
"disabled_entities": "+{count} {count, plural,\n one {entidad deshabilitada}\n other {entidades deshabilitadas}\n}",
|
||||
@@ -1704,14 +1735,25 @@
|
||||
},
|
||||
"name": "Nombre",
|
||||
"no_devices": "Sin dispositivos",
|
||||
"picker": {
|
||||
"filter": {
|
||||
"filter": "Filtrar",
|
||||
"hidden_devices": "{number} {number, plural,\n one {dispositivo oculto}\n other {dispositivos ocultos}\n}",
|
||||
"show_all": "Mostrar todo",
|
||||
"show_disabled": "Mostrar dispositivos deshabilitados"
|
||||
},
|
||||
"search": "Buscar dispositivos"
|
||||
},
|
||||
"scene": {
|
||||
"create": "Crear escena con el dispositivo",
|
||||
"create_disable": "No se puede crear una escena con un dispositivo deshabilitado",
|
||||
"no_scenes": "Sin escenas",
|
||||
"scenes": "Escenas"
|
||||
},
|
||||
"scenes": "Escenas",
|
||||
"script": {
|
||||
"create": "Crear script con el dispositivo",
|
||||
"create_disable": "No se puede crear un script con un dispositivo deshabilitado",
|
||||
"no_scripts": "Sin scripts",
|
||||
"scripts": "Scripts"
|
||||
},
|
||||
@@ -1777,7 +1819,7 @@
|
||||
"header": "Configurar Home Assistant",
|
||||
"helpers": {
|
||||
"caption": "Ayudantes",
|
||||
"description": "Administra los elementos que pueden ayudar a construir automatizaciones.",
|
||||
"description": "Elementos que ayudan a construir automatizaciones",
|
||||
"dialog": {
|
||||
"add_helper": "Añadir ayudante",
|
||||
"add_platform": "Añadir {platform}",
|
||||
@@ -1809,7 +1851,7 @@
|
||||
"copy_github": "Para GitHub",
|
||||
"copy_raw": "Texto sin procesar",
|
||||
"custom_uis": "IU personalizadas:",
|
||||
"description": "Ver información sobre tu instalación de Home Assistant",
|
||||
"description": "Versión, estado del sistema y enlaces a la documentación",
|
||||
"developed_by": "Desarrollado por un montón de gente impresionante.",
|
||||
"documentation": "Documentación",
|
||||
"frontend": "interfaz de usuario",
|
||||
@@ -1915,7 +1957,7 @@
|
||||
},
|
||||
"configure": "Configurar",
|
||||
"configured": "Configurado",
|
||||
"description": "Administra las integraciones",
|
||||
"description": "Gestiona integraciones con servicios, dispositivos, ...",
|
||||
"details": "Detalles de la integración",
|
||||
"discovered": "Descubierto",
|
||||
"home_assistant_website": "Sitio web de Home Assistant",
|
||||
@@ -1948,7 +1990,7 @@
|
||||
"logs": {
|
||||
"caption": "Registros",
|
||||
"clear": "Limpiar",
|
||||
"description": "Ver los registros de Home Assistant",
|
||||
"description": "Ve los registros de Home Assistant",
|
||||
"details": "Detalles de registro ({level})",
|
||||
"load_full_log": "Cargar registro completo de Home Assistant",
|
||||
"loading_log": "Cargando registro de errores...",
|
||||
@@ -2000,7 +2042,7 @@
|
||||
"open": "Abrir"
|
||||
}
|
||||
},
|
||||
"description": "Administra tus Paneles de Control Lovelace",
|
||||
"description": "Crea conjuntos personalizados de tarjetas para controlar tu hogar",
|
||||
"resources": {
|
||||
"cant_edit_yaml": "Estás utilizando Lovelace en modo YAML, por tanto no puedes administrar tus recursos a través de la IU. Adminístralos en configuration.yaml.",
|
||||
"caption": "Recursos",
|
||||
@@ -2190,7 +2232,7 @@
|
||||
"update": "Actualizar"
|
||||
},
|
||||
"introduction": "Aquí puedes definir a cada persona de interés en Home Assistant.",
|
||||
"learn_more": "Saber más sobre las personas",
|
||||
"learn_more": "Aprende más sobre las personas",
|
||||
"no_persons_created_yet": "Parece que aún no has creado ninguna persona.",
|
||||
"note_about_persons_configured_in_yaml": "Nota: las personas configuradas a través de configuration.yaml no se pueden editar a través de la IU.",
|
||||
"person_not_found": "No pudimos encontrar a la persona que intentabas editar.",
|
||||
@@ -2199,7 +2241,7 @@
|
||||
"scene": {
|
||||
"activated": "Activada escena {name}.",
|
||||
"caption": "Escenas",
|
||||
"description": "Administra las escenas",
|
||||
"description": "Captura los estados de los dispositivos y recupéralos fácilmente más tarde",
|
||||
"editor": {
|
||||
"default_name": "Nueva Escena",
|
||||
"devices": {
|
||||
@@ -2234,7 +2276,7 @@
|
||||
"name": "Nombre"
|
||||
},
|
||||
"introduction": "El editor de escenas te permite crear y editar escenas. Por favor, sigue el siguiente enlace para leer las instrucciones para asegurarte de que has configurado Home Assistant correctamente.",
|
||||
"learn_more": "Saber más sobre las escenas",
|
||||
"learn_more": "Aprende más sobre las escenas",
|
||||
"no_scenes": "No pudimos encontrar ninguna escena editable",
|
||||
"only_editable": "Solo las escenas definidas en scenes.yaml son editables.",
|
||||
"pick_scene": "Elige una escena para editar",
|
||||
@@ -2243,7 +2285,7 @@
|
||||
},
|
||||
"script": {
|
||||
"caption": "Scripts",
|
||||
"description": "Administra los scripts",
|
||||
"description": "Ejecuta una secuencia de acciones",
|
||||
"editor": {
|
||||
"alias": "Nombre",
|
||||
"default_name": "Nuevo script",
|
||||
@@ -2255,7 +2297,7 @@
|
||||
"id_already_exists": "Este ID ya existe",
|
||||
"id_already_exists_save_error": "No puedes guardar este script porque el ID no es único, elije otro ID o déjalo en blanco para generar uno automáticamente.",
|
||||
"introduction": "Utiliza scripts para ejecutar una secuencia de acciones.",
|
||||
"link_available_actions": "Saber más sobre las acciones disponibles.",
|
||||
"link_available_actions": "Aprende más sobre las acciones disponibles.",
|
||||
"load_error_not_editable": "Solo los scripts dentro de scripts.yaml son editables.",
|
||||
"max": {
|
||||
"parallel": "Número máximo de ejecuciones paralelas",
|
||||
@@ -2284,7 +2326,7 @@
|
||||
"name": "Nombre"
|
||||
},
|
||||
"introduction": "El editor de scripts te permite crear y editar scripts. Por favor, sigue el siguiente enlace para leer las instrucciones para asegurarte de que has configurado Home Assistant correctamente.",
|
||||
"learn_more": "Saber más sobre los scripts",
|
||||
"learn_more": "Aprende más sobre los scripts",
|
||||
"no_scripts": "No hemos encontrado ningún script editable",
|
||||
"run_script": "Ejecutar script",
|
||||
"show_info": "Mostrar información sobre el script",
|
||||
@@ -2354,7 +2396,7 @@
|
||||
"confirm_remove": "¿Estás seguro de que quieres eliminar la etiqueta {tag} ?",
|
||||
"confirm_remove_title": "¿Eliminar etiqueta?",
|
||||
"create_automation": "Crear automatización con etiqueta",
|
||||
"description": "Administrar etiquetas",
|
||||
"description": "Activa automatizaciones cuando se escanea una etiqueta NFC, un código QR, etc.",
|
||||
"detail": {
|
||||
"companion_apps": "aplicaciones complementarias",
|
||||
"create": "Crear",
|
||||
@@ -2373,7 +2415,7 @@
|
||||
"last_scanned": "Última vez escaneada",
|
||||
"name": "Nombre"
|
||||
},
|
||||
"learn_more": "Más información sobre las etiquetas",
|
||||
"learn_more": "Aprende más sobre las etiquetas",
|
||||
"never_scanned": "Nunca escaneado",
|
||||
"no_tags": "Sin etiquetas",
|
||||
"write": "Escribir"
|
||||
@@ -2389,10 +2431,11 @@
|
||||
"username": "Nombre de usuario"
|
||||
},
|
||||
"caption": "Usuarios",
|
||||
"description": "Administra usuarios",
|
||||
"description": "Administra las cuentas de usuario de Home Assistant",
|
||||
"editor": {
|
||||
"activate_user": "Activar usuario",
|
||||
"active": "Activo",
|
||||
"active_tooltip": "Controla si el usuario puede iniciar sesión",
|
||||
"admin": "Administrador",
|
||||
"caption": "Ver usuario",
|
||||
"change_password": "Cambiar la contraseña",
|
||||
@@ -2586,7 +2629,7 @@
|
||||
"wakeup_interval": "Intervalo de activación"
|
||||
},
|
||||
"description": "Administra tu red Z-Wave",
|
||||
"learn_more": "Saber más sobre Z-Wave",
|
||||
"learn_more": "Aprende más sobre Z-Wave",
|
||||
"network_management": {
|
||||
"header": "Administración de red Z-Wave",
|
||||
"introduction": "Ejecutar comandos que afectan a la red Z-Wave. No recibirás comentarios sobre si la mayoría de los comandos tuvieron éxito, pero puedes consultar el Registro OZW para intentar averiguarlo."
|
||||
@@ -3325,7 +3368,7 @@
|
||||
"demo": {
|
||||
"demo_by": "por {name}",
|
||||
"introduction": "¡Bienvenido a casa! Has llegado a la demostración de Home Assistant donde mostramos las mejores interfaces de usuario creadas por nuestra comunidad.",
|
||||
"learn_more": "Saber más sobre Home Assistant",
|
||||
"learn_more": "Aprende más sobre Home Assistant",
|
||||
"next_demo": "Siguiente demostración"
|
||||
}
|
||||
},
|
||||
@@ -3405,16 +3448,19 @@
|
||||
"profile": {
|
||||
"advanced_mode": {
|
||||
"description": "Desbloquea las funciones avanzadas.",
|
||||
"link_promo": "Saber más",
|
||||
"link_promo": "Aprende más",
|
||||
"title": "Modo avanzado"
|
||||
},
|
||||
"change_password": {
|
||||
"confirm_new_password": "Confirmar nueva contraseña",
|
||||
"current_password": "Contraseña actual",
|
||||
"error_new_is_old": "La nueva contraseña debe ser diferente a la contraseña actual",
|
||||
"error_new_mismatch": "Los nuevos valores de contraseña introducidos no coinciden",
|
||||
"error_required": "Obligatorio",
|
||||
"header": "Cambiar contraseña",
|
||||
"new_password": "Nueva contraseña",
|
||||
"submit": "Enviar"
|
||||
"submit": "Enviar",
|
||||
"success": "Contraseña cambiada con éxito"
|
||||
},
|
||||
"current_user": "Has iniciado sesión como {fullName}.",
|
||||
"customize_sidebar": {
|
||||
@@ -3483,7 +3529,7 @@
|
||||
"error_load_platform": "Configurar notify.html5.",
|
||||
"error_use_https": "Requiere SSL activado para frontend.",
|
||||
"header": "Notificaciones push",
|
||||
"link_promo": "Saber más",
|
||||
"link_promo": "Aprende más",
|
||||
"push_notifications": "Notificaciones push"
|
||||
},
|
||||
"refresh_tokens": {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user