mirror of
https://github.com/home-assistant/frontend.git
synced 2026-07-24 20:54:40 +00:00
Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a5c6ffd1b9 | |||
| 9aaaaae175 | |||
| 7d39b69540 | |||
| 09bad14c3d | |||
| 369c9dc6e2 | |||
| 9676d2cee7 | |||
| 5156c67226 | |||
| 4d48fc3d85 | |||
| 20da329a21 | |||
| 4b664cc142 | |||
| c9b620fdb2 | |||
| 25c886d401 | |||
| 740805356f | |||
| ce5fb57577 | |||
| 3e20d2b454 | |||
| a9e8186491 | |||
| 3bb909b026 | |||
| b921d91aeb | |||
| 05790954c6 | |||
| 13014c1351 | |||
| e34c63b830 | |||
| 943100d758 | |||
| 55f40d66f2 | |||
| 593e5ac79c | |||
| ef31bce5ee | |||
| 3c75eb96f1 | |||
| f34dfde925 | |||
| e3b72fe0aa | |||
| 60de74a375 | |||
| 55e58f8d35 | |||
| a465254418 | |||
| 5d27a138cf | |||
| 22f4b036df | |||
| 03f694922d | |||
| a841e287e5 | |||
| 5d2afdd825 | |||
| 67240e2339 | |||
| f84a8eccfa | |||
| 68a058e4f1 | |||
| d678b42ece | |||
| 2cf63cda08 | |||
| 7bd4eeb0df | |||
| dc3ee7c779 | |||
| e8cc97a8e5 | |||
| 3b837e1d54 | |||
| bb6c2050bc | |||
| 082d4f9691 | |||
| 153d68a9cd | |||
| 0404faa856 | |||
| afbc2d6b8f | |||
| 89ecc8bd2f | |||
| 7f21a2b319 | |||
| e2f07f6723 | |||
| a475e143b7 | |||
| e50fd80b2e | |||
| 68ea1abc05 | |||
| 2e76b306c4 | |||
| ca3cac4ed3 | |||
| 41852460e1 | |||
| 9ec4e083d9 | |||
| 9560a1c4a7 | |||
| 4f5a47ace7 | |||
| 01c4d662f2 | |||
| 194024edb9 | |||
| bef0d3a6a1 | |||
| 47a024b795 | |||
| 39847f9c9d | |||
| f24f21ca91 | |||
| c8ea37eec0 | |||
| b71f452795 | |||
| 7ea1ece169 | |||
| aece3a37c0 | |||
| 705871f8dc | |||
| 4a11975349 | |||
| 4d3d27f2c4 | |||
| d784a30d42 | |||
| 35f776284b | |||
| f659a6fe37 | |||
| ad53c99fc4 | |||
| fa0172d00c |
@@ -94,6 +94,7 @@ class HcLovelace extends LitElement {
|
||||
return css`
|
||||
:host {
|
||||
min-height: 100vh;
|
||||
height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
import { DemoTrace } from "./types";
|
||||
|
||||
export const basicTrace: DemoTrace = {
|
||||
trace: {
|
||||
last_action: "action/0/choose/0/sequence/0",
|
||||
last_condition: "condition/0",
|
||||
run_id: "0",
|
||||
state: "stopped",
|
||||
timestamp: {
|
||||
start: "2021-03-22T19:17:09.519178+00:00",
|
||||
finish: "2021-03-22T19:17:09.556129+00:00",
|
||||
},
|
||||
trigger: "state of input_boolean.toggle_1",
|
||||
domain: "automation",
|
||||
item_id: "1615419646544",
|
||||
action_trace: {
|
||||
"action/0": [
|
||||
{
|
||||
path: "action/0",
|
||||
timestamp: "2021-03-22T19:17:09.526794+00:00",
|
||||
changed_variables: {
|
||||
trigger: {
|
||||
platform: "state",
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
from_state: {
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
state: "on",
|
||||
attributes: {
|
||||
editable: true,
|
||||
friendly_name: "Toggle 1",
|
||||
},
|
||||
last_changed: "2021-03-22T19:11:24.418709+00:00",
|
||||
last_updated: "2021-03-22T19:11:24.418709+00:00",
|
||||
context: {
|
||||
id: "55daa6c47a7613b0800fe0ec81090a84",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
to_state: {
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
state: "off",
|
||||
attributes: {
|
||||
editable: true,
|
||||
friendly_name: "Toggle 1",
|
||||
},
|
||||
last_changed: "2021-03-22T19:17:09.516874+00:00",
|
||||
last_updated: "2021-03-22T19:17:09.516874+00:00",
|
||||
context: {
|
||||
id: "116d7a6562d594b114f7efe728619a3f",
|
||||
parent_id: null,
|
||||
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
|
||||
},
|
||||
},
|
||||
for: null,
|
||||
attribute: null,
|
||||
description: "state of input_boolean.toggle_1",
|
||||
},
|
||||
context: {
|
||||
id: "54a7371cff31be0f4010c9fde2317322",
|
||||
parent_id: "116d7a6562d594b114f7efe728619a3f",
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
result: {
|
||||
choice: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
"action/0/choose/0": [
|
||||
{
|
||||
path: "action/0/choose/0",
|
||||
timestamp: "2021-03-22T19:17:09.530176+00:00",
|
||||
result: {
|
||||
result: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"action/0/choose/0/conditions/0": [
|
||||
{
|
||||
path: "action/0/choose/0/conditions/0",
|
||||
timestamp: "2021-03-22T19:17:09.539155+00:00",
|
||||
result: {
|
||||
result: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
"action/0/choose/0/sequence/0": [
|
||||
{
|
||||
path: "action/0/choose/0/sequence/0",
|
||||
timestamp: "2021-03-22T19:17:09.542769+00:00",
|
||||
result: {
|
||||
params: {
|
||||
domain: "input_boolean",
|
||||
service: "toggle",
|
||||
service_data: {},
|
||||
target: {
|
||||
entity_id: ["input_boolean.toggle_2"],
|
||||
},
|
||||
},
|
||||
running_script: false,
|
||||
limit: 10,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
condition_trace: {
|
||||
"condition/0": [
|
||||
{
|
||||
path: "condition/0",
|
||||
timestamp: "2021-03-22T19:17:09.520267+00:00",
|
||||
changed_variables: {
|
||||
trigger: {
|
||||
platform: "state",
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
from_state: {
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
state: "on",
|
||||
attributes: {
|
||||
editable: true,
|
||||
friendly_name: "Toggle 1",
|
||||
},
|
||||
last_changed: "2021-03-22T19:11:24.418709+00:00",
|
||||
last_updated: "2021-03-22T19:11:24.418709+00:00",
|
||||
context: {
|
||||
id: "55daa6c47a7613b0800fe0ec81090a84",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
to_state: {
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
state: "off",
|
||||
attributes: {
|
||||
editable: true,
|
||||
friendly_name: "Toggle 1",
|
||||
},
|
||||
last_changed: "2021-03-22T19:17:09.516874+00:00",
|
||||
last_updated: "2021-03-22T19:17:09.516874+00:00",
|
||||
context: {
|
||||
id: "116d7a6562d594b114f7efe728619a3f",
|
||||
parent_id: null,
|
||||
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
|
||||
},
|
||||
},
|
||||
for: null,
|
||||
attribute: null,
|
||||
description: "state of input_boolean.toggle_1",
|
||||
},
|
||||
},
|
||||
result: {
|
||||
result: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
config: {
|
||||
id: "1615419646544",
|
||||
alias: "Ensure Party mode",
|
||||
description: "",
|
||||
trigger: [
|
||||
{
|
||||
platform: "state",
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
},
|
||||
],
|
||||
condition: [
|
||||
{
|
||||
condition: "template",
|
||||
alias: "Test if Paulus is home",
|
||||
value_template: "{{ true }}",
|
||||
},
|
||||
],
|
||||
action: [
|
||||
{
|
||||
choose: [
|
||||
{
|
||||
alias: "If toggle 3 is on",
|
||||
conditions: "{{ is_state('input_boolean.toggle_3', 'on') }}",
|
||||
sequence: [
|
||||
{
|
||||
service: "input_boolean.toggle",
|
||||
alias: "Toggle 2 while 3 is on",
|
||||
target: {
|
||||
entity_id: "input_boolean.toggle_2",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
default: [
|
||||
{
|
||||
service: "input_boolean.toggle",
|
||||
alias: "Toggle 2",
|
||||
target: {
|
||||
entity_id: "input_boolean.toggle_2",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
mode: "single",
|
||||
},
|
||||
context: {
|
||||
id: "54a7371cff31be0f4010c9fde2317322",
|
||||
parent_id: "116d7a6562d594b114f7efe728619a3f",
|
||||
user_id: null,
|
||||
},
|
||||
variables: {
|
||||
trigger: {
|
||||
platform: "state",
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
from_state: {
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
state: "on",
|
||||
attributes: {
|
||||
editable: true,
|
||||
friendly_name: "Toggle 1",
|
||||
},
|
||||
last_changed: "2021-03-22T19:11:24.418709+00:00",
|
||||
last_updated: "2021-03-22T19:11:24.418709+00:00",
|
||||
context: {
|
||||
id: "55daa6c47a7613b0800fe0ec81090a84",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
to_state: {
|
||||
entity_id: "input_boolean.toggle_1",
|
||||
state: "off",
|
||||
attributes: {
|
||||
editable: true,
|
||||
friendly_name: "Toggle 1",
|
||||
},
|
||||
last_changed: "2021-03-22T19:17:09.516874+00:00",
|
||||
last_updated: "2021-03-22T19:17:09.516874+00:00",
|
||||
context: {
|
||||
id: "116d7a6562d594b114f7efe728619a3f",
|
||||
parent_id: null,
|
||||
user_id: "d1b4e89da01445fa8bc98e39fac477ca",
|
||||
},
|
||||
},
|
||||
for: null,
|
||||
attribute: null,
|
||||
description: "state of input_boolean.toggle_1",
|
||||
},
|
||||
},
|
||||
},
|
||||
logbookEntries: [
|
||||
{
|
||||
name: "Ensure Party mode",
|
||||
message: "has been triggered by state of input_boolean.toggle_1",
|
||||
source: "state of input_boolean.toggle_1",
|
||||
entity_id: "automation.toggle_toggles",
|
||||
context_id: "54a7371cff31be0f4010c9fde2317322",
|
||||
when: "2021-03-22T19:17:09.523041+00:00",
|
||||
domain: "automation",
|
||||
},
|
||||
{
|
||||
when: "2021-03-22T19:17:09.549346+00:00",
|
||||
name: "Toggle 2",
|
||||
state: "on",
|
||||
entity_id: "input_boolean.toggle_2",
|
||||
context_entity_id: "automation.toggle_toggles",
|
||||
context_entity_id_name: "Ensure Party mode",
|
||||
context_event_type: "automation_triggered",
|
||||
context_domain: "automation",
|
||||
context_name: "Ensure Party mode",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,248 @@
|
||||
import { DemoTrace } from "./types";
|
||||
|
||||
export const motionLightTrace: DemoTrace = {
|
||||
trace: {
|
||||
last_action: "action/3",
|
||||
last_condition: null,
|
||||
run_id: "1",
|
||||
state: "stopped",
|
||||
timestamp: {
|
||||
start: "2021-03-14T06:07:01.768006+00:00",
|
||||
finish: "2021-03-14T06:07:53.287525+00:00",
|
||||
},
|
||||
trigger: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
domain: "automation",
|
||||
item_id: "1614732497392",
|
||||
action_trace: {
|
||||
"action/0": [
|
||||
{
|
||||
path: "action/0",
|
||||
timestamp: "2021-03-14T06:07:01.771038+00:00",
|
||||
changed_variables: {
|
||||
trigger: {
|
||||
platform: "state",
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
from_state: {
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
state: "off",
|
||||
attributes: {
|
||||
friendly_name: "Paulus’s MacBook Pro Camera In Use",
|
||||
icon: "mdi:camera-off",
|
||||
},
|
||||
last_changed: "2021-03-14T06:06:29.235325+00:00",
|
||||
last_updated: "2021-03-14T06:06:29.235325+00:00",
|
||||
context: {
|
||||
id: "ad4864c5ce957c38a07b50378eeb245d",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
to_state: {
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
state: "on",
|
||||
attributes: {
|
||||
friendly_name: "Paulus’s MacBook Pro Camera In Use",
|
||||
icon: "mdi:camera",
|
||||
},
|
||||
last_changed: "2021-03-14T06:07:01.762009+00:00",
|
||||
last_updated: "2021-03-14T06:07:01.762009+00:00",
|
||||
context: {
|
||||
id: "e22ddfd5f11dc4aad9a52fc10dab613b",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
for: null,
|
||||
attribute: null,
|
||||
description:
|
||||
"state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
},
|
||||
context: {
|
||||
id: "43b6ee9293a551c5cc14e8eb60af54ba",
|
||||
parent_id: "e22ddfd5f11dc4aad9a52fc10dab613b",
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"action/1": [
|
||||
{ path: "action/1", timestamp: "2021-03-14T06:07:01.875316+00:00" },
|
||||
],
|
||||
"action/2": [
|
||||
{
|
||||
path: "action/2",
|
||||
timestamp: "2021-03-14T06:07:53.195013+00:00",
|
||||
changed_variables: {
|
||||
wait: {
|
||||
remaining: null,
|
||||
trigger: {
|
||||
platform: "state",
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
from_state: {
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
state: "on",
|
||||
attributes: {
|
||||
friendly_name: "Paulus’s MacBook Pro Camera In Use",
|
||||
icon: "mdi:camera",
|
||||
},
|
||||
last_changed: "2021-03-14T06:07:01.762009+00:00",
|
||||
last_updated: "2021-03-14T06:07:01.762009+00:00",
|
||||
context: {
|
||||
id: "e22ddfd5f11dc4aad9a52fc10dab613b",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
to_state: {
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
state: "off",
|
||||
attributes: {
|
||||
friendly_name: "Paulus’s MacBook Pro Camera In Use",
|
||||
icon: "mdi:camera-off",
|
||||
},
|
||||
last_changed: "2021-03-14T06:07:53.186755+00:00",
|
||||
last_updated: "2021-03-14T06:07:53.186755+00:00",
|
||||
context: {
|
||||
id: "b2308cc91d509ea8e0c623331ab178d6",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
for: null,
|
||||
attribute: null,
|
||||
description:
|
||||
"state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"action/3": [
|
||||
{
|
||||
path: "action/3",
|
||||
timestamp: "2021-03-14T06:07:53.196014+00:00",
|
||||
},
|
||||
],
|
||||
},
|
||||
condition_trace: {},
|
||||
config: {
|
||||
mode: "restart",
|
||||
max_exceeded: "silent",
|
||||
trigger: [
|
||||
{
|
||||
platform: "state",
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
from: "off",
|
||||
to: "on",
|
||||
},
|
||||
],
|
||||
action: [
|
||||
{
|
||||
service: "light.turn_on",
|
||||
target: {
|
||||
entity_id: "light.elgato_key_light_air",
|
||||
},
|
||||
},
|
||||
{
|
||||
wait_for_trigger: [
|
||||
{
|
||||
platform: "state",
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
from: "on",
|
||||
to: "off",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
service: "light.turn_off",
|
||||
target: {
|
||||
entity_id: "light.elgato_key_light_air",
|
||||
},
|
||||
},
|
||||
],
|
||||
id: "1614732497392",
|
||||
alias: "Auto Elgato",
|
||||
description: "",
|
||||
},
|
||||
context: {
|
||||
id: "43b6ee9293a551c5cc14e8eb60af54ba",
|
||||
parent_id: "e22ddfd5f11dc4aad9a52fc10dab613b",
|
||||
user_id: null,
|
||||
},
|
||||
variables: {
|
||||
trigger: {
|
||||
platform: "state",
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
from_state: {
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
state: "off",
|
||||
attributes: {
|
||||
friendly_name: "Paulus’s MacBook Pro Camera In Use",
|
||||
icon: "mdi:camera-off",
|
||||
},
|
||||
last_changed: "2021-03-14T06:06:29.235325+00:00",
|
||||
last_updated: "2021-03-14T06:06:29.235325+00:00",
|
||||
context: {
|
||||
id: "ad4864c5ce957c38a07b50378eeb245d",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
to_state: {
|
||||
entity_id: "binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
state: "on",
|
||||
attributes: {
|
||||
friendly_name: "Paulus’s MacBook Pro Camera In Use",
|
||||
icon: "mdi:camera",
|
||||
},
|
||||
last_changed: "2021-03-14T06:07:01.762009+00:00",
|
||||
last_updated: "2021-03-14T06:07:01.762009+00:00",
|
||||
context: {
|
||||
id: "e22ddfd5f11dc4aad9a52fc10dab613b",
|
||||
parent_id: null,
|
||||
user_id: null,
|
||||
},
|
||||
},
|
||||
for: null,
|
||||
attribute: null,
|
||||
description: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
},
|
||||
},
|
||||
},
|
||||
logbookEntries: [
|
||||
{
|
||||
name: "Auto Elgato",
|
||||
message:
|
||||
"has been triggered by state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
source: "state of binary_sensor.pauluss_macbook_pro_camera_in_use",
|
||||
entity_id: "automation.auto_elgato",
|
||||
when: "2021-03-14T06:07:01.768492+00:00",
|
||||
domain: "automation",
|
||||
},
|
||||
{
|
||||
when: "2021-03-14T06:07:01.872187+00:00",
|
||||
name: "Elgato Key Light Air",
|
||||
state: "on",
|
||||
entity_id: "light.elgato_key_light_air",
|
||||
context_entity_id: "automation.auto_elgato",
|
||||
context_entity_id_name: "Auto Elgato",
|
||||
context_event_type: "automation_triggered",
|
||||
context_domain: "automation",
|
||||
context_name: "Auto Elgato",
|
||||
},
|
||||
{
|
||||
when: "2021-03-14T06:07:53.284505+00:00",
|
||||
name: "Elgato Key Light Air",
|
||||
state: "off",
|
||||
entity_id: "light.elgato_key_light_air",
|
||||
context_entity_id: "automation.auto_elgato",
|
||||
context_entity_id_name: "Auto Elgato",
|
||||
context_event_type: "automation_triggered",
|
||||
context_domain: "automation",
|
||||
context_name: "Auto Elgato",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { AutomationTraceExtended } from "../../../../src/data/trace";
|
||||
import { LogbookEntry } from "../../../../src/data/logbook";
|
||||
|
||||
export interface DemoTrace {
|
||||
trace: AutomationTraceExtended;
|
||||
logbookEntries: LogbookEntry[];
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
css,
|
||||
LitElement,
|
||||
TemplateResult,
|
||||
property,
|
||||
} from "lit-element";
|
||||
import "../../../src/components/ha-card";
|
||||
import "../../../src/components/trace/hat-trace";
|
||||
import { provideHass } from "../../../src/fake_data/provide_hass";
|
||||
import { HomeAssistant } from "../../../src/types";
|
||||
import { DemoTrace } from "../data/traces/types";
|
||||
import { basicTrace } from "../data/traces/basic_trace";
|
||||
import { motionLightTrace } from "../data/traces/motion-light-trace";
|
||||
|
||||
const traces: DemoTrace[] = [basicTrace, motionLightTrace];
|
||||
|
||||
@customElement("demo-automation-trace")
|
||||
export class DemoAutomationTrace extends LitElement {
|
||||
@property({ attribute: false }) hass?: HomeAssistant;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.hass) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
${traces.map(
|
||||
(trace) => html`
|
||||
<ha-card .heading=${trace.trace.config.alias}>
|
||||
<div class="card-content">
|
||||
<hat-trace
|
||||
.hass=${this.hass}
|
||||
.trace=${trace.trace}
|
||||
.logbookEntries=${trace.logbookEntries}
|
||||
></hat-trace>
|
||||
</div>
|
||||
</ha-card>
|
||||
`
|
||||
)}
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
const hass = provideHass(this);
|
||||
hass.updateTranslations(null, "en");
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
ha-card {
|
||||
max-width: 600px;
|
||||
margin: 24px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"demo-automation-trace": DemoAutomationTrace;
|
||||
}
|
||||
}
|
||||
@@ -81,4 +81,8 @@ class DemoMoreInfoLight extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("demo-more-info-light", DemoMoreInfoLight);
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"demo-more-info-light": DemoMoreInfoLight;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,29 +111,9 @@ class HaGallery extends PolymerElement {
|
||||
</template>
|
||||
</ha-card>
|
||||
|
||||
<ha-card header="More Info Demos">
|
||||
<div class="card-content intro">
|
||||
<p>
|
||||
More info screens show up when an entity is clicked.
|
||||
</p>
|
||||
</div>
|
||||
<template is="dom-repeat" items="[[_moreInfoDemos]]">
|
||||
<a href="#[[item]]">
|
||||
<paper-item>
|
||||
<paper-item-body>{{ item }}</paper-item-body>
|
||||
<ha-icon icon="hass:chevron-right"></ha-icon>
|
||||
</paper-item>
|
||||
</a>
|
||||
</template>
|
||||
</ha-card>
|
||||
|
||||
<ha-card header="Util Demos">
|
||||
<div class="card-content intro">
|
||||
<p>
|
||||
Test pages for our utility functions.
|
||||
</p>
|
||||
</div>
|
||||
<template is="dom-repeat" items="[[_utilDemos]]">
|
||||
<ha-card header="Other Demos">
|
||||
<div class="card-content intro"></div>
|
||||
<template is="dom-repeat" items="[[_restDemos]]">
|
||||
<a href="#[[item]]">
|
||||
<paper-item>
|
||||
<paper-item-body>{{ item }}</paper-item-body>
|
||||
@@ -178,13 +158,9 @@ class HaGallery extends PolymerElement {
|
||||
type: Array,
|
||||
computed: "_computeLovelace(_demos)",
|
||||
},
|
||||
_moreInfoDemos: {
|
||||
_restDemos: {
|
||||
type: Array,
|
||||
computed: "_computeMoreInfos(_demos)",
|
||||
},
|
||||
_utilDemos: {
|
||||
type: Array,
|
||||
computed: "_computeUtil(_demos)",
|
||||
computed: "_computeRest(_demos)",
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -237,12 +213,8 @@ class HaGallery extends PolymerElement {
|
||||
return demos.filter((demo) => demo.includes("hui"));
|
||||
}
|
||||
|
||||
_computeMoreInfos(demos) {
|
||||
return demos.filter((demo) => demo.includes("more-info"));
|
||||
}
|
||||
|
||||
_computeUtil(demos) {
|
||||
return demos.filter((demo) => demo.includes("util"));
|
||||
_computeRest(demos) {
|
||||
return demos.filter((demo) => !demo.includes("hui"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../components/supervisor-connectivity";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||
import "@material/mwc-list/mwc-list-item";
|
||||
@@ -134,8 +133,6 @@ class HassioAddonStore extends LitElement {
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
<supervisor-connectivity .supervisor=${this.supervisor}>
|
||||
</supervisor-connectivity>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../components/supervisor-connectivity";
|
||||
import {
|
||||
mdiCogs,
|
||||
mdiFileDocument,
|
||||
@@ -130,8 +129,6 @@ class HassioAddonDashboard extends LitElement {
|
||||
.supervisor=${this.supervisor}
|
||||
.addon=${this.addon}
|
||||
></hassio-addon-router>
|
||||
<supervisor-connectivity .supervisor=${this.supervisor}>
|
||||
</supervisor-connectivity>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
@@ -180,9 +177,8 @@ class HassioAddonDashboard extends LitElement {
|
||||
const requestedAddon = extractSearchParam("addon");
|
||||
if (requestedAddon) {
|
||||
const addonsInfo = await fetchHassioAddonsInfo(this.hass);
|
||||
const validAddon = addonsInfo.addons.some(
|
||||
(addon) => addon.slug === requestedAddon
|
||||
);
|
||||
const validAddon = addonsInfo.addons
|
||||
.some((addon) => addon.slug === requestedAddon);
|
||||
if (!validAddon) {
|
||||
this._error = this.supervisor.localize("my.error_addon_not_found");
|
||||
} else {
|
||||
|
||||
@@ -242,14 +242,14 @@ class HassioAddonInfo extends LitElement {
|
||||
? html`
|
||||
Current version: ${this.addon.version}
|
||||
<div class="changelog" @click=${this._openChangelog}>
|
||||
(<span class="changelog-link">
|
||||
${this.supervisor.localize("addon.dashboard.changelog")} </span
|
||||
(<span class="changelog-link">${
|
||||
this.supervisor.localize("addon.dashboard.changelog")}</span
|
||||
>)
|
||||
</div>
|
||||
`
|
||||
: html`<span class="changelog-link" @click=${this._openChangelog}>
|
||||
${this.supervisor.localize("addon.dashboard.changelog")}
|
||||
</span>`}
|
||||
: html`<span class="changelog-link" @click=${this._openChangelog}>${
|
||||
this.supervisor.localize("addon.dashboard.changelog")
|
||||
}</span>`}
|
||||
</div>
|
||||
|
||||
<div class="description light-color">
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { Supervisor } from "../../../src/data/supervisor/supervisor";
|
||||
import { haStyle } from "../../../src/resources/styles";
|
||||
|
||||
@customElement("supervisor-connectivity")
|
||||
class SupervisorConnectivity extends LitElement {
|
||||
@property({ attribute: false }) public supervisor!: Supervisor;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (this.supervisor.network.supervisor_internet) {
|
||||
return html``;
|
||||
}
|
||||
|
||||
return html`<div class="connectivity">
|
||||
<span>${this.supervisor.localize("common.error.lost_connectivity")}</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.connectivity {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
height: 32px;
|
||||
width: 100vw;
|
||||
background-color: var(--error-color);
|
||||
color: var(--primary-text-color);
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
span {
|
||||
padding-left: 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"supervisor-connectivity": SupervisorConnectivity;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ class SupervisorMetric extends LitElement {
|
||||
</span>
|
||||
<div slot="description" .title=${this.tooltip ?? ""}>
|
||||
<span class="value">
|
||||
${roundedValue}%
|
||||
${roundedValue} %
|
||||
</span>
|
||||
<ha-bar
|
||||
class="${classMap({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../components/supervisor-connectivity";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -50,8 +49,6 @@ class HassioDashboard extends LitElement {
|
||||
.supervisor=${this.supervisor}
|
||||
></hassio-addons>
|
||||
</div>
|
||||
<supervisor-connectivity .supervisor=${this.supervisor}>
|
||||
</supervisor-connectivity>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../components/supervisor-connectivity";
|
||||
import "@material/mwc-button";
|
||||
import "@material/mwc-icon-button";
|
||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||
@@ -270,8 +269,6 @@ class HassioSnapshots extends LitElement {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<supervisor-connectivity .supervisor=${this.supervisor}>
|
||||
</supervisor-connectivity>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -154,8 +154,8 @@ class HassioHostInfo extends LitElement {
|
||||
)}
|
||||
</span>
|
||||
<span slot="description">
|
||||
${this.supervisor.host.disk_life_time - 10}% -
|
||||
${this.supervisor.host.disk_life_time}%
|
||||
${this.supervisor.host.disk_life_time - 10} % -
|
||||
${this.supervisor.host.disk_life_time} %
|
||||
</span>
|
||||
</ha-settings-row>`
|
||||
: ""}
|
||||
|
||||
@@ -48,6 +48,7 @@ const UNSUPPORTED_REASON_URL = {
|
||||
os: "/more-info/unsupported/os",
|
||||
privileged: "/more-info/unsupported/privileged",
|
||||
systemd: "/more-info/unsupported/systemd",
|
||||
content_trust: "/more-info/unsupported/content_trust",
|
||||
};
|
||||
|
||||
const UNHEALTHY_REASON_URL = {
|
||||
@@ -55,6 +56,7 @@ const UNHEALTHY_REASON_URL = {
|
||||
supervisor: "/more-info/unhealthy/supervisor",
|
||||
setup: "/more-info/unhealthy/setup",
|
||||
docker: "/more-info/unhealthy/docker",
|
||||
untrusted: "/more-info/unhealthy/untrusted",
|
||||
};
|
||||
|
||||
@customElement("hassio-supervisor-info")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "../components/supervisor-connectivity";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
@@ -63,8 +62,6 @@ class HassioSystem extends LitElement {
|
||||
.supervisor=${this.supervisor}
|
||||
></hassio-supervisor-log>
|
||||
</div>
|
||||
<supervisor-connectivity .supervisor=${this.supervisor}>
|
||||
</supervisor-connectivity>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
+2
-1
@@ -25,7 +25,7 @@
|
||||
"@braintree/sanitize-url": "^5.0.0",
|
||||
"@codemirror/commands": "^0.18.0",
|
||||
"@codemirror/gutter": "^0.18.0",
|
||||
"@codemirror/highlight": "^0.18.1",
|
||||
"@codemirror/highlight": "^0.18.0",
|
||||
"@codemirror/history": "^0.18.0",
|
||||
"@codemirror/legacy-modes": "^0.18.0",
|
||||
"@codemirror/rectangular-selection": "^0.18.0",
|
||||
@@ -132,6 +132,7 @@
|
||||
"sortablejs": "^1.10.2",
|
||||
"superstruct": "^0.10.13",
|
||||
"tinykeys": "^1.1.1",
|
||||
"tsparticles": "^1.19.2",
|
||||
"unfetch": "^4.1.0",
|
||||
"vis-data": "^7.1.1",
|
||||
"vis-network": "^8.5.4",
|
||||
|
||||
@@ -2,12 +2,12 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="home-assistant-frontend",
|
||||
version="20210302.0",
|
||||
version="20210324.0",
|
||||
description="The Home Assistant frontend",
|
||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||
author="The Home Assistant Authors",
|
||||
author_email="hello@home-assistant.io",
|
||||
license="Apache License 2.0",
|
||||
license="Apache-2.0",
|
||||
packages=find_packages(include=["hass_frontend", "hass_frontend.*"]),
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
|
||||
@@ -56,6 +56,8 @@ export const FIXED_DOMAIN_ICONS = {
|
||||
|
||||
export const FIXED_DEVICE_CLASS_ICONS = {
|
||||
current: "hass:current-ac",
|
||||
carbon_dioxide: "mdi:molecule-co2",
|
||||
carbon_monoxide: "mdi:molecule-co",
|
||||
energy: "hass:flash",
|
||||
humidity: "hass:water-percent",
|
||||
illuminance: "hass:brightness-5",
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
const isTemplateRegex = new RegExp("{%|{{|{#");
|
||||
export const isTemplate = (value: string): boolean =>
|
||||
isTemplateRegex.test(value);
|
||||
|
||||
export const hasTemplate = (value: unknown): boolean => {
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
if (typeof value === "string") {
|
||||
return isTemplate(value);
|
||||
}
|
||||
if (typeof value === "object") {
|
||||
const values = Array.isArray(value) ? value : Object.values(value!);
|
||||
return values.some((val) => hasTemplate(val));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -236,20 +236,19 @@ export class HaDataTable extends LitElement {
|
||||
"auto-height": this.autoHeight,
|
||||
})}"
|
||||
role="table"
|
||||
aria-rowcount=${this._filteredData.length}
|
||||
aria-rowcount=${this._filteredData.length + 1}
|
||||
style=${styleMap({
|
||||
height: this.autoHeight
|
||||
? `${(this._filteredData.length || 1) * 53 + 57}px`
|
||||
: `calc(100% - ${this._headerHeight}px)`,
|
||||
})}
|
||||
>
|
||||
<div class="mdc-data-table__header-row" role="row">
|
||||
<div class="mdc-data-table__header-row" role="row" aria-rowindex="1">
|
||||
${this.selectable
|
||||
? html`
|
||||
<div
|
||||
class="mdc-data-table__header-cell mdc-data-table__header-cell--checkbox"
|
||||
role="columnheader"
|
||||
scope="col"
|
||||
>
|
||||
<ha-checkbox
|
||||
class="mdc-data-table__row-checkbox"
|
||||
@@ -292,7 +291,13 @@ export class HaDataTable extends LitElement {
|
||||
})
|
||||
: ""}
|
||||
role="columnheader"
|
||||
scope="col"
|
||||
aria-sort=${ifDefined(
|
||||
sorted
|
||||
? this._sortDirection === "desc"
|
||||
? "descending"
|
||||
: "ascending"
|
||||
: undefined
|
||||
)}
|
||||
@click=${this._handleHeaderClick}
|
||||
.columnId=${key}
|
||||
>
|
||||
@@ -338,7 +343,7 @@ export class HaDataTable extends LitElement {
|
||||
}
|
||||
return html`
|
||||
<div
|
||||
aria-rowindex=${index}
|
||||
aria-rowindex=${index! + 2}
|
||||
role="row"
|
||||
.rowId=${row[this.id]}
|
||||
@click=${this._handleRowClick}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { forwardHaptic } from "../../data/haptics";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import "../ha-icon-button";
|
||||
import "../ha-switch";
|
||||
import "../ha-formfield";
|
||||
|
||||
const isOn = (stateObj?: HassEntity) =>
|
||||
stateObj !== undefined &&
|
||||
@@ -29,6 +30,8 @@ export class HaEntityToggle extends LitElement {
|
||||
|
||||
@property() public stateObj?: HassEntity;
|
||||
|
||||
@property() public label?: string;
|
||||
|
||||
@internalProperty() private _isOn = false;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
@@ -55,15 +58,21 @@ export class HaEntityToggle extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
const switchTemplate = html`<ha-switch
|
||||
aria-label=${`Toggle ${computeStateName(this.stateObj)} ${
|
||||
this._isOn ? "off" : "on"
|
||||
}`}
|
||||
.checked=${this._isOn}
|
||||
.disabled=${UNAVAILABLE_STATES.includes(this.stateObj.state)}
|
||||
@change=${this._toggleChanged}
|
||||
></ha-switch>`;
|
||||
|
||||
if (!this.label) {
|
||||
return switchTemplate;
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-switch
|
||||
aria-label=${`Toggle ${computeStateName(this.stateObj)} ${
|
||||
this._isOn ? "off" : "on"
|
||||
}`}
|
||||
.checked=${this._isOn}
|
||||
.disabled=${UNAVAILABLE_STATES.includes(this.stateObj.state)}
|
||||
@change=${this._toggleChanged}
|
||||
></ha-switch>
|
||||
<ha-formfield .label=${this.label}>${switchTemplate}</ha-formfield>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
|
||||
this._devices = devices;
|
||||
}),
|
||||
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
||||
this._entities = entities.filter((entity) => entity.area_id);
|
||||
this._entities = entities;
|
||||
}),
|
||||
];
|
||||
}
|
||||
@@ -193,13 +193,13 @@ export class HaAreaPicker extends SubscribeMixin(LitElement) {
|
||||
deviceEntityLookup[entity.device_id].push(entity);
|
||||
}
|
||||
inputDevices = devices;
|
||||
inputEntities = entities;
|
||||
inputEntities = entities.filter((entity) => entity.area_id);
|
||||
} else {
|
||||
if (deviceFilter) {
|
||||
inputDevices = devices;
|
||||
}
|
||||
if (entityFilter) {
|
||||
inputEntities = entities;
|
||||
inputEntities = entities.filter((entity) => entity.area_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ class HaClimateState extends LitElement {
|
||||
)}-${formatNumber(
|
||||
this.stateObj.attributes.target_humidity_high,
|
||||
this.hass!.language
|
||||
)}%`;
|
||||
)} %`;
|
||||
}
|
||||
|
||||
if (this.stateObj.attributes.humidity != null) {
|
||||
|
||||
@@ -47,6 +47,17 @@ export class HaCodeEditor extends UpdatingElement {
|
||||
return this.codemirror ? this.codemirror.state.doc.toString() : this._value;
|
||||
}
|
||||
|
||||
public get hasComments(): boolean {
|
||||
if (!this.codemirror || !this._loadedCodeMirror) {
|
||||
return false;
|
||||
}
|
||||
const className = this._loadedCodeMirror.HighlightStyle.get(
|
||||
this.codemirror.state,
|
||||
this._loadedCodeMirror.tags.comment
|
||||
);
|
||||
return !!this.shadowRoot!.querySelector(`span.${className}`);
|
||||
}
|
||||
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
if (!this.codemirror) {
|
||||
|
||||
@@ -36,6 +36,7 @@ interface ExtHassService extends Omit<HassService, "fields"> {
|
||||
example?: any;
|
||||
selector?: Selector;
|
||||
}[];
|
||||
hasSelector: string[];
|
||||
}
|
||||
|
||||
@customElement("ha-service-control")
|
||||
@@ -52,8 +53,6 @@ export class HaServiceControl extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public showAdvanced?: boolean;
|
||||
|
||||
@internalProperty() private _serviceData?: ExtHassService;
|
||||
|
||||
@internalProperty() private _checkedKeys = new Set();
|
||||
|
||||
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
|
||||
@@ -70,13 +69,11 @@ export class HaServiceControl extends LitElement {
|
||||
this._checkedKeys = new Set();
|
||||
}
|
||||
|
||||
this._serviceData = this.value?.service
|
||||
? this._getServiceInfo(this.value.service)
|
||||
: undefined;
|
||||
const serviceData = this._getServiceInfo(this.value?.service);
|
||||
|
||||
if (
|
||||
this._serviceData &&
|
||||
"target" in this._serviceData &&
|
||||
serviceData &&
|
||||
"target" in serviceData &&
|
||||
(this.value?.data?.entity_id ||
|
||||
this.value?.data?.area_id ||
|
||||
this.value?.data?.device_id)
|
||||
@@ -119,7 +116,7 @@ export class HaServiceControl extends LitElement {
|
||||
return ENTITY_COMPONENT_DOMAINS.includes(domain) ? [domain] : null;
|
||||
});
|
||||
|
||||
private _getServiceInfo = memoizeOne((service: string):
|
||||
private _getServiceInfo = memoizeOne((service?: string):
|
||||
| ExtHassService
|
||||
| undefined => {
|
||||
if (!service) {
|
||||
@@ -147,23 +144,29 @@ export class HaServiceControl extends LitElement {
|
||||
return {
|
||||
...serviceDomains[domain][serviceName],
|
||||
fields,
|
||||
hasSelector: fields.length
|
||||
? fields.filter((field) => field.selector).map((field) => field.key)
|
||||
: [],
|
||||
};
|
||||
});
|
||||
|
||||
protected render() {
|
||||
const legacy =
|
||||
this._serviceData?.fields.length &&
|
||||
!this._serviceData.fields.some((field) => field.selector);
|
||||
const serviceData = this._getServiceInfo(this.value?.service);
|
||||
|
||||
const shouldRenderServiceDataYaml =
|
||||
(serviceData?.fields.length && !serviceData.hasSelector.length) ||
|
||||
(serviceData &&
|
||||
Object.keys(this.value?.data || {}).some(
|
||||
(key) => !serviceData!.hasSelector.includes(key)
|
||||
));
|
||||
|
||||
const entityId =
|
||||
legacy &&
|
||||
this._serviceData?.fields.find((field) => field.key === "entity_id");
|
||||
shouldRenderServiceDataYaml &&
|
||||
serviceData?.fields.find((field) => field.key === "entity_id");
|
||||
|
||||
const hasOptional = Boolean(
|
||||
!legacy &&
|
||||
this._serviceData?.fields.some(
|
||||
(field) => field.selector && !field.required
|
||||
)
|
||||
!shouldRenderServiceDataYaml &&
|
||||
serviceData?.fields.some((field) => field.selector && !field.required)
|
||||
);
|
||||
|
||||
return html`<ha-service-picker
|
||||
@@ -171,8 +174,8 @@ export class HaServiceControl extends LitElement {
|
||||
.value=${this.value?.service}
|
||||
@value-changed=${this._serviceChanged}
|
||||
></ha-service-picker>
|
||||
<p>${this._serviceData?.description}</p>
|
||||
${this._serviceData && "target" in this._serviceData
|
||||
<p>${serviceData?.description}</p>
|
||||
${serviceData && "target" in serviceData
|
||||
? html`<ha-settings-row .narrow=${this.narrow}>
|
||||
${hasOptional
|
||||
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
||||
@@ -188,8 +191,8 @@ export class HaServiceControl extends LitElement {
|
||||
)}</span
|
||||
><ha-selector
|
||||
.hass=${this.hass}
|
||||
.selector=${this._serviceData.target
|
||||
? { target: this._serviceData.target }
|
||||
.selector=${serviceData.target
|
||||
? { target: serviceData.target }
|
||||
: {
|
||||
target: {
|
||||
entity: { domain: computeDomain(this.value!.service) },
|
||||
@@ -209,7 +212,7 @@ export class HaServiceControl extends LitElement {
|
||||
allow-custom-entity
|
||||
></ha-entity-picker>`
|
||||
: ""}
|
||||
${legacy
|
||||
${shouldRenderServiceDataYaml
|
||||
? html`<ha-yaml-editor
|
||||
.label=${this.hass.localize(
|
||||
"ui.components.service-control.service_data"
|
||||
@@ -218,8 +221,12 @@ export class HaServiceControl extends LitElement {
|
||||
.defaultValue=${this.value?.data}
|
||||
@value-changed=${this._dataChanged}
|
||||
></ha-yaml-editor>`
|
||||
: this._serviceData?.fields.map((dataField) =>
|
||||
dataField.selector && (!dataField.advanced || this.showAdvanced)
|
||||
: serviceData?.fields.map((dataField) =>
|
||||
dataField.selector &&
|
||||
(!dataField.advanced ||
|
||||
this.showAdvanced ||
|
||||
(this.value?.data &&
|
||||
this.value.data[dataField.key] !== undefined))
|
||||
? html`<ha-settings-row .narrow=${this.narrow}>
|
||||
${dataField.required
|
||||
? hasOptional
|
||||
|
||||
@@ -107,6 +107,10 @@ export class PaperTimeInput extends PolymerElement {
|
||||
#millisec {
|
||||
width: 38px;
|
||||
}
|
||||
|
||||
.no-suffix {
|
||||
margin-left: -2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<label hidden$="[[hideLabel]]">[[label]]</label>
|
||||
@@ -134,6 +138,7 @@ export class PaperTimeInput extends PolymerElement {
|
||||
|
||||
<!-- Min Input -->
|
||||
<paper-input
|
||||
class$="[[_computeClassNames(enableSecond)]]"
|
||||
id="min"
|
||||
type="number"
|
||||
value="{{min}}"
|
||||
@@ -155,6 +160,7 @@ export class PaperTimeInput extends PolymerElement {
|
||||
|
||||
<!-- Sec Input -->
|
||||
<paper-input
|
||||
class$="[[_computeClassNames(enableMillisecond)]]"
|
||||
id="sec"
|
||||
type="number"
|
||||
value="{{sec}}"
|
||||
@@ -479,6 +485,10 @@ export class PaperTimeInput extends PolymerElement {
|
||||
_equal(n1, n2) {
|
||||
return n1 === n2;
|
||||
}
|
||||
|
||||
_computeClassNames(hasSuffix) {
|
||||
return hasSuffix ? " " : "no-suffix";
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("paper-time-input", PaperTimeInput);
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import { mdiCircleOutline } from "@mdi/js";
|
||||
import {
|
||||
LitElement,
|
||||
customElement,
|
||||
html,
|
||||
css,
|
||||
property,
|
||||
TemplateResult,
|
||||
internalProperty,
|
||||
} from "lit-element";
|
||||
import { buttonLinkStyle } from "../../resources/styles";
|
||||
import "../ha-svg-icon";
|
||||
|
||||
@customElement("ha-timeline")
|
||||
class HaTimeline extends LitElement {
|
||||
@property({ type: Boolean, reflect: true }) public label = false;
|
||||
|
||||
@property({ type: Boolean }) public lastItem = false;
|
||||
|
||||
@property({ type: String }) public icon?: string;
|
||||
|
||||
@property({ attribute: false }) public moreItems?: TemplateResult[];
|
||||
|
||||
@internalProperty() private _showMore = false;
|
||||
|
||||
protected render() {
|
||||
return html`
|
||||
<div class="timeline-start">
|
||||
${this.label
|
||||
? ""
|
||||
: html`
|
||||
<ha-svg-icon .path=${this.icon || mdiCircleOutline}></ha-svg-icon>
|
||||
`}
|
||||
${this.lastItem ? "" : html`<div class="line"></div>`}
|
||||
</div>
|
||||
<div class="content">
|
||||
<slot></slot>
|
||||
${!this.moreItems
|
||||
? ""
|
||||
: html`
|
||||
<div>
|
||||
${this._showMore ||
|
||||
// If there is only 1 item hidden behind "show more", just show it
|
||||
// instead of showing the more info link. We're not animals.
|
||||
this.moreItems.length === 1
|
||||
? this.moreItems
|
||||
: html`
|
||||
<button class="link" @click=${this._handleShowMore}>
|
||||
Show ${this.moreItems.length} more items
|
||||
</button>
|
||||
`}
|
||||
</div>
|
||||
`}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleShowMore() {
|
||||
this._showMore = true;
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
:host(:not([lastItem])) {
|
||||
min-height: 50px;
|
||||
}
|
||||
:host([label]) {
|
||||
margin-top: -8px;
|
||||
font-style: italic;
|
||||
color: var(--timeline-label-color, var(--secondary-text-color));
|
||||
}
|
||||
.timeline-start {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-right: 8px;
|
||||
width: 24px;
|
||||
}
|
||||
ha-svg-icon {
|
||||
color: var(
|
||||
--timeline-ball-color,
|
||||
var(--timeline-color, var(--secondary-text-color))
|
||||
);
|
||||
}
|
||||
.line {
|
||||
flex: 1;
|
||||
width: 2px;
|
||||
background-color: var(
|
||||
--timeline-line-color,
|
||||
var(--timeline-color, var(--secondary-text-color))
|
||||
);
|
||||
margin: 4px 0;
|
||||
}
|
||||
.content {
|
||||
margin-top: 2px;
|
||||
}
|
||||
:host(:not([lastItem])) .content {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
:host([label]) .content {
|
||||
margin-top: 0;
|
||||
padding-top: 6px;
|
||||
}
|
||||
`,
|
||||
buttonLinkStyle,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-timeline": HaTimeline;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,450 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
|
||||
import {
|
||||
AutomationTraceExtended,
|
||||
ChooseActionTrace,
|
||||
getDataFromPath,
|
||||
} from "../../data/trace";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import "./ha-timeline";
|
||||
import {
|
||||
mdiCheckCircleOutline,
|
||||
mdiCircle,
|
||||
mdiCircleOutline,
|
||||
mdiPauseCircleOutline,
|
||||
mdiRecordCircleOutline,
|
||||
mdiStopCircleOutline,
|
||||
} from "@mdi/js";
|
||||
import { LogbookEntry } from "../../data/logbook";
|
||||
import { getActionType } from "../../data/script";
|
||||
import relativeTime from "../../common/datetime/relative_time";
|
||||
|
||||
const LOGBOOK_ENTRIES_BEFORE_FOLD = 2;
|
||||
|
||||
const pathToName = (path: string) => path.split("/").join(" ");
|
||||
|
||||
/* eslint max-classes-per-file: "off" */
|
||||
|
||||
// Report time entry when more than this time has passed
|
||||
const SIGNIFICANT_TIME_CHANGE = 5000; // 5 seconds
|
||||
|
||||
const isSignificantTimeChange = (a: Date, b: Date) =>
|
||||
Math.abs(b.getTime() - a.getTime()) > SIGNIFICANT_TIME_CHANGE;
|
||||
|
||||
class RenderedTimeTracker {
|
||||
private lastReportedTime: Date;
|
||||
|
||||
constructor(
|
||||
private hass: HomeAssistant,
|
||||
private entries: TemplateResult[],
|
||||
trace: AutomationTraceExtended
|
||||
) {
|
||||
this.lastReportedTime = new Date(trace.timestamp.start);
|
||||
}
|
||||
|
||||
setLastReportedTime(date: Date) {
|
||||
this.lastReportedTime = date;
|
||||
}
|
||||
|
||||
renderTime(from: Date, to: Date): void {
|
||||
this.entries.push(html`
|
||||
<ha-timeline label>
|
||||
${relativeTime(from, this.hass.localize, {
|
||||
compareTime: to,
|
||||
includeTense: false,
|
||||
})}
|
||||
later
|
||||
</ha-timeline>
|
||||
`);
|
||||
this.lastReportedTime = to;
|
||||
}
|
||||
|
||||
maybeRenderTime(timestamp: Date): boolean {
|
||||
if (!isSignificantTimeChange(timestamp, this.lastReportedTime)) {
|
||||
this.lastReportedTime = timestamp;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.renderTime(this.lastReportedTime, timestamp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class LogbookRenderer {
|
||||
private curIndex: number;
|
||||
|
||||
private pendingItems: Array<[Date, LogbookEntry]> = [];
|
||||
|
||||
constructor(
|
||||
private entries: TemplateResult[],
|
||||
private timeTracker: RenderedTimeTracker,
|
||||
private logbookEntries: LogbookEntry[]
|
||||
) {
|
||||
// Skip the "automation got triggered item"
|
||||
this.curIndex =
|
||||
logbookEntries.length > 0 && logbookEntries[0].domain === "automation"
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
get curItem() {
|
||||
return this.logbookEntries[this.curIndex];
|
||||
}
|
||||
|
||||
get hasNext() {
|
||||
return this.curIndex !== this.logbookEntries.length;
|
||||
}
|
||||
|
||||
maybeRenderItem() {
|
||||
const logbookEntry = this.curItem;
|
||||
this.curIndex++;
|
||||
const entryDate = new Date(logbookEntry.when);
|
||||
|
||||
if (this.pendingItems.length === 0) {
|
||||
this.pendingItems.push([entryDate, logbookEntry]);
|
||||
return;
|
||||
}
|
||||
|
||||
const previousEntryDate = this.pendingItems[
|
||||
this.pendingItems.length - 1
|
||||
][0];
|
||||
|
||||
// If logbook entry is too long after the last one,
|
||||
// add a time passed label
|
||||
if (isSignificantTimeChange(previousEntryDate, entryDate)) {
|
||||
this._renderLogbookEntries();
|
||||
this.timeTracker.renderTime(previousEntryDate, entryDate);
|
||||
}
|
||||
|
||||
this.pendingItems.push([entryDate, logbookEntry]);
|
||||
}
|
||||
|
||||
flush() {
|
||||
if (this.pendingItems.length > 0) {
|
||||
this._renderLogbookEntries();
|
||||
}
|
||||
}
|
||||
|
||||
private _renderLogbookEntries() {
|
||||
this.timeTracker.maybeRenderTime(this.pendingItems[0][0]);
|
||||
|
||||
const parts: TemplateResult[] = [];
|
||||
|
||||
let i;
|
||||
|
||||
for (
|
||||
i = 0;
|
||||
i < Math.min(this.pendingItems.length, LOGBOOK_ENTRIES_BEFORE_FOLD);
|
||||
i++
|
||||
) {
|
||||
parts.push(this._renderLogbookEntryHelper(this.pendingItems[i][1]));
|
||||
}
|
||||
|
||||
let moreItems: TemplateResult[] | undefined;
|
||||
|
||||
// If we didn't render all items, push rest into `moreItems`
|
||||
if (i < this.pendingItems.length) {
|
||||
moreItems = [];
|
||||
for (; i < this.pendingItems.length; i++) {
|
||||
moreItems.push(this._renderLogbookEntryHelper(this.pendingItems[i][1]));
|
||||
}
|
||||
}
|
||||
|
||||
this.entries.push(html`
|
||||
<ha-timeline .icon=${mdiCircleOutline} .moreItems=${moreItems}>
|
||||
${parts}
|
||||
</ha-timeline>
|
||||
`);
|
||||
|
||||
// Clear rendered items.
|
||||
this.timeTracker.setLastReportedTime(
|
||||
this.pendingItems[this.pendingItems.length - 1][0]
|
||||
);
|
||||
this.pendingItems = [];
|
||||
}
|
||||
|
||||
private _renderLogbookEntryHelper(entry: LogbookEntry) {
|
||||
return html`${entry.name} (${entry.entity_id}) turned ${entry.state}<br />`;
|
||||
}
|
||||
}
|
||||
|
||||
class ActionRenderer {
|
||||
private curIndex = 0;
|
||||
|
||||
private keys: string[];
|
||||
|
||||
constructor(
|
||||
private entries: TemplateResult[],
|
||||
private trace: AutomationTraceExtended,
|
||||
private timeTracker: RenderedTimeTracker
|
||||
) {
|
||||
this.keys = Object.keys(trace.action_trace);
|
||||
}
|
||||
|
||||
get curItem() {
|
||||
return this._getItem(this.curIndex);
|
||||
}
|
||||
|
||||
get hasNext() {
|
||||
return this.curIndex !== this.keys.length;
|
||||
}
|
||||
|
||||
renderItem() {
|
||||
this.curIndex = this._renderItem(this.curIndex);
|
||||
}
|
||||
|
||||
private _getItem(index: number) {
|
||||
return this.trace.action_trace[this.keys[index]];
|
||||
}
|
||||
|
||||
private _renderItem(
|
||||
index: number,
|
||||
actionType?: ReturnType<typeof getActionType>
|
||||
): number {
|
||||
const value = this._getItem(index);
|
||||
const timestamp = new Date(value[0].timestamp);
|
||||
|
||||
this.timeTracker.maybeRenderTime(timestamp);
|
||||
|
||||
const path = value[0].path;
|
||||
let data;
|
||||
try {
|
||||
data = getDataFromPath(this.trace.config, path);
|
||||
} catch (err) {
|
||||
this.entries.push(
|
||||
html`Unable to extract path ${path}. Download trace and report as bug`
|
||||
);
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
const isTopLevel = path.split("/").length === 2;
|
||||
|
||||
if (!isTopLevel && !actionType) {
|
||||
this._renderEntry(path.replace(/\//g, " "));
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
if (!actionType) {
|
||||
actionType = getActionType(data);
|
||||
}
|
||||
|
||||
if (actionType === "choose") {
|
||||
return this._handleChoose(index);
|
||||
}
|
||||
|
||||
this._renderEntry(data.alias || actionType);
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
private _handleChoose(index: number): number {
|
||||
// startLevel: choose root config
|
||||
|
||||
// +1: 'default
|
||||
// +2: executed sequence
|
||||
|
||||
// +1: 'choose'
|
||||
// +2: current choice
|
||||
|
||||
// +3: 'conditions'
|
||||
// +4: evaluated condition
|
||||
|
||||
// +3: 'sequence'
|
||||
// +4: executed sequence
|
||||
|
||||
const startLevel = this.keys[index].split("/").length - 1;
|
||||
|
||||
const chooseTrace = this._getItem(index)[0] as ChooseActionTrace;
|
||||
const defaultExecuted = chooseTrace.result.choice === "default";
|
||||
|
||||
if (defaultExecuted) {
|
||||
this._renderEntry(`Choose: Default action executed`);
|
||||
} else {
|
||||
this._renderEntry(`Choose: Choice ${chooseTrace.result.choice} executed`);
|
||||
}
|
||||
|
||||
let i;
|
||||
|
||||
// Skip over conditions
|
||||
for (i = index + 1; i < this.keys.length; i++) {
|
||||
const parts = this.keys[i].split("/");
|
||||
|
||||
// We're done if no more sequence in current level
|
||||
if (parts.length <= startLevel) {
|
||||
return i;
|
||||
}
|
||||
|
||||
// We're going to skip all conditions
|
||||
if (parts[startLevel + 3] === "sequence") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Render choice
|
||||
while (i < this.keys.length) {
|
||||
const path = this.keys[i];
|
||||
const parts = path.split("/");
|
||||
|
||||
// We're done if no more sequence in current level
|
||||
if (parts.length <= startLevel) {
|
||||
return i;
|
||||
}
|
||||
|
||||
// We know it's an action sequence, so force the type like that
|
||||
// for rendering.
|
||||
i = this._renderItem(i, getActionType(this._getDataFromPath(path)));
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private _renderEntry(description: string) {
|
||||
this.entries.push(html`
|
||||
<ha-timeline .icon=${mdiRecordCircleOutline}>
|
||||
${description}
|
||||
</ha-timeline>
|
||||
`);
|
||||
}
|
||||
|
||||
private _getDataFromPath(path: string) {
|
||||
return getDataFromPath(this.trace.config, path);
|
||||
}
|
||||
}
|
||||
|
||||
@customElement("hat-trace")
|
||||
export class HaAutomationTracer extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) private trace?: AutomationTraceExtended;
|
||||
|
||||
@property({ attribute: false }) private logbookEntries?: LogbookEntry[];
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this.trace) {
|
||||
return html``;
|
||||
}
|
||||
const entries = [
|
||||
html`
|
||||
<ha-timeline .icon=${mdiCircle}>
|
||||
Triggered by the ${this.trace.variables.trigger.description} at
|
||||
${formatDateTimeWithSeconds(
|
||||
new Date(this.trace.timestamp.start),
|
||||
this.hass.language
|
||||
)}
|
||||
</ha-timeline>
|
||||
`,
|
||||
];
|
||||
|
||||
if (this.trace.condition_trace) {
|
||||
for (const [path, value] of Object.entries(this.trace.condition_trace)) {
|
||||
entries.push(html`
|
||||
<ha-timeline
|
||||
?lastItem=${!value[0].result.result}
|
||||
class="condition"
|
||||
.icon=${value[0].result.result
|
||||
? mdiCheckCircleOutline
|
||||
: mdiStopCircleOutline}
|
||||
>
|
||||
${getDataFromPath(this.trace!.config, path).alias ||
|
||||
pathToName(path)}
|
||||
${value[0].result.result ? "passed" : "failed"}
|
||||
</ha-timeline>
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.trace.action_trace && this.logbookEntries) {
|
||||
const timeTracker = new RenderedTimeTracker(
|
||||
this.hass,
|
||||
entries,
|
||||
this.trace
|
||||
);
|
||||
const logbookRenderer = new LogbookRenderer(
|
||||
entries,
|
||||
timeTracker,
|
||||
this.logbookEntries
|
||||
);
|
||||
const actionRenderer = new ActionRenderer(
|
||||
entries,
|
||||
this.trace,
|
||||
timeTracker
|
||||
);
|
||||
|
||||
while (logbookRenderer.hasNext && actionRenderer.hasNext) {
|
||||
// Find next item time-wise.
|
||||
const logbookItem = logbookRenderer.curItem;
|
||||
const actionTrace = actionRenderer.curItem;
|
||||
const actionTimestamp = new Date(actionTrace[0].timestamp);
|
||||
|
||||
if (new Date(logbookItem.when) > actionTimestamp) {
|
||||
logbookRenderer.flush();
|
||||
actionRenderer.renderItem();
|
||||
} else {
|
||||
logbookRenderer.maybeRenderItem();
|
||||
}
|
||||
}
|
||||
|
||||
while (logbookRenderer.hasNext) {
|
||||
logbookRenderer.maybeRenderItem();
|
||||
}
|
||||
|
||||
logbookRenderer.flush();
|
||||
|
||||
while (actionRenderer.hasNext) {
|
||||
actionRenderer.renderItem();
|
||||
}
|
||||
}
|
||||
|
||||
// null means it was stopped by a condition
|
||||
if (this.trace.last_action !== null) {
|
||||
entries.push(html`
|
||||
<ha-timeline
|
||||
lastItem
|
||||
.icon=${this.trace.timestamp.finish
|
||||
? mdiCircle
|
||||
: mdiPauseCircleOutline}
|
||||
>
|
||||
${this.trace.timestamp.finish
|
||||
? html`Finished at
|
||||
${formatDateTimeWithSeconds(
|
||||
new Date(this.trace.timestamp.finish),
|
||||
this.hass.language
|
||||
)}
|
||||
(runtime:
|
||||
${(
|
||||
(new Date(this.trace.timestamp.finish!).getTime() -
|
||||
new Date(this.trace.timestamp.start).getTime()) /
|
||||
1000
|
||||
).toFixed(2)}
|
||||
seconds)`
|
||||
: "Still running"}
|
||||
</ha-timeline>
|
||||
`);
|
||||
}
|
||||
|
||||
return html`${entries}`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
css`
|
||||
ha-timeline[lastItem].condition {
|
||||
--timeline-ball-color: var(--error-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hat-trace": HaAutomationTracer;
|
||||
}
|
||||
}
|
||||
+19
-1
@@ -28,6 +28,17 @@ export interface ManualAutomationConfig {
|
||||
action: Action[];
|
||||
mode?: typeof MODES[number];
|
||||
max?: number;
|
||||
max_exceeded?:
|
||||
| "silent"
|
||||
| "critical"
|
||||
| "fatal"
|
||||
| "error"
|
||||
| "warning"
|
||||
| "warn"
|
||||
| "info"
|
||||
| "debug"
|
||||
| "notset";
|
||||
variables?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface BlueprintAutomationConfig extends ManualAutomationConfig {
|
||||
@@ -45,7 +56,7 @@ export interface StateTrigger {
|
||||
entity_id: string;
|
||||
attribute?: string;
|
||||
from?: string | number;
|
||||
to?: string | number;
|
||||
to?: string | string[] | number;
|
||||
for?: string | number | ForDict;
|
||||
}
|
||||
|
||||
@@ -149,11 +160,13 @@ export type Trigger =
|
||||
|
||||
export interface LogicalCondition {
|
||||
condition: "and" | "not" | "or";
|
||||
alias?: string;
|
||||
conditions: Condition[];
|
||||
}
|
||||
|
||||
export interface StateCondition {
|
||||
condition: "state";
|
||||
alias?: string;
|
||||
entity_id: string;
|
||||
attribute?: string;
|
||||
state: string | number;
|
||||
@@ -162,6 +175,7 @@ export interface StateCondition {
|
||||
|
||||
export interface NumericStateCondition {
|
||||
condition: "numeric_state";
|
||||
alias?: string;
|
||||
entity_id: string;
|
||||
attribute?: string;
|
||||
above?: number;
|
||||
@@ -171,6 +185,7 @@ export interface NumericStateCondition {
|
||||
|
||||
export interface SunCondition {
|
||||
condition: "sun";
|
||||
alias?: string;
|
||||
after_offset: number;
|
||||
before_offset: number;
|
||||
after: "sunrise" | "sunset";
|
||||
@@ -179,12 +194,14 @@ export interface SunCondition {
|
||||
|
||||
export interface ZoneCondition {
|
||||
condition: "zone";
|
||||
alias?: string;
|
||||
entity_id: string;
|
||||
zone: string;
|
||||
}
|
||||
|
||||
export interface TimeCondition {
|
||||
condition: "time";
|
||||
alias?: string;
|
||||
after?: string;
|
||||
before?: string;
|
||||
weekday?: string | string[];
|
||||
@@ -192,6 +209,7 @@ export interface TimeCondition {
|
||||
|
||||
export interface TemplateCondition {
|
||||
condition: "template";
|
||||
alias?: string;
|
||||
value_template: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,18 @@ import { HaFormSchema } from "../components/ha-form/ha-form";
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
export interface DeviceAutomation {
|
||||
alias?: string;
|
||||
device_id: string;
|
||||
domain: string;
|
||||
entity_id: string;
|
||||
entity_id?: string;
|
||||
type?: string;
|
||||
subtype?: string;
|
||||
event?: string;
|
||||
}
|
||||
|
||||
export type DeviceAction = DeviceAutomation;
|
||||
export interface DeviceAction extends DeviceAutomation {
|
||||
entity_id: string;
|
||||
}
|
||||
|
||||
export interface DeviceCondition extends DeviceAutomation {
|
||||
condition: string;
|
||||
|
||||
@@ -50,8 +50,6 @@ export interface WifiConfiguration {
|
||||
export interface NetworkInfo {
|
||||
interfaces: NetworkInterface[];
|
||||
docker: DockerNetwork;
|
||||
supervisor_internet: boolean;
|
||||
host_internet: boolean | null;
|
||||
}
|
||||
|
||||
export const fetchNetworkInfo = async (
|
||||
|
||||
+38
-7
@@ -14,7 +14,9 @@ export interface LogbookEntry {
|
||||
message?: string;
|
||||
entity_id?: string;
|
||||
icon?: string;
|
||||
domain: string;
|
||||
source?: string;
|
||||
domain?: string;
|
||||
context_id?: string;
|
||||
context_user_id?: string;
|
||||
context_event_type?: string;
|
||||
context_domain?: string;
|
||||
@@ -29,6 +31,20 @@ const DATA_CACHE: {
|
||||
[cacheKey: string]: { [entityId: string]: Promise<LogbookEntry[]> };
|
||||
} = {};
|
||||
|
||||
export const getLogbookDataForContext = async (
|
||||
hass: HomeAssistant,
|
||||
startDate: string,
|
||||
contextId?: string
|
||||
) =>
|
||||
getLogbookDataFromServer(
|
||||
hass,
|
||||
startDate,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
contextId
|
||||
);
|
||||
|
||||
export const getLogbookData = async (
|
||||
hass: HomeAssistant,
|
||||
startDate: string,
|
||||
@@ -100,15 +116,30 @@ export const getLogbookDataCache = async (
|
||||
const getLogbookDataFromServer = async (
|
||||
hass: HomeAssistant,
|
||||
startDate: string,
|
||||
endDate: string,
|
||||
endDate?: string,
|
||||
entityId?: string,
|
||||
entity_matches_only?: boolean
|
||||
entitymatchesOnly?: boolean,
|
||||
contextId?: string
|
||||
) => {
|
||||
const url = `logbook/${startDate}?end_time=${endDate}${
|
||||
entityId ? `&entity=${entityId}` : ""
|
||||
}${entity_matches_only ? `&entity_matches_only` : ""}`;
|
||||
const params = new URLSearchParams();
|
||||
|
||||
return hass.callApi<LogbookEntry[]>("GET", url);
|
||||
if (endDate) {
|
||||
params.append("end_time", endDate);
|
||||
}
|
||||
if (entityId) {
|
||||
params.append("entity", entityId);
|
||||
}
|
||||
if (entitymatchesOnly) {
|
||||
params.append("entity_matches_only", "");
|
||||
}
|
||||
if (contextId) {
|
||||
params.append("context_id", contextId);
|
||||
}
|
||||
|
||||
return hass.callApi<LogbookEntry[]>(
|
||||
"GET",
|
||||
`logbook/${startDate}?${params.toString()}`
|
||||
);
|
||||
};
|
||||
|
||||
export const clearLogbookCache = (startDate: string, endDate: string) => {
|
||||
|
||||
+54
-2
@@ -29,12 +29,14 @@ export interface ScriptConfig {
|
||||
}
|
||||
|
||||
export interface EventAction {
|
||||
alias?: string;
|
||||
event: string;
|
||||
event_data?: Record<string, any>;
|
||||
event_data_template?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface ServiceAction {
|
||||
alias?: string;
|
||||
service: string;
|
||||
entity_id?: string;
|
||||
target?: HassServiceTarget;
|
||||
@@ -42,6 +44,7 @@ export interface ServiceAction {
|
||||
}
|
||||
|
||||
export interface DeviceAction {
|
||||
alias?: string;
|
||||
device_id: string;
|
||||
domain: string;
|
||||
entity_id: string;
|
||||
@@ -55,26 +58,31 @@ export interface DelayActionParts {
|
||||
days?: number;
|
||||
}
|
||||
export interface DelayAction {
|
||||
delay: number | Partial<DelayActionParts>;
|
||||
alias?: string;
|
||||
delay: number | Partial<DelayActionParts> | string;
|
||||
}
|
||||
|
||||
export interface SceneAction {
|
||||
alias?: string;
|
||||
scene: string;
|
||||
}
|
||||
|
||||
export interface WaitAction {
|
||||
alias?: string;
|
||||
wait_template: string;
|
||||
timeout?: number;
|
||||
continue_on_timeout?: boolean;
|
||||
}
|
||||
|
||||
export interface WaitForTriggerAction {
|
||||
alias?: string;
|
||||
wait_for_trigger: Trigger[];
|
||||
timeout?: number;
|
||||
continue_on_timeout?: boolean;
|
||||
}
|
||||
|
||||
export interface RepeatAction {
|
||||
alias?: string;
|
||||
repeat: CountRepeat | WhileRepeat | UntilRepeat;
|
||||
}
|
||||
|
||||
@@ -95,7 +103,13 @@ export interface UntilRepeat extends BaseRepeat {
|
||||
}
|
||||
|
||||
export interface ChooseAction {
|
||||
choose: [{ conditions: Condition[]; sequence: Action[] }];
|
||||
choose: [
|
||||
{
|
||||
alias?: string;
|
||||
conditions: string | Condition[];
|
||||
sequence: Action[];
|
||||
}
|
||||
];
|
||||
default?: Action[];
|
||||
}
|
||||
|
||||
@@ -149,3 +163,41 @@ export const getScriptEditorInitData = () => {
|
||||
inititialScriptEditorData = undefined;
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getActionType = (action: Action) => {
|
||||
// Check based on config_validation.py#determine_script_action
|
||||
if ("delay" in action) {
|
||||
return "delay";
|
||||
}
|
||||
if ("wait_template" in action) {
|
||||
return "wait_template";
|
||||
}
|
||||
if ("condition" in action) {
|
||||
return "check_condition";
|
||||
}
|
||||
if ("event" in action) {
|
||||
return "fire_event";
|
||||
}
|
||||
if ("device_id" in action) {
|
||||
return "device_action";
|
||||
}
|
||||
if ("scene" in action) {
|
||||
return "activate_scene";
|
||||
}
|
||||
if ("repeat" in action) {
|
||||
return "repeat";
|
||||
}
|
||||
if ("choose" in action) {
|
||||
return "choose";
|
||||
}
|
||||
if ("wait_for_trigger" in action) {
|
||||
return "wait_for_trigger";
|
||||
}
|
||||
if ("variables" in action) {
|
||||
return "variables";
|
||||
}
|
||||
if ("service" in action) {
|
||||
return "service";
|
||||
}
|
||||
return "unknown";
|
||||
};
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { HomeAssistant } from "../types";
|
||||
import { Action } from "./script";
|
||||
|
||||
export const callExecuteScript = (hass: HomeAssistant, sequence: Action[]) =>
|
||||
hass.callWS({
|
||||
type: "execute_script",
|
||||
sequence,
|
||||
});
|
||||
@@ -0,0 +1,140 @@
|
||||
import { HomeAssistant, Context } from "../types";
|
||||
import { AutomationConfig } from "./automation";
|
||||
|
||||
interface TraceVariables extends Record<string, unknown> {
|
||||
trigger: {
|
||||
description: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
}
|
||||
|
||||
interface BaseTrace {
|
||||
path: string;
|
||||
timestamp: string;
|
||||
changed_variables?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface ConditionTrace extends BaseTrace {
|
||||
result: { result: boolean };
|
||||
}
|
||||
|
||||
export interface CallServiceActionTrace extends BaseTrace {
|
||||
result: {
|
||||
limit: number;
|
||||
running_script: boolean;
|
||||
params: Record<string, unknown>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ChooseActionTrace extends BaseTrace {
|
||||
result: { choice: number | "default" };
|
||||
}
|
||||
|
||||
export interface ChooseChoiceActionTrace extends BaseTrace {
|
||||
result: { result: boolean };
|
||||
}
|
||||
|
||||
export type ActionTrace =
|
||||
| BaseTrace
|
||||
| CallServiceActionTrace
|
||||
| ChooseActionTrace
|
||||
| ChooseChoiceActionTrace;
|
||||
|
||||
export interface AutomationTrace {
|
||||
domain: string;
|
||||
item_id: string;
|
||||
last_action: string | null;
|
||||
last_condition: string | null;
|
||||
run_id: string;
|
||||
state: "running" | "stopped" | "debugged";
|
||||
timestamp: {
|
||||
start: string;
|
||||
finish: string | null;
|
||||
};
|
||||
trigger: unknown;
|
||||
}
|
||||
|
||||
export interface AutomationTraceExtended extends AutomationTrace {
|
||||
condition_trace: Record<string, ConditionTrace[]>;
|
||||
action_trace: Record<string, ActionTrace[]>;
|
||||
context: Context;
|
||||
variables: TraceVariables;
|
||||
config: AutomationConfig;
|
||||
}
|
||||
|
||||
interface TraceTypes {
|
||||
automation: {
|
||||
short: AutomationTrace;
|
||||
extended: AutomationTraceExtended;
|
||||
};
|
||||
}
|
||||
|
||||
export const loadTrace = <T extends keyof TraceTypes>(
|
||||
hass: HomeAssistant,
|
||||
domain: T,
|
||||
item_id: string,
|
||||
run_id: string
|
||||
): Promise<TraceTypes[T]["extended"]> =>
|
||||
hass.callWS({
|
||||
type: "trace/get",
|
||||
domain,
|
||||
item_id,
|
||||
run_id,
|
||||
});
|
||||
|
||||
export const loadTraces = <T extends keyof TraceTypes>(
|
||||
hass: HomeAssistant,
|
||||
domain: T,
|
||||
item_id: string
|
||||
): Promise<Array<TraceTypes[T]["short"]>> =>
|
||||
hass.callWS({
|
||||
type: "trace/list",
|
||||
domain,
|
||||
item_id,
|
||||
});
|
||||
|
||||
export type TraceContexts = Record<
|
||||
string,
|
||||
{ run_id: string; domain: string; item_id: string }
|
||||
>;
|
||||
|
||||
export const loadTraceContexts = (
|
||||
hass: HomeAssistant,
|
||||
domain?: string,
|
||||
item_id?: string
|
||||
): Promise<TraceContexts> =>
|
||||
hass.callWS({
|
||||
type: "trace/contexts",
|
||||
domain,
|
||||
item_id,
|
||||
});
|
||||
|
||||
export const getDataFromPath = (
|
||||
config: AutomationConfig,
|
||||
path: string
|
||||
): any => {
|
||||
const parts = path.split("/").reverse();
|
||||
|
||||
let result: any = config;
|
||||
|
||||
while (parts.length) {
|
||||
const raw = parts.pop()!;
|
||||
const asNumber = Number(raw);
|
||||
|
||||
if (isNaN(asNumber)) {
|
||||
result = result[raw];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(result)) {
|
||||
result = result[asNumber];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (asNumber !== 0) {
|
||||
throw new Error("If config is not an array, can only return index 0");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
@@ -28,6 +28,34 @@ export interface ZWaveJSNode {
|
||||
status: number;
|
||||
}
|
||||
|
||||
export interface ZWaveJSNodeConfigParams {
|
||||
property: number;
|
||||
value: any;
|
||||
configuration_value_type: string;
|
||||
metadata: ZWaveJSNodeConfigParamMetadata;
|
||||
}
|
||||
|
||||
export interface ZWaveJSNodeConfigParamMetadata {
|
||||
description: string;
|
||||
label: string;
|
||||
max: number;
|
||||
min: number;
|
||||
readable: boolean;
|
||||
writeable: boolean;
|
||||
type: string;
|
||||
unit: string;
|
||||
states: { [key: number]: string };
|
||||
}
|
||||
|
||||
export interface ZWaveJSSetConfigParamData {
|
||||
type: string;
|
||||
entry_id: string;
|
||||
node_id: number;
|
||||
property: number;
|
||||
property_key?: number;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
export enum NodeStatus {
|
||||
Unknown,
|
||||
Asleep,
|
||||
@@ -58,6 +86,36 @@ export const fetchNodeStatus = (
|
||||
node_id,
|
||||
});
|
||||
|
||||
export const fetchNodeConfigParameters = (
|
||||
hass: HomeAssistant,
|
||||
entry_id: string,
|
||||
node_id: number
|
||||
): Promise<ZWaveJSNodeConfigParams[]> =>
|
||||
hass.callWS({
|
||||
type: "zwave_js/get_config_parameters",
|
||||
entry_id,
|
||||
node_id,
|
||||
});
|
||||
|
||||
export const setNodeConfigParameter = (
|
||||
hass: HomeAssistant,
|
||||
entry_id: string,
|
||||
node_id: number,
|
||||
property: number,
|
||||
value: number,
|
||||
property_key?: number
|
||||
): Promise<unknown> => {
|
||||
const data: ZWaveJSSetConfigParamData = {
|
||||
type: "zwave_js/set_config_parameter",
|
||||
entry_id,
|
||||
node_id,
|
||||
property,
|
||||
value,
|
||||
property_key,
|
||||
};
|
||||
return hass.callWS(data);
|
||||
};
|
||||
|
||||
export const getIdentifiersFromDevice = function (
|
||||
device: DeviceRegistryEntry
|
||||
): ZWaveJSNodeIdentifiers | undefined {
|
||||
|
||||
@@ -123,7 +123,7 @@ class MoreInfoVacuum extends LitElement {
|
||||
<div>
|
||||
<span>
|
||||
<ha-icon .icon=${stateObj.attributes.battery_icon}></ha-icon>
|
||||
${stateObj.attributes.battery_level}%
|
||||
${stateObj.attributes.battery_level} %
|
||||
</span>
|
||||
</div>
|
||||
`
|
||||
|
||||
@@ -9,10 +9,12 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { closeDialog } from "../make-dialog-manager";
|
||||
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||
import { throttle } from "../../common/util/throttle";
|
||||
import "../../components/ha-circular-progress";
|
||||
import "../../components/state-history-charts";
|
||||
import { TraceContexts, loadTraceContexts } from "../../data/trace";
|
||||
import { getLogbookData, LogbookEntry } from "../../data/logbook";
|
||||
import "../../panels/logbook/ha-logbook";
|
||||
import { haStyle, haStyleScrollbar } from "../../resources/styles";
|
||||
@@ -26,6 +28,8 @@ export class MoreInfoLogbook extends LitElement {
|
||||
|
||||
@internalProperty() private _logbookEntries?: LogbookEntry[];
|
||||
|
||||
@internalProperty() private _traceContexts?: TraceContexts;
|
||||
|
||||
@internalProperty() private _persons = {};
|
||||
|
||||
private _lastLogbookDate?: Date;
|
||||
@@ -63,6 +67,7 @@ export class MoreInfoLogbook extends LitElement {
|
||||
relative-time
|
||||
.hass=${this.hass}
|
||||
.entries=${this._logbookEntries}
|
||||
.traceContexts=${this._traceContexts}
|
||||
.userIdToName=${this._persons}
|
||||
></ha-logbook>
|
||||
`
|
||||
@@ -75,6 +80,11 @@ export class MoreInfoLogbook extends LitElement {
|
||||
|
||||
protected firstUpdated(): void {
|
||||
this._fetchPersonNames();
|
||||
this.addEventListener("click", (ev) => {
|
||||
if ((ev.composedPath()[0] as HTMLElement).tagName === "A") {
|
||||
setTimeout(() => closeDialog("ha-more-info-dialog"), 500);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
@@ -115,17 +125,21 @@ export class MoreInfoLogbook extends LitElement {
|
||||
this._lastLogbookDate ||
|
||||
new Date(new Date().getTime() - 24 * 60 * 60 * 1000);
|
||||
const now = new Date();
|
||||
const newEntries = await getLogbookData(
|
||||
this.hass,
|
||||
lastDate.toISOString(),
|
||||
now.toISOString(),
|
||||
this.entityId,
|
||||
true
|
||||
);
|
||||
const [newEntries, traceContexts] = await Promise.all([
|
||||
getLogbookData(
|
||||
this.hass,
|
||||
lastDate.toISOString(),
|
||||
now.toISOString(),
|
||||
this.entityId,
|
||||
true
|
||||
),
|
||||
loadTraceContexts(this.hass),
|
||||
]);
|
||||
this._logbookEntries = this._logbookEntries
|
||||
? [...newEntries, ...this._logbookEntries]
|
||||
: newEntries;
|
||||
this._lastLogbookDate = now;
|
||||
this._traceContexts = traceContexts;
|
||||
}
|
||||
|
||||
private _fetchPersonNames() {
|
||||
|
||||
@@ -9,6 +9,7 @@ import "../resources/safari-14-attachshadow-patch";
|
||||
import { createCustomPanelElement } from "../util/custom-panel/create-custom-panel-element";
|
||||
import { loadCustomPanel } from "../util/custom-panel/load-custom-panel";
|
||||
import { setCustomPanelProperties } from "../util/custom-panel/set-custom-panel-properties";
|
||||
import { baseEntrypointStyles } from "../resources/styles";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -41,6 +42,7 @@ function initialize(
|
||||
properties: Record<string, unknown>
|
||||
) {
|
||||
const style = document.createElement("style");
|
||||
|
||||
style.innerHTML = "body{margin:0}";
|
||||
document.head.appendChild(style);
|
||||
|
||||
@@ -86,7 +88,24 @@ function initialize(
|
||||
(err) => {
|
||||
// eslint-disable-next-line
|
||||
console.error(err, panel);
|
||||
alert(`Unable to load the panel source: ${err}.`);
|
||||
let errorScreen;
|
||||
if (panel.url_path === "hassio") {
|
||||
import("../layouts/supervisor-error-screen");
|
||||
errorScreen = document.createElement(
|
||||
"supervisor-error-screen"
|
||||
) as any;
|
||||
} else {
|
||||
import("../layouts/hass-error-screen");
|
||||
errorScreen = document.createElement("hass-error-screen") as any;
|
||||
errorScreen.error = `Unable to load the panel source: ${err}.`;
|
||||
}
|
||||
|
||||
const errorStyle = document.createElement("style");
|
||||
errorStyle.innerHTML = baseEntrypointStyles.cssText;
|
||||
document.body.appendChild(errorStyle);
|
||||
|
||||
errorScreen.hass = properties.hass;
|
||||
document.body.appendChild(errorScreen);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
// eslint-disable-next-line spaced-comment
|
||||
/// <reference path="../types/service-worker.d.ts" />
|
||||
/* eslint-env serviceworker */
|
||||
import { cacheNames } from "workbox-core";
|
||||
import { cacheNames, RouteHandler } from "workbox-core";
|
||||
import { cleanupOutdatedCaches, precacheAndRoute } from "workbox-precaching";
|
||||
import { registerRoute } from "workbox-routing";
|
||||
import { registerRoute, setCatchHandler } from "workbox-routing";
|
||||
import {
|
||||
CacheFirst,
|
||||
NetworkOnly,
|
||||
StaleWhileRevalidate,
|
||||
} from "workbox-strategies";
|
||||
|
||||
const noFallBackRegEx = new RegExp(
|
||||
`${location.host}/(api|static|auth|frontend_latest|frontend_es5|local)/.*`
|
||||
);
|
||||
|
||||
// Clean up caches from older workboxes and old service workers.
|
||||
// Will help with cleaning up Workbox v4 stuff
|
||||
cleanupOutdatedCaches();
|
||||
@@ -18,13 +22,17 @@ cleanupOutdatedCaches();
|
||||
function initRouting() {
|
||||
precacheAndRoute(
|
||||
// @ts-ignore
|
||||
WB_MANIFEST
|
||||
WB_MANIFEST,
|
||||
{
|
||||
// Ignore all URL parameters.
|
||||
ignoreURLParametersMatching: [/.*/],
|
||||
}
|
||||
);
|
||||
|
||||
// Cache static content (including translations) on first access.
|
||||
registerRoute(
|
||||
new RegExp(`${location.host}/(static|frontend_latest|frontend_es5)/.+`),
|
||||
new CacheFirst()
|
||||
new CacheFirst({ matchOptions: { ignoreSearch: true } })
|
||||
);
|
||||
|
||||
// Get api from network.
|
||||
@@ -41,8 +49,14 @@ function initRouting() {
|
||||
new NetworkOnly()
|
||||
);
|
||||
|
||||
// For the root "/" we ignore search
|
||||
registerRoute(
|
||||
new RegExp(`^${location.host}/(\\?.*)?$`),
|
||||
new StaleWhileRevalidate({ matchOptions: { ignoreSearch: true } })
|
||||
);
|
||||
|
||||
// For rest of the files (on Home Assistant domain only) try both cache and network.
|
||||
// This includes the root "/" or "/states" response and user files from "/local".
|
||||
// This includes "/states" response and user files from "/local".
|
||||
// First access might bring stale data from cache, but a single refresh will bring updated
|
||||
// file.
|
||||
registerRoute(new RegExp(`${location.host}/.*`), new StaleWhileRevalidate());
|
||||
@@ -158,8 +172,15 @@ function initPushNotifications() {
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
// Delete all runtime caching, so that index.html has to be refetched.
|
||||
// And add the new index.html back to the runtime cache
|
||||
const cacheName = cacheNames.runtime;
|
||||
event.waitUntil(caches.delete(cacheName));
|
||||
event.waitUntil(
|
||||
caches.delete(cacheName).then(() =>
|
||||
caches.open(cacheName).then((cache) => {
|
||||
cache.add("/");
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener("activate", () => {
|
||||
@@ -177,5 +198,19 @@ self.addEventListener("message", (message) => {
|
||||
}
|
||||
});
|
||||
|
||||
const catchHandler: RouteHandler = async (options) => {
|
||||
const dest = (options.request as Request).destination;
|
||||
const url = (options.request as Request).url;
|
||||
|
||||
if (dest !== "document" || noFallBackRegEx.test(url)) {
|
||||
return Response.error();
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("Using fallback for request:", options.request);
|
||||
|
||||
return (await caches.match("/", { ignoreSearch: true })) || Response.error();
|
||||
};
|
||||
|
||||
initRouting();
|
||||
setCatchHandler(catchHandler);
|
||||
initPushNotifications();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Home Assistant</title>
|
||||
<link rel="preload" href="<%= latestPageJS %>" as="script" crossorigin="use-credentials" />
|
||||
<link rel="modulepreload" href="<%= latestPageJS %>" crossorigin="use-credentials" />
|
||||
<%= renderTemplate('_header') %>
|
||||
<style>
|
||||
.content {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<% if (!useWDS) { %>
|
||||
<link rel="preload" href="<%= latestCoreJS %>" as="script" crossorigin="use-credentials" />
|
||||
<link rel="preload" href="<%= latestAppJS %>" as="script" crossorigin="use-credentials" />
|
||||
<link rel="modulepreload" href="<%= latestCoreJS %>" crossorigin="use-credentials" />
|
||||
<link rel="modulepreload" href="<%= latestAppJS %>" crossorigin="use-credentials" />
|
||||
<% } %>
|
||||
<%= renderTemplate('_header') %>
|
||||
<title>Home Assistant</title>
|
||||
|
||||
@@ -2,29 +2,21 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Home Assistant</title>
|
||||
<link rel="preload" href="<%= latestPageJS %>" as="script" crossorigin="use-credentials" />
|
||||
<link rel="modulepreload" href="<%= latestPageJS %>" crossorigin="use-credentials" />
|
||||
<%= renderTemplate('_header') %>
|
||||
<style>
|
||||
html {
|
||||
color: var(--primary-text-color, #212121);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
background-color: #111111;
|
||||
color: #e1e1e1;
|
||||
}
|
||||
ha-onboarding {
|
||||
--primary-text-color: #e1e1e1;
|
||||
--secondary-text-color: #9b9b9b;
|
||||
--disabled-text-color: #6f6f6f;
|
||||
--mdc-theme-surface: #1e1e1e;
|
||||
--ha-card-background: #1e1e1e;
|
||||
}
|
||||
background-color: #0277bd !important;
|
||||
}
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
padding: 20px 16px;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
border-radius: 4px;
|
||||
max-width: 432px;
|
||||
margin: 64px auto 0;
|
||||
box-shadow: rgba(0, 0, 0, 0.25) 0px 54px 55px, rgba(0, 0, 0, 0.12) 0px -12px 30px, rgba(0, 0, 0, 0.12) 0px 4px 6px, rgba(0, 0, 0, 0.17) 0px 12px 13px, rgba(0, 0, 0, 0.09) 0px -3px 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -39,12 +31,36 @@
|
||||
.header img {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
color: #e1e1e1;
|
||||
}
|
||||
ha-onboarding {
|
||||
--primary-text-color: #e1e1e1;
|
||||
--secondary-text-color: #9b9b9b;
|
||||
--disabled-text-color: #6f6f6f;
|
||||
--mdc-theme-surface: #1e1e1e;
|
||||
--ha-card-background: #1e1e1e;
|
||||
}
|
||||
.content {
|
||||
background-color: #111111;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 450px) {
|
||||
.content {
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<body id='particles'>
|
||||
<div class="content">
|
||||
<div class="header">
|
||||
<img src="/static/icons/favicon-192x192.png" height="52" />
|
||||
<img src="/static/icons/favicon-192x192.png" height="52" width="52" />
|
||||
Home Assistant
|
||||
</div>
|
||||
|
||||
@@ -76,4 +92,4 @@
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../types";
|
||||
import "./hass-subpage";
|
||||
import "../components/ha-menu-button";
|
||||
import "../components/ha-icon-button-arrow-prev";
|
||||
|
||||
@customElement("hass-error-screen")
|
||||
class HassErrorScreen extends LitElement {
|
||||
@@ -17,22 +18,37 @@ class HassErrorScreen extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public toolbar = true;
|
||||
|
||||
@property({ type: Boolean }) public rootnav = false;
|
||||
|
||||
@property() public narrow?: boolean;
|
||||
|
||||
@property() public error?: string;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
${this.toolbar
|
||||
? html`<div class="toolbar">
|
||||
<ha-icon-button-arrow-prev
|
||||
.hass=${this.hass}
|
||||
@click=${this._handleBack}
|
||||
></ha-icon-button-arrow-prev>
|
||||
${this.rootnav
|
||||
? html`
|
||||
<ha-menu-button
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
></ha-menu-button>
|
||||
`
|
||||
: html`
|
||||
<ha-icon-button-arrow-prev
|
||||
.hass=${this.hass}
|
||||
@click=${this._handleBack}
|
||||
></ha-icon-button-arrow-prev>
|
||||
`}
|
||||
</div>`
|
||||
: ""}
|
||||
<div class="content">
|
||||
<h3>${this.error}</h3>
|
||||
<slot>
|
||||
<mwc-button @click=${this._handleBack}>go back</mwc-button>
|
||||
<mwc-button @click=${this._handleBack}>
|
||||
${this.hass?.localize("ui.panel.error.go_back") || "go back"}
|
||||
</mwc-button>
|
||||
</slot>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -16,13 +16,13 @@ import { HomeAssistant } from "../types";
|
||||
|
||||
@customElement("hass-loading-screen")
|
||||
class HassLoadingScreen extends LitElement {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property({ type: Boolean, attribute: "no-toolbar" })
|
||||
public noToolbar = false;
|
||||
|
||||
@property({ type: Boolean }) public rootnav = false;
|
||||
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property() public narrow?: boolean;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import { customElement, property, PropertyValues } from "lit-element";
|
||||
import { deepActiveElement } from "../common/dom/deep-active-element";
|
||||
import { deepEqual } from "../common/util/deep-equal";
|
||||
import { getDefaultPanel } from "../data/panel";
|
||||
import { CustomPanelInfo } from "../data/panel_custom";
|
||||
import { HomeAssistant, Panels } from "../types";
|
||||
import { removeInitSkeleton } from "../util/init-skeleton";
|
||||
@@ -37,25 +38,6 @@ const COMPONENTS = {
|
||||
import("../panels/media-browser/ha-panel-media-browser"),
|
||||
};
|
||||
|
||||
const getRoutes = (panels: Panels): RouterOptions => {
|
||||
const routes: RouterOptions["routes"] = {};
|
||||
Object.values(panels).forEach((panel) => {
|
||||
const data: RouteOptions = {
|
||||
tag: `ha-panel-${panel.component_name}`,
|
||||
cache: CACHE_URL_PATHS.includes(panel.url_path),
|
||||
};
|
||||
if (panel.component_name in COMPONENTS) {
|
||||
data.load = COMPONENTS[panel.component_name];
|
||||
}
|
||||
routes[panel.url_path] = data;
|
||||
});
|
||||
|
||||
return {
|
||||
showLoading: true,
|
||||
routes,
|
||||
};
|
||||
};
|
||||
|
||||
@customElement("partial-panel-resolver")
|
||||
class PartialPanelResolver extends HassRouterPage {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@@ -144,6 +126,31 @@ class PartialPanelResolver extends HassRouterPage {
|
||||
}
|
||||
}
|
||||
|
||||
private getRoutes(panels: Panels): RouterOptions {
|
||||
const routes: RouterOptions["routes"] = {};
|
||||
Object.values(panels).forEach((panel) => {
|
||||
const data: RouteOptions = {
|
||||
tag: `ha-panel-${panel.component_name}`,
|
||||
cache: CACHE_URL_PATHS.includes(panel.url_path),
|
||||
};
|
||||
if (panel.component_name in COMPONENTS) {
|
||||
data.load = COMPONENTS[panel.component_name];
|
||||
}
|
||||
routes[panel.url_path] = data;
|
||||
});
|
||||
|
||||
return {
|
||||
beforeRender: (page) => {
|
||||
if (!page || !routes[page]) {
|
||||
return getDefaultPanel(this.hass).url_path;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
showLoading: true,
|
||||
routes,
|
||||
};
|
||||
}
|
||||
|
||||
private _onHidden() {
|
||||
this._hiddenTimeout = window.setTimeout(() => {
|
||||
this._hiddenTimeout = undefined;
|
||||
@@ -191,7 +198,7 @@ class PartialPanelResolver extends HassRouterPage {
|
||||
}
|
||||
|
||||
private async _updateRoutes(oldPanels?: HomeAssistant["panels"]) {
|
||||
this.routerOptions = getRoutes(this.hass.panels);
|
||||
this.routerOptions = this.getRoutes(this.hass.panels);
|
||||
|
||||
if (
|
||||
!this._waitForStart &&
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
import "../components/ha-card";
|
||||
import "@material/mwc-button";
|
||||
import {
|
||||
css,
|
||||
CSSResultArray,
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../types";
|
||||
import "./hass-subpage";
|
||||
import "../resources/ha-style";
|
||||
import "../resources/roboto";
|
||||
import { haStyle } from "../resources/styles";
|
||||
import { applyThemesOnElement } from "../common/dom/apply_themes_on_element";
|
||||
import { atLeastVersion } from "../common/config/version";
|
||||
|
||||
@customElement("supervisor-error-screen")
|
||||
class SupervisorErrorScreen extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
protected firstUpdated(changedProps: PropertyValues) {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
this._applyTheme();
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!oldHass) {
|
||||
return;
|
||||
}
|
||||
if (oldHass.themes !== this.hass.themes) {
|
||||
this._applyTheme();
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div class="toolbar">
|
||||
<ha-icon-button-arrow-prev
|
||||
.hass=${this.hass}
|
||||
@click=${this._handleBack}
|
||||
></ha-icon-button-arrow-prev>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
${this.hass.localize("ui.panel.error.supervisor.title")}
|
||||
</div>
|
||||
<ha-card header="Troubleshooting">
|
||||
<div class="card-content">
|
||||
<ol>
|
||||
<li>
|
||||
${this.hass.localize("ui.panel.error.supervisor.wait")}
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
class="supervisor_error-link"
|
||||
href="http://homeassistant.local:4357"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
${this.hass.localize("ui.panel.error.supervisor.observer")}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
${this.hass.localize("ui.panel.error.supervisor.reboot")}
|
||||
</li>
|
||||
<li>
|
||||
<a href="/config/info" target="_parent">
|
||||
${this.hass.localize(
|
||||
"ui.panel.error.supervisor.system_health"
|
||||
)}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://www.home-assistant.io/help/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
${this.hass.localize("ui.panel.error.supervisor.ask")}
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</ha-card>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private _applyTheme() {
|
||||
let themeName: string;
|
||||
let options: Partial<HomeAssistant["selectedTheme"]> | undefined;
|
||||
|
||||
if (atLeastVersion(this.hass.config.version, 0, 114)) {
|
||||
themeName =
|
||||
this.hass.selectedTheme?.theme ||
|
||||
(this.hass.themes.darkMode && this.hass.themes.default_dark_theme
|
||||
? this.hass.themes.default_dark_theme!
|
||||
: this.hass.themes.default_theme);
|
||||
|
||||
options = this.hass.selectedTheme;
|
||||
if (themeName === "default" && options?.dark === undefined) {
|
||||
options = {
|
||||
...this.hass.selectedTheme,
|
||||
dark: this.hass.themes.darkMode,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
themeName =
|
||||
((this.hass.selectedTheme as unknown) as string) ||
|
||||
this.hass.themes.default_theme;
|
||||
}
|
||||
|
||||
applyThemesOnElement(
|
||||
this.parentElement,
|
||||
this.hass.themes,
|
||||
themeName,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
private _handleBack(): void {
|
||||
history.back();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
height: var(--header-height);
|
||||
padding: 0 16px;
|
||||
pointer-events: none;
|
||||
background-color: var(--app-header-background-color);
|
||||
font-weight: 400;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
ha-icon-button-arrow-prev {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.content {
|
||||
color: var(--primary-text-color);
|
||||
display: flex;
|
||||
padding: 16px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.title {
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
line-height: 32px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--mdc-theme-primary);
|
||||
}
|
||||
|
||||
ha-card {
|
||||
width: 600px;
|
||||
margin: 16px;
|
||||
padding: 8px;
|
||||
}
|
||||
@media all and (max-width: 500px) {
|
||||
ha-card {
|
||||
width: calc(100vw - 32px);
|
||||
}
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"supervisor-error-screen": SupervisorErrorScreen;
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,9 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
|
||||
import("./onboarding-core-config");
|
||||
registerServiceWorker(this, false);
|
||||
this.addEventListener("onboarding-step", (ev) => this._handleStepDone(ev));
|
||||
if (window.innerWidth > 450) {
|
||||
import("./particles");
|
||||
}
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
|
||||
@@ -206,7 +206,7 @@ class OnboardingCreateUser extends LitElement {
|
||||
}
|
||||
|
||||
.action {
|
||||
margin: 32px 0;
|
||||
margin: 32px 0 16px;
|
||||
text-align: center;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import { tsParticles } from "tsparticles";
|
||||
|
||||
tsParticles.load("particles", {
|
||||
// autoPlay: true,
|
||||
fullScreen: {
|
||||
enable: true,
|
||||
zIndex: -1,
|
||||
},
|
||||
detectRetina: true,
|
||||
fpsLimit: 60,
|
||||
motion: {
|
||||
disable: false,
|
||||
reduce: {
|
||||
factor: 4,
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
particles: {
|
||||
color: {
|
||||
value: "#fff",
|
||||
animation: {
|
||||
enable: true,
|
||||
speed: 50,
|
||||
sync: false,
|
||||
},
|
||||
},
|
||||
links: {
|
||||
color: {
|
||||
value: "random",
|
||||
},
|
||||
distance: 100,
|
||||
enable: true,
|
||||
frequency: 1,
|
||||
opacity: 0.7,
|
||||
width: 1,
|
||||
},
|
||||
move: {
|
||||
enable: true,
|
||||
speed: 0.5,
|
||||
},
|
||||
number: {
|
||||
density: {
|
||||
enable: true,
|
||||
area: 800,
|
||||
factor: 1000,
|
||||
},
|
||||
limit: 0,
|
||||
value: 50,
|
||||
},
|
||||
opacity: {
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 0.3,
|
||||
},
|
||||
value: 0.5,
|
||||
animation: {
|
||||
destroy: "none",
|
||||
enable: true,
|
||||
minimumValue: 0.3,
|
||||
speed: 0.5,
|
||||
startValue: "random",
|
||||
sync: false,
|
||||
},
|
||||
},
|
||||
size: {
|
||||
random: {
|
||||
enable: true,
|
||||
minimumValue: 1,
|
||||
},
|
||||
value: 3,
|
||||
animation: {
|
||||
destroy: "none",
|
||||
enable: true,
|
||||
minimumValue: 1,
|
||||
speed: 3,
|
||||
startValue: "random",
|
||||
sync: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
pauseOnBlur: true,
|
||||
});
|
||||
@@ -193,12 +193,16 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
</div>
|
||||
${this._warnings
|
||||
? html`<div class="warning">
|
||||
UI editor is not supported for this config:
|
||||
${this.hass.localize("ui.errors.config.editor_not_supported")}:
|
||||
<br />
|
||||
<ul>
|
||||
${this._warnings.map((warning) => html`<li>${warning}</li>`)}
|
||||
</ul>
|
||||
You can still edit your config in YAML.
|
||||
${this._warnings!.length > 0 && this._warnings![0] !== undefined
|
||||
? html` <ul>
|
||||
${this._warnings!.map(
|
||||
(warning) => html`<li>${warning}</li>`
|
||||
)}
|
||||
</ul>`
|
||||
: ""}
|
||||
${this.hass.localize("ui.errors.config.edit_in_yaml_supported")}
|
||||
</div>`
|
||||
: ""}
|
||||
${yamlMode
|
||||
@@ -212,7 +216,11 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
)}
|
||||
`
|
||||
: ""}
|
||||
<h2>Edit in YAML</h2>
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.edit_yaml"
|
||||
)}
|
||||
</h2>
|
||||
<ha-yaml-editor
|
||||
.defaultValue=${this.action}
|
||||
@value-changed=${this._onYamlChange}
|
||||
@@ -329,6 +337,7 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
}
|
||||
|
||||
private _switchYamlMode() {
|
||||
this._warnings = undefined;
|
||||
this._yamlMode = !this._yamlMode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import { customElement, html, LitElement, property } from "lit-element";
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
import { hasTemplate } from "../../../../../common/string/has-template";
|
||||
import "../../../../../components/entity/ha-entity-picker";
|
||||
import { HaFormTimeData } from "../../../../../components/ha-form/ha-form";
|
||||
import "../../../../../components/ha-service-picker";
|
||||
@@ -14,45 +21,57 @@ export class HaDelayAction extends LitElement implements ActionElement {
|
||||
|
||||
@property() public action!: DelayAction;
|
||||
|
||||
@property() public _timeData!: HaFormTimeData;
|
||||
|
||||
public static get defaultConfig() {
|
||||
return { delay: "" };
|
||||
}
|
||||
|
||||
protected render() {
|
||||
let data: HaFormTimeData = {};
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
if (!changedProperties.has("action")) {
|
||||
return;
|
||||
}
|
||||
// Check for templates in action. If found, revert to YAML mode.
|
||||
if (this.action && hasTemplate(this.action)) {
|
||||
fireEvent(
|
||||
this,
|
||||
"ui-mode-not-available",
|
||||
Error(this.hass.localize("ui.errors.config.no_template_editor_support"))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this.action.delay !== "object") {
|
||||
if (isNaN(this.action.delay)) {
|
||||
if (typeof this.action.delay === "string" || isNaN(this.action.delay)) {
|
||||
const parts = this.action.delay?.toString().split(":") || [];
|
||||
data = {
|
||||
this._timeData = {
|
||||
hours: Number(parts[0]) || 0,
|
||||
minutes: Number(parts[1]) || 0,
|
||||
seconds: Number(parts[2]) || 0,
|
||||
milliseconds: Number(parts[3]) || 0,
|
||||
};
|
||||
} else {
|
||||
data = { seconds: this.action.delay };
|
||||
this._timeData = { seconds: this.action.delay };
|
||||
}
|
||||
} else {
|
||||
const { days, minutes, seconds, milliseconds } = this.action.delay;
|
||||
let { hours } = this.action.delay || 0;
|
||||
hours = (hours || 0) + (days || 0) * 24;
|
||||
data = {
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
seconds: seconds,
|
||||
milliseconds: milliseconds,
|
||||
};
|
||||
return;
|
||||
}
|
||||
const { days, minutes, seconds, milliseconds } = this.action.delay;
|
||||
let { hours } = this.action.delay || 0;
|
||||
hours = (hours || 0) + (days || 0) * 24;
|
||||
this._timeData = {
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
seconds: seconds,
|
||||
milliseconds: milliseconds,
|
||||
};
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-time-input
|
||||
.data=${data}
|
||||
enableMillisecond
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-time-input>
|
||||
`;
|
||||
protected render() {
|
||||
return html`<ha-time-input
|
||||
.data=${this._timeData}
|
||||
enableMillisecond
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-time-input>`;
|
||||
}
|
||||
|
||||
private _valueChanged(ev: CustomEvent) {
|
||||
|
||||
@@ -16,6 +16,7 @@ import type { HomeAssistant } from "../../../../../types";
|
||||
import { EntityIdOrAll } from "../../../../../common/structs/is-entity-id";
|
||||
import { ActionElement } from "../ha-automation-action-row";
|
||||
import "../../../../../components/ha-service-control";
|
||||
import { hasTemplate } from "../../../../../common/string/has-template";
|
||||
|
||||
const actionStruct = object({
|
||||
service: optional(string()),
|
||||
@@ -46,6 +47,15 @@ export class HaServiceAction extends LitElement implements ActionElement {
|
||||
assert(this.action, actionStruct);
|
||||
} catch (error) {
|
||||
fireEvent(this, "ui-mode-not-available", error);
|
||||
return;
|
||||
}
|
||||
if (this.action && hasTemplate(this.action)) {
|
||||
fireEvent(
|
||||
this,
|
||||
"ui-mode-not-available",
|
||||
Error(this.hass.localize("ui.errors.config.no_template_editor_support"))
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (this.action.entity_id) {
|
||||
this._action = {
|
||||
|
||||
@@ -63,7 +63,11 @@ export default class HaAutomationConditionEditor extends LitElement {
|
||||
)}
|
||||
`
|
||||
: ""}
|
||||
<h2>Edit in YAML</h2>
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.edit_yaml"
|
||||
)}
|
||||
</h2>
|
||||
<ha-yaml-editor
|
||||
.defaultValue=${this.condition}
|
||||
@value-changed=${this._onYamlChange}
|
||||
|
||||
@@ -197,7 +197,11 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
${this.narrow
|
||||
? html` <span slot="header">${this._config?.alias}</span> `
|
||||
: ""}
|
||||
<div class="content">
|
||||
<div
|
||||
class="content ${classMap({
|
||||
"yaml-mode": this._mode === "yaml",
|
||||
})}"
|
||||
>
|
||||
${this._errors
|
||||
? html` <div class="errors">${this._errors}</div> `
|
||||
: ""}
|
||||
@@ -223,52 +227,52 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
`
|
||||
: this._mode === "yaml"
|
||||
? html`
|
||||
<ha-config-section .isWide=${false}>
|
||||
${!this.narrow
|
||||
? html`
|
||||
<span slot="header">${this._config.alias}</span>
|
||||
`
|
||||
: ``}
|
||||
<ha-card>
|
||||
<div class="card-content">
|
||||
<ha-yaml-editor
|
||||
.defaultValue=${this._preprocessYaml()}
|
||||
@value-changed=${this._yamlChanged}
|
||||
></ha-yaml-editor>
|
||||
<mwc-button @click=${this._copyYaml}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.copy_to_clipboard"
|
||||
)}
|
||||
</mwc-button>
|
||||
</div>
|
||||
${stateObj
|
||||
? html`
|
||||
<div
|
||||
class="card-actions layout horizontal justified center"
|
||||
>
|
||||
<div class="layout horizontal center">
|
||||
<ha-entity-toggle
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
></ha-entity-toggle>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.enable_disable"
|
||||
)}
|
||||
</div>
|
||||
<mwc-button
|
||||
@click=${this._runActions}
|
||||
.stateObj=${stateObj}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.card.automation.trigger"
|
||||
)}
|
||||
</mwc-button>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
</ha-card>
|
||||
<ha-config-section> </ha-config-section
|
||||
></ha-config-section>
|
||||
${!this.narrow
|
||||
? html`
|
||||
<ha-card
|
||||
><div class="card-header">
|
||||
${this._config.alias}
|
||||
</div>
|
||||
${stateObj
|
||||
? html`
|
||||
<div
|
||||
class="card-actions layout horizontal justified center"
|
||||
>
|
||||
<ha-entity-toggle
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.enable_disable"
|
||||
)}
|
||||
></ha-entity-toggle>
|
||||
|
||||
<mwc-button
|
||||
@click=${this._runActions}
|
||||
.stateObj=${stateObj}
|
||||
>
|
||||
${this.hass.localize(
|
||||
"ui.card.automation.trigger"
|
||||
)}
|
||||
</mwc-button>
|
||||
</div>
|
||||
`
|
||||
: ""}
|
||||
</ha-card>
|
||||
`
|
||||
: ``}
|
||||
<ha-yaml-editor
|
||||
.defaultValue=${this._preprocessYaml()}
|
||||
@value-changed=${this._yamlChanged}
|
||||
></ha-yaml-editor>
|
||||
<ha-card
|
||||
><div class="card-actions">
|
||||
<mwc-button @click=${this._copyYaml}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.copy_to_clipboard"
|
||||
)}
|
||||
</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
`
|
||||
: ``}
|
||||
</div>
|
||||
@@ -531,6 +535,22 @@ export class HaAutomationEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
.content {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.yaml-mode {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
ha-yaml-editor {
|
||||
flex-grow: 1;
|
||||
--code-mirror-height: 100%;
|
||||
min-height: 0;
|
||||
}
|
||||
.yaml-mode ha-card {
|
||||
overflow: initial;
|
||||
--ha-card-border-radius: 0;
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,36 @@ class HaAutomationPicker extends LitElement {
|
||||
></ha-icon-button>
|
||||
`,
|
||||
};
|
||||
columns.trace = {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_info, automation: any) => html`
|
||||
<a
|
||||
href=${ifDefined(
|
||||
automation.attributes.id
|
||||
? `/config/automation/trace/${automation.attributes.id}`
|
||||
: undefined
|
||||
)}
|
||||
>
|
||||
<ha-icon-button
|
||||
icon="hass:hammer"
|
||||
.disabled=${!automation.attributes.id}
|
||||
title="${this.hass.localize(
|
||||
"ui.panel.config.automation.picker.dev_automation"
|
||||
)}"
|
||||
></ha-icon-button>
|
||||
</a>
|
||||
${!automation.attributes.id
|
||||
? html`
|
||||
<paper-tooltip animation-delay="0" position="left">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.picker.dev_only_editable"
|
||||
)}
|
||||
</paper-tooltip>
|
||||
`
|
||||
: ""}
|
||||
`,
|
||||
};
|
||||
columns.edit = {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
RouterOptions,
|
||||
} from "../../../layouts/hass-router-page";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import "./ha-automation-editor";
|
||||
import "./ha-automation-picker";
|
||||
import "./ha-automation-editor";
|
||||
|
||||
const equal = (a: AutomationEntity[], b: AutomationEntity[]): boolean => {
|
||||
if (a.length !== b.length) {
|
||||
@@ -48,6 +48,10 @@ class HaConfigAutomation extends HassRouterPage {
|
||||
edit: {
|
||||
tag: "ha-automation-editor",
|
||||
},
|
||||
trace: {
|
||||
tag: "ha-automation-trace",
|
||||
load: () => import("./trace/ha-automation-trace"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -81,7 +85,7 @@ class HaConfigAutomation extends HassRouterPage {
|
||||
|
||||
if (
|
||||
(!changedProps || changedProps.has("route")) &&
|
||||
this._currentPage === "edit"
|
||||
this._currentPage !== "dashboard"
|
||||
) {
|
||||
const automationId = this.routeTail.path.substr(1);
|
||||
pageEl.automationId = automationId === "new" ? null : automationId;
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { AutomationEntity } from "../../../../data/automation";
|
||||
import {
|
||||
AutomationTrace,
|
||||
AutomationTraceExtended,
|
||||
loadTrace,
|
||||
loadTraces,
|
||||
} from "../../../../data/trace";
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/trace/hat-trace";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
import { HomeAssistant, Route } from "../../../../types";
|
||||
import { configSections } from "../../ha-panel-config";
|
||||
import {
|
||||
getLogbookDataForContext,
|
||||
LogbookEntry,
|
||||
} from "../../../../data/logbook";
|
||||
import { formatDateTimeWithSeconds } from "../../../../common/datetime/format_date_time";
|
||||
import { repeat } from "lit-html/directives/repeat";
|
||||
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||
|
||||
@customElement("ha-automation-trace")
|
||||
export class HaAutomationTrace extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public automationId!: string;
|
||||
|
||||
@property() public automations!: AutomationEntity[];
|
||||
|
||||
@property() public isWide?: boolean;
|
||||
|
||||
@property() public narrow!: boolean;
|
||||
|
||||
@property() public route!: Route;
|
||||
|
||||
@internalProperty() private _entityId?: string;
|
||||
|
||||
@internalProperty() private _traces?: AutomationTrace[];
|
||||
|
||||
@internalProperty() private _runId?: string;
|
||||
|
||||
@internalProperty() private _trace?: AutomationTraceExtended;
|
||||
|
||||
@internalProperty() private _logbookEntries?: LogbookEntry[];
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const stateObj = this._entityId
|
||||
? this.hass.states[this._entityId]
|
||||
: undefined;
|
||||
|
||||
return html`
|
||||
<hass-tabs-subpage
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
.backCallback=${() => this._backTapped()}
|
||||
.tabs=${configSections.automation}
|
||||
>
|
||||
<ha-card
|
||||
.header=${`Trace for ${
|
||||
stateObj?.attributes.friendly_name || this._entityId
|
||||
}`}
|
||||
>
|
||||
<div class="actions">
|
||||
${this._traces && this._traces.length > 0
|
||||
? html`
|
||||
<select .value=${this._runId} @change=${this._pickTrace}>
|
||||
${repeat(
|
||||
this._traces,
|
||||
(trace) => trace.run_id,
|
||||
(trace) =>
|
||||
html`<option value=${trace.run_id}
|
||||
>${formatDateTimeWithSeconds(
|
||||
new Date(trace.timestamp.start),
|
||||
this.hass.language
|
||||
)}</option
|
||||
>`
|
||||
)}
|
||||
</select>
|
||||
`
|
||||
: ""}
|
||||
<button @click=${this._loadTraces}>
|
||||
Refresh
|
||||
</button>
|
||||
<button @click=${this._downloadTrace}>
|
||||
Download
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
${this._traces === undefined
|
||||
? "Loading…"
|
||||
: this._traces.length === 0
|
||||
? "No traces found"
|
||||
: this._trace === undefined
|
||||
? "Loading…"
|
||||
: html`
|
||||
<hat-trace
|
||||
.hass=${this.hass}
|
||||
.trace=${this._trace}
|
||||
.logbookEntries=${this._logbookEntries}
|
||||
></hat-trace>
|
||||
`}
|
||||
</div>
|
||||
</ha-card>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
if (!this.automationId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
this._loadTraces(params.get("run_id") || undefined);
|
||||
}
|
||||
|
||||
protected updated(changedProps) {
|
||||
super.updated(changedProps);
|
||||
|
||||
// Only reset if automationId has changed and we had one before.
|
||||
if (changedProps.get("automationId")) {
|
||||
this._traces = undefined;
|
||||
this._entityId = undefined;
|
||||
this._runId = undefined;
|
||||
this._trace = undefined;
|
||||
this._logbookEntries = undefined;
|
||||
if (this.automationId) {
|
||||
this._loadTraces();
|
||||
}
|
||||
}
|
||||
|
||||
if (changedProps.has("_runId") && this._runId) {
|
||||
this._trace = undefined;
|
||||
this._logbookEntries = undefined;
|
||||
this.shadowRoot!.querySelector("select")!.value = this._runId;
|
||||
this._loadTrace();
|
||||
}
|
||||
|
||||
if (
|
||||
changedProps.has("automations") &&
|
||||
this.automationId &&
|
||||
!this._entityId
|
||||
) {
|
||||
const automation = this.automations.find(
|
||||
(entity: AutomationEntity) => entity.attributes.id === this.automationId
|
||||
);
|
||||
this._entityId = automation?.entity_id;
|
||||
}
|
||||
}
|
||||
|
||||
private _pickTrace(ev) {
|
||||
this._runId = ev.target.value;
|
||||
}
|
||||
|
||||
private async _loadTraces(runId?: string) {
|
||||
this._traces = await loadTraces(this.hass, "automation", this.automationId);
|
||||
// Newest will be on top.
|
||||
this._traces.reverse();
|
||||
|
||||
if (runId) {
|
||||
this._runId = runId;
|
||||
}
|
||||
|
||||
// Check if current run ID still exists
|
||||
if (
|
||||
this._runId &&
|
||||
!this._traces.some((trace) => trace.run_id === this._runId)
|
||||
) {
|
||||
this._runId = undefined;
|
||||
|
||||
// If we came here from a trace passed into the url, clear it.
|
||||
if (runId) {
|
||||
const params = new URLSearchParams(location.search);
|
||||
params.delete("run_id");
|
||||
history.replaceState(
|
||||
null,
|
||||
"",
|
||||
`${location.pathname}?${params.toString()}`
|
||||
);
|
||||
}
|
||||
|
||||
await showAlertDialog(this, {
|
||||
text: "Chosen trace is no longer available",
|
||||
});
|
||||
}
|
||||
|
||||
// See if we can set a default runID
|
||||
if (!this._runId && this._traces.length > 0) {
|
||||
this._runId = this._traces[0].run_id;
|
||||
}
|
||||
}
|
||||
|
||||
private async _loadTrace() {
|
||||
const trace = await loadTrace(
|
||||
this.hass,
|
||||
"automation",
|
||||
this.automationId,
|
||||
this._runId!
|
||||
);
|
||||
this._logbookEntries = await getLogbookDataForContext(
|
||||
this.hass,
|
||||
trace.timestamp.start,
|
||||
trace.context.id
|
||||
);
|
||||
|
||||
this._trace = trace;
|
||||
}
|
||||
|
||||
private _backTapped(): void {
|
||||
history.back();
|
||||
}
|
||||
|
||||
private _downloadTrace() {
|
||||
const aEl = document.createElement("a");
|
||||
aEl.download = `trace ${this._entityId} ${
|
||||
this._trace!.timestamp.start
|
||||
}.json`;
|
||||
aEl.href = `data:application/json;charset=utf-8,${encodeURI(
|
||||
JSON.stringify(
|
||||
{
|
||||
trace: this._trace,
|
||||
logbookEntries: this._logbookEntries,
|
||||
},
|
||||
undefined,
|
||||
2
|
||||
)
|
||||
)}`;
|
||||
aEl.click();
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
ha-card {
|
||||
max-width: 800px;
|
||||
margin: 24px auto;
|
||||
}
|
||||
|
||||
.actions {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-automation-trace": HaAutomationTrace;
|
||||
}
|
||||
}
|
||||
@@ -136,7 +136,11 @@ export default class HaAutomationTriggerRow extends LitElement {
|
||||
)}
|
||||
`
|
||||
: ""}
|
||||
<h2>Edit in YAML</h2>
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.edit_yaml"
|
||||
)}
|
||||
</h2>
|
||||
<ha-yaml-editor
|
||||
.defaultValue=${this.trigger}
|
||||
@value-changed=${this._onYamlChange}
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import "@material/mwc-icon-button";
|
||||
import { mdiDelete, mdiDownload, mdiHelpCircle, mdiRobot } from "@mdi/js";
|
||||
import {
|
||||
mdiDelete,
|
||||
mdiDownload,
|
||||
mdiHelpCircle,
|
||||
mdiRobot,
|
||||
mdiShareVariant,
|
||||
} from "@mdi/js";
|
||||
import "@polymer/paper-tooltip/paper-tooltip";
|
||||
import {
|
||||
CSSResult,
|
||||
@@ -140,6 +146,24 @@ class HaBlueprintOverview extends LitElement {
|
||||
)}
|
||||
</mwc-button>`,
|
||||
},
|
||||
share: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
template: (_, blueprint: any) =>
|
||||
blueprint.error
|
||||
? ""
|
||||
: html`<mwc-icon-button
|
||||
.blueprint=${blueprint}
|
||||
.disabled=${!blueprint.source_url}
|
||||
.label=${this.hass.localize(
|
||||
blueprint.source_url
|
||||
? "ui.panel.config.blueprint.overview.share_blueprint"
|
||||
: "ui.panel.config.blueprint.overview.share_blueprint_no_url"
|
||||
)}
|
||||
@click=${(ev) => this._share(ev)}
|
||||
><ha-svg-icon .path=${mdiShareVariant}></ha-svg-icon
|
||||
></mwc-icon-button>`,
|
||||
},
|
||||
delete: {
|
||||
title: "",
|
||||
type: "icon-button",
|
||||
@@ -262,6 +286,16 @@ class HaBlueprintOverview extends LitElement {
|
||||
createNewFunctions[blueprint.domain](this, blueprint);
|
||||
}
|
||||
|
||||
private _share(ev) {
|
||||
const blueprint = ev.currentTarget.blueprint;
|
||||
const params = new URLSearchParams();
|
||||
params.append("redirect", "blueprint_import");
|
||||
params.append("blueprint_url", blueprint.source_url);
|
||||
window.open(
|
||||
`https://my.home-assistant.io/create-link/?${params.toString()}`
|
||||
);
|
||||
}
|
||||
|
||||
private async _delete(ev) {
|
||||
const blueprint = ev.currentTarget.blueprint;
|
||||
if (
|
||||
|
||||
@@ -9,7 +9,10 @@ import {
|
||||
import "../../../../components/ha-card";
|
||||
import "../../../../components/ha-chips";
|
||||
import { showAutomationEditor } from "../../../../data/automation";
|
||||
import { DeviceAutomation } from "../../../../data/device_automation";
|
||||
import {
|
||||
DeviceAction,
|
||||
DeviceAutomation,
|
||||
} from "../../../../data/device_automation";
|
||||
import { showScriptEditor } from "../../../../data/script";
|
||||
import { HomeAssistant } from "../../../../types";
|
||||
|
||||
@@ -79,7 +82,7 @@ export abstract class HaDeviceAutomationCard<
|
||||
return;
|
||||
}
|
||||
if (this.script) {
|
||||
showScriptEditor(this, { sequence: [automation] });
|
||||
showScriptEditor(this, { sequence: [automation as DeviceAction] });
|
||||
return;
|
||||
}
|
||||
const data = {};
|
||||
|
||||
@@ -111,6 +111,7 @@ export class HaDeviceCard extends LitElement {
|
||||
}
|
||||
.extra-info {
|
||||
margin-top: 8px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.manuf,
|
||||
.entity-id,
|
||||
|
||||
+10
@@ -21,6 +21,7 @@ import { haStyle } from "../../../../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../../../../types";
|
||||
import { showZHAClusterDialog } from "../../../../integrations/integration-panels/zha/show-dialog-zha-cluster";
|
||||
import { showZHADeviceZigbeeInfoDialog } from "../../../../integrations/integration-panels/zha/show-dialog-zha-device-zigbee-info";
|
||||
import { showZHADeviceChildrenDialog } from "../../../../integrations/integration-panels/zha/show-dialog-zha-device-children";
|
||||
|
||||
@customElement("ha-device-actions-zha")
|
||||
export class HaDeviceActionsZha extends LitElement {
|
||||
@@ -65,6 +66,11 @@ export class HaDeviceActionsZha extends LitElement {
|
||||
<mwc-button @click=${this._onAddDevicesClick}>
|
||||
${this.hass!.localize("ui.dialogs.zha_device_info.buttons.add")}
|
||||
</mwc-button>
|
||||
<mwc-button @click=${this._handleDeviceChildrenClicked}>
|
||||
${this.hass!.localize(
|
||||
"ui.dialogs.zha_device_info.buttons.device_children"
|
||||
)}
|
||||
</mwc-button>
|
||||
`
|
||||
: ""}
|
||||
${this._zhaDevice.device_type !== "Coordinator"
|
||||
@@ -120,6 +126,10 @@ export class HaDeviceActionsZha extends LitElement {
|
||||
showZHADeviceZigbeeInfoDialog(this, { device: this._zhaDevice! });
|
||||
}
|
||||
|
||||
private async _handleDeviceChildrenClicked() {
|
||||
showZHADeviceChildrenDialog(this, { device: this._zhaDevice! });
|
||||
}
|
||||
|
||||
private async _removeDevice() {
|
||||
const confirmed = await showConfirmationDialog(this, {
|
||||
text: this.hass.localize(
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import {
|
||||
css,
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { DeviceRegistryEntry } from "../../../../../../data/device_registry";
|
||||
import { haStyle } from "../../../../../../resources/styles";
|
||||
|
||||
import { HomeAssistant } from "../../../../../../types";
|
||||
|
||||
@customElement("ha-device-actions-zwave_js")
|
||||
export class HaDeviceActionsZWaveJS extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public device!: DeviceRegistryEntry;
|
||||
|
||||
@internalProperty() private _entryId?: string;
|
||||
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
if (changedProperties.has("device")) {
|
||||
this._entryId = this.device.config_entries[0];
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<a
|
||||
.href=${`/config/zwave_js/node_config/${this.device.id}?config_entry=${this._entryId}`}
|
||||
>
|
||||
<mwc-button>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.device_info.device_config"
|
||||
)}
|
||||
</mwc-button>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -181,15 +181,17 @@ export class HaConfigDevicePage extends LitElement {
|
||||
<span slot="header">
|
||||
${computeDeviceName(device, this.hass)}
|
||||
</span>
|
||||
<ha-icon-button
|
||||
slot="toolbar-icon"
|
||||
icon="hass:pencil"
|
||||
@click=${this._showSettings}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: ""
|
||||
}
|
||||
|
||||
<ha-icon-button
|
||||
slot="toolbar-icon"
|
||||
icon="hass:cog"
|
||||
@click=${this._showSettings}
|
||||
></ha-icon-button>
|
||||
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="header fullwidth">
|
||||
@@ -197,19 +199,25 @@ export class HaConfigDevicePage extends LitElement {
|
||||
this.narrow
|
||||
? ""
|
||||
: html`
|
||||
<div>
|
||||
<h1>${computeDeviceName(device, this.hass)}</h1>
|
||||
${area
|
||||
? html`
|
||||
<a href="/config/areas/area/${area.area_id}"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.integrations.config_entry.area",
|
||||
"area",
|
||||
area.name || "Unnamed Area"
|
||||
)}</a
|
||||
>
|
||||
`
|
||||
: ""}
|
||||
<div class="header-name">
|
||||
<div>
|
||||
<h1>${computeDeviceName(device, this.hass)}</h1>
|
||||
${area
|
||||
? html`
|
||||
<a href="/config/areas/area/${area.area_id}"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.integrations.config_entry.area",
|
||||
"area",
|
||||
area.name || "Unnamed Area"
|
||||
)}</a
|
||||
>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
<ha-icon-button
|
||||
icon="hass:pencil"
|
||||
@click=${this._showSettings}
|
||||
></ha-icon-button>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
@@ -218,7 +226,7 @@ export class HaConfigDevicePage extends LitElement {
|
||||
batteryState
|
||||
? html`
|
||||
<div class="battery">
|
||||
${batteryIsBinary ? "" : batteryState.state + "%"}
|
||||
${batteryIsBinary ? "" : batteryState.state + " %"}
|
||||
<ha-battery-icon
|
||||
.hass=${this.hass!}
|
||||
.batteryStateObj=${batteryState}
|
||||
@@ -614,11 +622,20 @@ export class HaConfigDevicePage extends LitElement {
|
||||
import(
|
||||
"./device-detail/integration-elements/zwave_js/ha-device-info-zwave_js"
|
||||
);
|
||||
import(
|
||||
"./device-detail/integration-elements/zwave_js/ha-device-actions-zwave_js"
|
||||
);
|
||||
templates.push(html`
|
||||
<ha-device-info-zwave_js
|
||||
.hass=${this.hass}
|
||||
.device=${device}
|
||||
></ha-device-info-zwave_js>
|
||||
<div class="card-actions" slot="actions">
|
||||
<ha-device-actions-zwave_js
|
||||
.hass=${this.hass}
|
||||
.device=${device}
|
||||
></ha-device-actions-zwave_js>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
return templates;
|
||||
@@ -780,6 +797,12 @@ export class HaConfigDevicePage extends LitElement {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.column,
|
||||
.fullwidth {
|
||||
padding: 8px;
|
||||
|
||||
@@ -283,8 +283,8 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
title: this.hass.localize("ui.panel.config.devices.data_table.battery"),
|
||||
sortable: true,
|
||||
type: "numeric",
|
||||
width: narrow ? "90px" : "15%",
|
||||
maxWidth: "90px",
|
||||
width: narrow ? "95px" : "15%",
|
||||
maxWidth: "95px",
|
||||
template: (batteryEntityPair: DeviceRowData["battery_entity"]) => {
|
||||
const battery =
|
||||
batteryEntityPair && batteryEntityPair[0]
|
||||
@@ -298,7 +298,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
battery && computeStateDomain(battery) === "binary_sensor";
|
||||
return battery && (batteryIsBinary || !isNaN(battery.state as any))
|
||||
? html`
|
||||
${batteryIsBinary ? "" : battery.state + "%"}
|
||||
${batteryIsBinary ? "" : battery.state + " %"}
|
||||
<ha-battery-icon
|
||||
.hass=${this.hass!}
|
||||
.batteryStateObj=${battery}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
import {
|
||||
CSSResult,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeRTLDirection } from "../../../../../common/util/compute_rtl";
|
||||
import "../../../../../components/ha-code-editor";
|
||||
import { createCloseHeading } from "../../../../../components/ha-dialog";
|
||||
import { haStyleDialog } from "../../../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../../../types";
|
||||
import { ZHADeviceChildrenDialogParams } from "./show-dialog-zha-device-children";
|
||||
import "../../../../../components/data-table/ha-data-table";
|
||||
import type {
|
||||
DataTableColumnContainer,
|
||||
DataTableRowData,
|
||||
} from "../../../../../components/data-table/ha-data-table";
|
||||
import "../../../../../components/ha-circular-progress";
|
||||
import { fetchDevices, ZHADevice } from "../../../../../data/zha";
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
|
||||
export interface DeviceRowData extends DataTableRowData {
|
||||
id: string;
|
||||
name: string;
|
||||
lqi: number;
|
||||
}
|
||||
|
||||
@customElement("dialog-zha-device-children")
|
||||
class DialogZHADeviceChildren extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@internalProperty() private _device: ZHADevice | undefined;
|
||||
|
||||
@internalProperty() private _devices: Map<string, ZHADevice> | undefined;
|
||||
|
||||
private _deviceChildren = memoizeOne(
|
||||
(
|
||||
device: ZHADevice | undefined,
|
||||
devices: Map<string, ZHADevice> | undefined
|
||||
) => {
|
||||
const outputDevices: DeviceRowData[] = [];
|
||||
if (device && devices) {
|
||||
device.neighbors.forEach((child) => {
|
||||
const zhaDevice: ZHADevice | undefined = devices.get(child.ieee);
|
||||
if (zhaDevice) {
|
||||
outputDevices.push({
|
||||
name: zhaDevice.user_given_name || zhaDevice.name,
|
||||
id: zhaDevice.device_reg_id,
|
||||
lqi: child.lqi,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return outputDevices;
|
||||
}
|
||||
);
|
||||
|
||||
private _columns: DataTableColumnContainer = {
|
||||
name: {
|
||||
title: "Name",
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
grows: true,
|
||||
},
|
||||
lqi: {
|
||||
title: "LQI",
|
||||
sortable: true,
|
||||
filterable: true,
|
||||
direction: "asc",
|
||||
width: "75px",
|
||||
},
|
||||
};
|
||||
|
||||
public showDialog(
|
||||
params: ZHADeviceChildrenDialogParams
|
||||
): void {
|
||||
this._device = params.device;
|
||||
this._fetchData();
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this._device = undefined;
|
||||
this._devices = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (!this._device) {
|
||||
return html``;
|
||||
}
|
||||
return html`
|
||||
<ha-dialog
|
||||
hideActions
|
||||
open
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${createCloseHeading(
|
||||
this.hass,
|
||||
this.hass.localize(`ui.dialogs.zha_device_info.device_children`)
|
||||
)}
|
||||
>
|
||||
${!this._devices
|
||||
? html`<ha-circular-progress
|
||||
alt="Loading"
|
||||
size="large"
|
||||
active
|
||||
></ha-circular-progress>`
|
||||
: html`<ha-data-table
|
||||
.columns=${this._columns}
|
||||
.data=${this._deviceChildren(this._device, this._devices)}
|
||||
auto-height
|
||||
.dir=${computeRTLDirection(this.hass)}
|
||||
.searchLabel=${this.hass.localize(
|
||||
"ui.components.data-table.search"
|
||||
)}
|
||||
.noDataText=${this.hass.localize(
|
||||
"ui.components.data-table.no-data"
|
||||
)}
|
||||
></ha-data-table>`}
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private async _fetchData(): Promise<void> {
|
||||
if (this._device && this.hass) {
|
||||
const devices = await fetchDevices(this.hass!);
|
||||
this._devices = new Map(
|
||||
devices.map((device: ZHADevice) => [device.ieee, device])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return haStyleDialog;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"dialog-zha-device-children": DialogZHADeviceChildren;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
import { ZHADevice } from "../../../../../data/zha";
|
||||
|
||||
export interface ZHADeviceChildrenDialogParams {
|
||||
device: ZHADevice;
|
||||
}
|
||||
|
||||
export const loadZHADeviceChildrenDialog = () =>
|
||||
import("./dialog-zha-device-children");
|
||||
|
||||
export const showZHADeviceChildrenDialog = (
|
||||
element: HTMLElement,
|
||||
zhaDeviceChildrenParams: ZHADeviceChildrenDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "dialog-zha-device-children",
|
||||
dialogImport: loadZHADeviceChildrenDialog,
|
||||
dialogParams: zhaDeviceChildrenParams,
|
||||
});
|
||||
};
|
||||
+27
@@ -27,6 +27,8 @@ import "../../../../../components/ha-svg-icon";
|
||||
import { PolymerChangedEvent } from "../../../../../polymer-types";
|
||||
import { formatAsPaddedHex } from "./functions";
|
||||
import { DeviceRegistryEntry } from "../../../../../data/device_registry";
|
||||
import "../../../../../components/ha-checkbox";
|
||||
import type { HaCheckbox } from "../../../../../components/ha-checkbox";
|
||||
|
||||
@customElement("zha-network-visualization-page")
|
||||
export class ZHANetworkVisualizationPage extends LitElement {
|
||||
@@ -55,11 +57,15 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
||||
@internalProperty()
|
||||
private _filter?: string;
|
||||
|
||||
private _autoZoom = true;
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
|
||||
if (this.hass) {
|
||||
this._fetchData();
|
||||
}
|
||||
|
||||
this._network = new Network(
|
||||
this._visualization!,
|
||||
{},
|
||||
@@ -92,6 +98,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
this._network.on("doubleClick", (properties) => {
|
||||
const ieee = properties.nodes[0];
|
||||
if (ieee) {
|
||||
@@ -106,6 +113,17 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
||||
}
|
||||
});
|
||||
|
||||
this._network.on("click", (properties) => {
|
||||
const ieee = properties.nodes[0];
|
||||
if (ieee) {
|
||||
const device = this._devices.get(ieee);
|
||||
if (device && this._autoZoom) {
|
||||
this.zoomedDeviceId = device.device_reg_id;
|
||||
this._zoomToDevice();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this._network.on("stabilized", () => {
|
||||
if (this.zoomedDeviceId) {
|
||||
this._zoomToDevice();
|
||||
@@ -141,6 +159,11 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
||||
.deviceFilter=${(device) => this._filterDevices(device)}
|
||||
@value-changed=${this._onZoomToDevice}
|
||||
></ha-device-picker>
|
||||
<ha-checkbox
|
||||
@change=${this._handleCheckboxChange}
|
||||
.checked=${this._autoZoom}
|
||||
></ha-checkbox
|
||||
>${this.hass!.localize("ui.panel.config.zha.visualization.auto_zoom")}
|
||||
<mwc-button @click=${this._refreshTopology}
|
||||
>${this.hass!.localize(
|
||||
"ui.panel.config.zha.visualization.refresh_topology"
|
||||
@@ -325,6 +348,10 @@ export class ZHANetworkVisualizationPage extends LitElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
private _handleCheckboxChange(ev: Event) {
|
||||
this._autoZoom = (ev.target as HaCheckbox).checked;
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
css`
|
||||
|
||||
+4
-3
@@ -37,6 +37,10 @@ class ZWaveJSConfigRouter extends HassRouterPage {
|
||||
tag: "zwave_js-config-dashboard",
|
||||
load: () => import("./zwave_js-config-dashboard"),
|
||||
},
|
||||
node_config: {
|
||||
tag: "zwave_js-node-config",
|
||||
load: () => import("./zwave_js-node-config"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -46,9 +50,6 @@ class ZWaveJSConfigRouter extends HassRouterPage {
|
||||
el.isWide = this.isWide;
|
||||
el.narrow = this.narrow;
|
||||
el.configEntryId = this._configEntry;
|
||||
if (this._currentPage === "node") {
|
||||
el.nodeId = this.routeTail.path.substr(1);
|
||||
}
|
||||
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
if (this._configEntry && !searchParams.has("config_entry")) {
|
||||
|
||||
@@ -0,0 +1,418 @@
|
||||
import "../../../../../components/ha-settings-row";
|
||||
import "@polymer/paper-item/paper-item";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
||||
import "@material/mwc-button/mwc-button";
|
||||
import "@material/mwc-icon-button/mwc-icon-button";
|
||||
import {
|
||||
css,
|
||||
CSSResultArray,
|
||||
customElement,
|
||||
html,
|
||||
internalProperty,
|
||||
LitElement,
|
||||
property,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit-element";
|
||||
import { debounce } from "../../../../../common/util/debounce";
|
||||
import "../../../../../components/ha-card";
|
||||
import "../../../../../components/ha-svg-icon";
|
||||
import "../../../../../components/ha-icon-next";
|
||||
import "../../../../../components/ha-switch";
|
||||
import {
|
||||
fetchNodeConfigParameters,
|
||||
setNodeConfigParameter,
|
||||
ZWaveJSNodeConfigParams,
|
||||
} from "../../../../../data/zwave_js";
|
||||
import "../../../../../layouts/hass-tabs-subpage";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../../../types";
|
||||
import "../../../ha-config-section";
|
||||
import { configTabs } from "./zwave_js-config-router";
|
||||
import {
|
||||
DeviceRegistryEntry,
|
||||
computeDeviceName,
|
||||
subscribeDeviceRegistry,
|
||||
} from "../../../../../data/device_registry";
|
||||
import { SubscribeMixin } from "../../../../../mixins/subscribe-mixin";
|
||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import memoizeOne from "memoize-one";
|
||||
|
||||
const getDevice = memoizeOne(
|
||||
(
|
||||
deviceId: string,
|
||||
entries?: DeviceRegistryEntry[]
|
||||
): DeviceRegistryEntry | undefined =>
|
||||
entries?.find((device) => device.id === deviceId)
|
||||
);
|
||||
|
||||
const getNodeId = memoizeOne((device: DeviceRegistryEntry):
|
||||
| number
|
||||
| undefined => {
|
||||
const identifier = device.identifiers.find(
|
||||
(ident) => ident[0] === "zwave_js"
|
||||
);
|
||||
if (!identifier) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parseInt(identifier[1].split("-")[1]);
|
||||
});
|
||||
|
||||
@customElement("zwave_js-node-config")
|
||||
class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@property({ type: Boolean }) public narrow!: boolean;
|
||||
|
||||
@property({ type: Boolean }) public isWide!: boolean;
|
||||
|
||||
@property() public configEntryId?: string;
|
||||
|
||||
@property() public deviceId!: string;
|
||||
|
||||
@property({ type: Array })
|
||||
private _deviceRegistryEntries?: DeviceRegistryEntry[];
|
||||
|
||||
@internalProperty() private _config?: ZWaveJSNodeConfigParams[];
|
||||
|
||||
@internalProperty() private _error?: string;
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.deviceId = this.route.path.substr(1);
|
||||
}
|
||||
|
||||
public hassSubscribe(): UnsubscribeFunc[] {
|
||||
return [
|
||||
subscribeDeviceRegistry(this.hass.connection, (entries) => {
|
||||
this._deviceRegistryEntries = entries;
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
if (
|
||||
(!this._config || changedProps.has("deviceId")) &&
|
||||
changedProps.has("_deviceRegistryEntries")
|
||||
) {
|
||||
this._fetchData();
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult {
|
||||
if (this._error) {
|
||||
return html`<hass-error-screen
|
||||
.hass=${this.hass}
|
||||
.error=${this.hass.localize(
|
||||
`ui.panel.config.zwave_js.node_config.error_${this._error}`
|
||||
)}
|
||||
></hass-error-screen>`;
|
||||
}
|
||||
|
||||
if (!this._config) {
|
||||
return html`<hass-loading-screen></hass-loading-screen>`;
|
||||
}
|
||||
|
||||
const device = this._device!;
|
||||
|
||||
return html`
|
||||
<hass-tabs-subpage
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.route=${this.route}
|
||||
.tabs=${configTabs}
|
||||
>
|
||||
<ha-config-section .narrow=${this.narrow} .isWide=${this.isWide}>
|
||||
<div slot="header">
|
||||
${this.hass.localize("ui.panel.config.zwave_js.node_config.header")}
|
||||
</div>
|
||||
|
||||
<div slot="introduction">
|
||||
${device
|
||||
? html`
|
||||
<div class="device-info">
|
||||
<h2>${computeDeviceName(device, this.hass)}</h2>
|
||||
<p>${device.manufacturer} ${device.model}</p>
|
||||
</div>
|
||||
`
|
||||
: ``}
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_config.introduction"
|
||||
)}
|
||||
<p>
|
||||
<em>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_config.attribution",
|
||||
"device_database",
|
||||
html`<a href="https://devices.zwave-js.io/" target="_blank"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_config.zwave_js_device_database"
|
||||
)}</a
|
||||
>`
|
||||
)}
|
||||
</em>
|
||||
</p>
|
||||
</div>
|
||||
<ha-card>
|
||||
${this._config
|
||||
? html`
|
||||
${Object.entries(this._config).map(
|
||||
([id, item]) => html` <ha-settings-row
|
||||
class="content config-item"
|
||||
.configId=${id}
|
||||
.narrow=${this.narrow}
|
||||
>
|
||||
${this._generateConfigBox(id, item)}
|
||||
</ha-settings-row>`
|
||||
)}
|
||||
`
|
||||
: ``}
|
||||
</ha-card>
|
||||
</ha-config-section>
|
||||
</hass-tabs-subpage>
|
||||
`;
|
||||
}
|
||||
|
||||
private _generateConfigBox(id, item): TemplateResult {
|
||||
const labelAndDescription = html`
|
||||
<span slot="heading">${item.metadata.label}</span>
|
||||
<span slot="description">
|
||||
${item.metadata.description}
|
||||
${item.metadata.description !== null && !item.metadata.writeable
|
||||
? html`<br />`
|
||||
: ""}
|
||||
${!item.metadata.writeable
|
||||
? html`<em>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.zwave_js.node_config.parameter_is_read_only"
|
||||
)}
|
||||
</em>`
|
||||
: ""}
|
||||
</span>
|
||||
`;
|
||||
|
||||
// Numeric entries with a min value of 0 and max of 1 are considered boolean
|
||||
if (
|
||||
(item.configuration_value_type === "range" &&
|
||||
item.metadata.min === 0 &&
|
||||
item.metadata.max === 1) ||
|
||||
this._isEnumeratedBool(item)
|
||||
) {
|
||||
return html`
|
||||
${labelAndDescription}
|
||||
<div class="toggle">
|
||||
<ha-switch
|
||||
.property=${item.property}
|
||||
.propertyKey=${item.property_key}
|
||||
.checked=${item.value === 1}
|
||||
.key=${id}
|
||||
@change=${this._switchToggled}
|
||||
.disabled=${!item.metadata.writeable}
|
||||
></ha-switch>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
if (item.configuration_value_type === "range") {
|
||||
return html`${labelAndDescription}
|
||||
<paper-input
|
||||
type="number"
|
||||
.value=${item.value}
|
||||
.min=${item.metadata.min}
|
||||
.max=${item.metadata.max}
|
||||
.property=${item.property}
|
||||
.propertyKey=${item.property_key}
|
||||
.key=${id}
|
||||
.disabled=${!item.metadata.writeable}
|
||||
@value-changed=${this._numericInputChanged}
|
||||
>
|
||||
</paper-input> `;
|
||||
}
|
||||
|
||||
if (item.configuration_value_type === "enumerated") {
|
||||
return html`
|
||||
${labelAndDescription}
|
||||
<div class="flex">
|
||||
<paper-dropdown-menu
|
||||
dynamic-align
|
||||
.disabled=${!item.metadata.writeable}
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
.selected=${item.value}
|
||||
attr-for-selected="value"
|
||||
.key=${id}
|
||||
.property=${item.property}
|
||||
.propertyKey=${item.property_key}
|
||||
@iron-select=${this._dropdownSelected}
|
||||
>
|
||||
${Object.entries(item.metadata.states).map(
|
||||
([key, state]) => html`
|
||||
<paper-item .value=${key}>${state}</paper-item>
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
return html`${labelAndDescription}
|
||||
<p>${item.value}</p>`;
|
||||
}
|
||||
|
||||
private _isEnumeratedBool(item): boolean {
|
||||
// Some Z-Wave config values use a states list with two options where index 0 = Disabled and 1 = Enabled
|
||||
// We want those to be considered boolean and show a toggle switch
|
||||
const disabledStates = ["disable", "disabled"];
|
||||
const enabledStates = ["enable", "enabled"];
|
||||
|
||||
if (item.configuration_value_type !== "enumerated") {
|
||||
return false;
|
||||
}
|
||||
if (!("states" in item.metadata)) {
|
||||
return false;
|
||||
}
|
||||
if (!(0 in item.metadata.states) || !(1 in item.metadata.states)) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
disabledStates.includes(item.metadata.states[0].toLowerCase()) &&
|
||||
enabledStates.includes(item.metadata.states[1].toLowerCase())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _switchToggled(ev) {
|
||||
this._updateConfigParameter(ev.target, ev.target.checked ? 1 : 0);
|
||||
}
|
||||
|
||||
private _dropdownSelected(ev) {
|
||||
if (ev.target === undefined || this._config![ev.target.key] === undefined) {
|
||||
return;
|
||||
}
|
||||
if (this._config![ev.target.key].value === ev.target.selected) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateConfigParameter(ev.target, Number(ev.target.selected));
|
||||
}
|
||||
|
||||
private debouncedUpdate = debounce((target, value) => {
|
||||
this._config![target.key].value = value;
|
||||
|
||||
this._updateConfigParameter(target, value);
|
||||
}, 1000);
|
||||
|
||||
private _numericInputChanged(ev) {
|
||||
if (ev.target === undefined || this._config![ev.target.key] === undefined) {
|
||||
return;
|
||||
}
|
||||
const value = Number(ev.target.value);
|
||||
if (Number(this._config![ev.target.key].value) === value) {
|
||||
return;
|
||||
}
|
||||
this.debouncedUpdate(ev.target, value);
|
||||
}
|
||||
|
||||
private _updateConfigParameter(target, value) {
|
||||
const nodeId = getNodeId(this._device!);
|
||||
setNodeConfigParameter(
|
||||
this.hass,
|
||||
this.configEntryId!,
|
||||
nodeId!,
|
||||
target.property,
|
||||
value,
|
||||
target.propertyKey ? target.propertyKey : undefined
|
||||
);
|
||||
this._config![target.key].value = value;
|
||||
}
|
||||
|
||||
private get _device(): DeviceRegistryEntry | undefined {
|
||||
return getDevice(this.deviceId, this._deviceRegistryEntries);
|
||||
}
|
||||
|
||||
private async _fetchData() {
|
||||
if (!this.configEntryId || !this._deviceRegistryEntries) {
|
||||
return;
|
||||
}
|
||||
|
||||
const device = this._device;
|
||||
if (!device) {
|
||||
this._error = "device_not_found";
|
||||
return;
|
||||
}
|
||||
|
||||
const nodeId = getNodeId(device);
|
||||
if (!nodeId) {
|
||||
this._error = "device_not_found";
|
||||
return;
|
||||
}
|
||||
|
||||
this._config = await fetchNodeConfigParameters(
|
||||
this.hass,
|
||||
this.configEntryId,
|
||||
nodeId!
|
||||
);
|
||||
}
|
||||
|
||||
static get styles(): CSSResultArray {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.secondary {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.flex .config-label,
|
||||
.flex paper-dropdown-menu {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.sectionHeader {
|
||||
position: relative;
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
ha-card {
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
ha-settings-row {
|
||||
--paper-time-input-justify-content: flex-end;
|
||||
border-top: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
:host(:not([narrow])) ha-settings-row paper-input {
|
||||
width: 30%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
ha-card:last-child {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"zwave_js-node-config": ZWaveJSNodeConfig;
|
||||
}
|
||||
}
|
||||
@@ -72,11 +72,7 @@ class DialogSystemLogDetail extends LitElement {
|
||||
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<span slot="title">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.logs.details",
|
||||
"level",
|
||||
item.level
|
||||
)}
|
||||
${this.hass.localize("ui.panel.config.logs.details", "level", html`<span class="${item.level.toLowerCase()}">${item.level}</span>`)}
|
||||
</span>
|
||||
<mwc-icon-button id="copy" @click=${this._copyLog} slot="actionItems">
|
||||
<ha-svg-icon .path=${mdiContentCopy}></ha-svg-icon>
|
||||
@@ -176,6 +172,12 @@ class DialogSystemLogDetail extends LitElement {
|
||||
margin-bottom: 0;
|
||||
font-family: var(--code-font-family, monospace);
|
||||
}
|
||||
.error {
|
||||
color: var(--error-color);
|
||||
}
|
||||
.warning {
|
||||
color: var(--warning-color);
|
||||
}
|
||||
|
||||
ha-header-bar {
|
||||
--mdc-theme-on-primary: var(--primary-text-color);
|
||||
|
||||
@@ -71,15 +71,15 @@ export class SystemLogCard extends LitElement {
|
||||
this.hass!.language
|
||||
)}
|
||||
–
|
||||
${html`(<span class="${item.level.toLowerCase()}"
|
||||
>${item.level}</span
|
||||
>) `}
|
||||
${integrations[idx]
|
||||
? domainToName(
|
||||
this.hass!.localize,
|
||||
integrations[idx]!
|
||||
)
|
||||
: item.source[0]}
|
||||
${html`(<span class="${item.level.toLowerCase()}"
|
||||
>${item.level}</span
|
||||
>)`}
|
||||
${item.count > 1
|
||||
? html`
|
||||
-
|
||||
|
||||
@@ -21,6 +21,7 @@ import "../../../components/ha-service-picker";
|
||||
import "../../../components/ha-yaml-editor";
|
||||
import type { HaYamlEditor } from "../../../components/ha-yaml-editor";
|
||||
import { ServiceAction } from "../../../data/script";
|
||||
import { callExecuteScript } from "../../../data/service";
|
||||
import { haStyle } from "../../../resources/styles";
|
||||
import "../../../styles/polymer-ha-style";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
@@ -250,17 +251,10 @@ class HaPanelDevService extends LitElement {
|
||||
);
|
||||
|
||||
private _callService() {
|
||||
const domain = computeDomain(this._serviceData!.service);
|
||||
const service = computeObjectId(this._serviceData!.service);
|
||||
if (!domain || !service) {
|
||||
if (!this._serviceData?.service) {
|
||||
return;
|
||||
}
|
||||
this.hass.callService(
|
||||
domain,
|
||||
service,
|
||||
this._serviceData!.data,
|
||||
this._serviceData!.target
|
||||
);
|
||||
callExecuteScript(this.hass, [this._serviceData]);
|
||||
}
|
||||
|
||||
private _toggleYaml() {
|
||||
|
||||
@@ -171,7 +171,7 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
[[localize('ui.panel.developer-tools.tabs.states.attributes')]]
|
||||
<paper-checkbox
|
||||
checked="{{_showAttributes}}"
|
||||
on-change="{{saveAttributeCheckboxState}}"
|
||||
on-change="saveAttributeCheckboxState"
|
||||
></paper-checkbox>
|
||||
</th>
|
||||
</tr>
|
||||
@@ -379,7 +379,7 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!value.state.includes(_stateFilter.toLowerCase())) {
|
||||
if (!value.state.toLowerCase().includes(_stateFilter.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import { computeRTL, emitRTLDirection } from "../../common/util/compute_rtl";
|
||||
import "../../components/entity/state-badge";
|
||||
import "../../components/ha-circular-progress";
|
||||
import "../../components/ha-relative-time";
|
||||
import { TraceContexts } from "../../data/trace";
|
||||
import { LogbookEntry } from "../../data/logbook";
|
||||
import { haStyle, haStyleScrollbar } from "../../resources/styles";
|
||||
import { HomeAssistant } from "../../types";
|
||||
@@ -32,6 +33,9 @@ class HaLogbook extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public userIdToName = {};
|
||||
|
||||
@property({ attribute: false })
|
||||
public traceContexts: TraceContexts = {};
|
||||
|
||||
@property({ attribute: false }) public entries: LogbookEntry[] = [];
|
||||
|
||||
@property({ type: Boolean, attribute: "narrow" })
|
||||
@@ -55,12 +59,16 @@ class HaLogbook extends LitElement {
|
||||
// @ts-ignore
|
||||
@restoreScroll(".container") private _savedScrollPos?: number;
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues) {
|
||||
protected shouldUpdate(changedProps: PropertyValues<this>) {
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
const languageChanged =
|
||||
oldHass === undefined || oldHass.language !== this.hass.language;
|
||||
|
||||
return changedProps.has("entries") || languageChanged;
|
||||
return (
|
||||
changedProps.has("entries") ||
|
||||
changedProps.has("traceContexts") ||
|
||||
languageChanged
|
||||
);
|
||||
}
|
||||
|
||||
protected updated(_changedProps: PropertyValues) {
|
||||
@@ -117,7 +125,10 @@ class HaLogbook extends LitElement {
|
||||
: undefined;
|
||||
const item_username =
|
||||
item.context_user_id && this.userIdToName[item.context_user_id];
|
||||
const domain = item.entity_id ? computeDomain(item.entity_id) : item.domain;
|
||||
const domain = item.entity_id
|
||||
? computeDomain(item.entity_id)
|
||||
: // Domain is there if there is no entity ID.
|
||||
item.domain!;
|
||||
|
||||
return html`
|
||||
<div class="entry-container">
|
||||
@@ -201,6 +212,22 @@ class HaLogbook extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.datetime=${item.when}
|
||||
></ha-relative-time>
|
||||
${item.domain === "automation" &&
|
||||
item.context_id! in this.traceContexts
|
||||
? html`
|
||||
-
|
||||
<a
|
||||
href=${`/config/automation/trace/${
|
||||
this.traceContexts[item.context_id!].item_id
|
||||
}?run_id=${
|
||||
this.traceContexts[item.context_id!].run_id
|
||||
}`}
|
||||
>${this.hass.localize(
|
||||
"ui.components.logbook.show_trace"
|
||||
)}</a
|
||||
>
|
||||
`
|
||||
: ""}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -277,6 +304,10 @@ class HaLogbook extends LitElement {
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.secondary a {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
|
||||
.date {
|
||||
margin: 8px 0;
|
||||
padding: 0 16px;
|
||||
|
||||
@@ -17,6 +17,7 @@ import "../../components/ha-date-range-picker";
|
||||
import type { DateRangePickerRanges } from "../../components/ha-date-range-picker";
|
||||
import "../../components/ha-icon-button";
|
||||
import "../../components/ha-menu-button";
|
||||
import { TraceContexts, loadTraceContexts } from "../../data/trace";
|
||||
import {
|
||||
clearLogbookCache,
|
||||
getLogbookData,
|
||||
@@ -35,9 +36,6 @@ export class HaPanelLogbook extends LitElement {
|
||||
|
||||
@property({ reflect: true, type: Boolean }) narrow!: boolean;
|
||||
|
||||
@property({ attribute: false })
|
||||
private _userIdToName = {};
|
||||
|
||||
@property() _startDate: Date;
|
||||
|
||||
@property() _endDate: Date;
|
||||
@@ -54,6 +52,10 @@ export class HaPanelLogbook extends LitElement {
|
||||
|
||||
private _fetchUserDone?: Promise<unknown>;
|
||||
|
||||
@internalProperty() private _userIdToName = {};
|
||||
|
||||
@internalProperty() private _traceContexts: TraceContexts = {};
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
|
||||
@@ -128,6 +130,7 @@ export class HaPanelLogbook extends LitElement {
|
||||
.hass=${this.hass}
|
||||
.entries=${this._entries}
|
||||
.userIdToName=${this._userIdToName}
|
||||
.traceContexts=${this._traceContexts}
|
||||
virtualize
|
||||
></ha-logbook>
|
||||
`}
|
||||
@@ -181,7 +184,7 @@ export class HaPanelLogbook extends LitElement {
|
||||
};
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
protected updated(changedProps: PropertyValues<this>) {
|
||||
if (
|
||||
changedProps.has("_startDate") ||
|
||||
changedProps.has("_endDate") ||
|
||||
@@ -257,19 +260,19 @@ export class HaPanelLogbook extends LitElement {
|
||||
|
||||
private async _getData() {
|
||||
this._isLoading = true;
|
||||
const [entries] = await Promise.all([
|
||||
const [entries, traceContexts] = await Promise.all([
|
||||
getLogbookData(
|
||||
this.hass,
|
||||
this._startDate.toISOString(),
|
||||
this._endDate.toISOString(),
|
||||
this._entityId
|
||||
),
|
||||
loadTraceContexts(this.hass),
|
||||
this._fetchUserDone,
|
||||
]);
|
||||
|
||||
// Fixed in TS 3.9 but upgrade out of scope for this PR.
|
||||
// @ts-ignore
|
||||
this._entries = entries;
|
||||
this._traceContexts = traceContexts;
|
||||
this._isLoading = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -272,7 +272,10 @@ export class HuiButtonCard extends LitElement implements LovelaceCard {
|
||||
height: auto;
|
||||
color: var(--paper-item-icon-color, #44739e);
|
||||
--mdc-icon-size: 100%;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
ha-icon + span {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
ha-icon,
|
||||
|
||||
@@ -284,7 +284,7 @@ class HuiMapCard extends LitElement implements LovelaceCard {
|
||||
this.updateMap(changedProps.get("_config") as MapCardConfig);
|
||||
}
|
||||
|
||||
if (this._config!.hours_to_show && this._configEntities?.length) {
|
||||
if (this._config?.hours_to_show && this._configEntities?.length) {
|
||||
const minute = 60000;
|
||||
if (changedProps.has("_config")) {
|
||||
this._getHistory();
|
||||
|
||||
@@ -129,7 +129,7 @@ class HuiGenericEntityRow extends LitElement {
|
||||
stateObj.attributes.brightness
|
||||
? html`${Math.round(
|
||||
(stateObj.attributes.brightness / 255) * 100
|
||||
)}%`
|
||||
)} %`
|
||||
: "")}
|
||||
</div>
|
||||
`
|
||||
|
||||
@@ -234,9 +234,13 @@ export abstract class HuiElementEditor<T> extends LitElement {
|
||||
<div class="warning">
|
||||
${this.hass.localize("ui.errors.config.editor_not_supported")}:
|
||||
<br />
|
||||
<ul>
|
||||
${this._warnings!.map((warning) => html`<li>${warning}</li>`)}
|
||||
</ul>
|
||||
${this._warnings!.length > 0 && this._warnings![0] !== undefined
|
||||
? html` <ul>
|
||||
${this._warnings!.map(
|
||||
(warning) => html`<li>${warning}</li>`
|
||||
)}
|
||||
</ul>`
|
||||
: ""}
|
||||
${this.hass.localize("ui.errors.config.edit_in_yaml_supported")}
|
||||
</div>
|
||||
`
|
||||
|
||||
@@ -52,7 +52,7 @@ class HuiHumidifierEntityRow extends LitElement implements LovelaceRow {
|
||||
.config=${this._config}
|
||||
.secondaryText=${stateObj.attributes.humidity
|
||||
? `${this.hass!.localize("ui.card.humidifier.humidity")}:
|
||||
${stateObj.attributes.humidity}%${
|
||||
${stateObj.attributes.humidity} %${
|
||||
stateObj.attributes.mode
|
||||
? ` (${
|
||||
this.hass!.localize(
|
||||
|
||||
@@ -248,7 +248,7 @@ class LovelaceFullConfigEditor extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
if (/^#|\s#/gm.test(value)) {
|
||||
if (this.yamlEditor.hasComments) {
|
||||
if (
|
||||
!confirm(
|
||||
this.hass.localize(
|
||||
|
||||
@@ -105,6 +105,7 @@ export class PanelView extends LitElement implements LovelaceViewElement {
|
||||
card.isPanel = true;
|
||||
|
||||
if (!this.lovelace?.editMode) {
|
||||
card.editMode = false;
|
||||
this._card = card;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import { HighlightStyle, tags } from "@codemirror/highlight";
|
||||
import { EditorView as CMEditorView, KeyBinding } from "@codemirror/view";
|
||||
import { EditorView, KeyBinding } from "@codemirror/view";
|
||||
import { StreamLanguage } from "@codemirror/stream-parser";
|
||||
import { jinja2 } from "@codemirror/legacy-modes/mode/jinja2";
|
||||
import { yaml } from "@codemirror/legacy-modes/mode/yaml";
|
||||
import { indentLess, indentMore } from "@codemirror/commands";
|
||||
import { Compartment } from "@codemirror/state";
|
||||
|
||||
export { keymap, highlightActiveLine, drawSelection } from "@codemirror/view";
|
||||
export { CMEditorView as EditorView };
|
||||
export {
|
||||
keymap,
|
||||
highlightActiveLine,
|
||||
drawSelection,
|
||||
EditorView,
|
||||
} from "@codemirror/view";
|
||||
export { EditorState, Prec } from "@codemirror/state";
|
||||
export { defaultKeymap } from "@codemirror/commands";
|
||||
export { lineNumbers } from "@codemirror/gutter";
|
||||
export { searchKeymap, highlightSelectionMatches } from "@codemirror/search";
|
||||
export { history, historyKeymap } from "@codemirror/history";
|
||||
export { rectangularSelection } from "@codemirror/rectangular-selection";
|
||||
export { HighlightStyle, tags } from "@codemirror/highlight";
|
||||
|
||||
export const langs = {
|
||||
jinja2: StreamLanguage.define(jinja2),
|
||||
@@ -31,20 +36,23 @@ export const tabKeyBindings: KeyBinding[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const theme = CMEditorView.theme({
|
||||
export const theme = EditorView.theme({
|
||||
"&": {
|
||||
color: "var(--primary-text-color)",
|
||||
backgroundColor:
|
||||
"var(--code-editor-background-color, var(--card-background-color))",
|
||||
"& ::selection": { backgroundColor: "rgba(var(--rgb-primary-color), 0.3)" },
|
||||
caretColor: "var(--secondary-text-color)",
|
||||
height: "var(--code-mirror-height, auto)",
|
||||
maxHeight: "var(--code-mirror-max-height, unset)",
|
||||
},
|
||||
|
||||
"&.cm-focused": { outline: "none" },
|
||||
|
||||
"&.cm-focused .cm-cursor": {
|
||||
borderLeftColor: "#var(--secondary-text-color)",
|
||||
borderLeftColor: "var(--secondary-text-color)",
|
||||
},
|
||||
|
||||
"&.cm-focused .cm-selectionBackground, .cm-selectionBackground": {
|
||||
backgroundColor: "rgba(var(--rgb-primary-color), 0.3)",
|
||||
},
|
||||
@@ -130,7 +138,7 @@ export const theme = CMEditorView.theme({
|
||||
"2px solid var(--paper-input-container-focus-color, var(--primary-color))",
|
||||
paddingRight: "0",
|
||||
},
|
||||
".cm-gutterElementags.lineNumber": { color: "inherit" },
|
||||
".cm-gutterElement.lineNumber": { color: "inherit" },
|
||||
});
|
||||
|
||||
export const highlightStyle = HighlightStyle.define([
|
||||
|
||||
+23
-10
@@ -94,6 +94,19 @@ export const derivedStyles = {
|
||||
"mdc-dialog-scroll-divider-color": "var(--divider-color)",
|
||||
};
|
||||
|
||||
export const buttonLinkStyle = css`
|
||||
button.link {
|
||||
background: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
export const haStyle = css`
|
||||
:host {
|
||||
font-family: var(--paper-font-body1_-_font-family);
|
||||
@@ -180,16 +193,7 @@ export const haStyle = css`
|
||||
--mdc-theme-primary: var(--error-color);
|
||||
}
|
||||
|
||||
button.link {
|
||||
background: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
padding: 0;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
${buttonLinkStyle}
|
||||
|
||||
.card-actions a {
|
||||
text-decoration: none;
|
||||
@@ -355,3 +359,12 @@ export const haStyleScrollbar = css`
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
`;
|
||||
|
||||
export const baseEntrypointStyles = css`
|
||||
body {
|
||||
background-color: var(--primary-background-color);
|
||||
color: var(--primary-text-color);
|
||||
height: calc(100vh - 32px);
|
||||
width: 100vw;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -230,7 +230,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
|
||||
}
|
||||
this.__loadedFragmetTranslations.add(fragment);
|
||||
const result = await getTranslation(fragment, language);
|
||||
this._updateResources(result.language, result.data);
|
||||
await this._updateResources(result.language, result.data);
|
||||
}
|
||||
|
||||
private async _loadCoreTranslations(language: string) {
|
||||
|
||||
+65
-34
@@ -300,6 +300,7 @@
|
||||
"entries_not_found": "No logbook entries found.",
|
||||
"by": "by",
|
||||
"by_service": "by service",
|
||||
"show_trace": "Show trace",
|
||||
"messages": {
|
||||
"was_away": "was detected away",
|
||||
"was_at_state": "was detected at {state}",
|
||||
@@ -743,12 +744,14 @@
|
||||
"manuf": "by {manufacturer}",
|
||||
"no_area": "No Area",
|
||||
"device_signature": "Zigbee device signature",
|
||||
"device_children": "Zigbee device children",
|
||||
"buttons": {
|
||||
"add": "Add Devices via this device",
|
||||
"remove": "Remove Device",
|
||||
"clusters": "Manage Clusters",
|
||||
"reconfigure": "Reconfigure Device",
|
||||
"zigbee_information": "Zigbee device signature",
|
||||
"device_children": "View Children",
|
||||
"view_in_visualization": "View in Visualization"
|
||||
},
|
||||
"services": {
|
||||
@@ -800,7 +803,8 @@
|
||||
"edit_in_yaml_supported": "You can still edit your config in YAML.",
|
||||
"key_missing": "Required key \"{key}\" is missing.",
|
||||
"key_not_expected": "Key \"{key}\" is not expected or not supported by the visual editor.",
|
||||
"key_wrong_type": "The provided value for \"{key}\" is not supported by the visual editor. We support ({type_correct}) but received ({type_wrong})."
|
||||
"key_wrong_type": "The provided value for \"{key}\" is not supported by the visual editor. We support ({type_correct}) but received ({type_wrong}).",
|
||||
"no_template_editor_support": "Templates not supported in visual editor"
|
||||
}
|
||||
},
|
||||
"login-form": {
|
||||
@@ -835,7 +839,7 @@
|
||||
"no_supervisor": "This redirect is not supported by your Home Assistant installation. It needs either the Home Assistant Operating System or Home Assistant Supervised installation method. For more information, see the {docs_link}.",
|
||||
"documentation": "documentation",
|
||||
"faq_link": "My Home Assistant FAQ",
|
||||
"error": "An unknown error occured"
|
||||
"error": "An unknown error occurred"
|
||||
},
|
||||
"config": {
|
||||
"header": "Configure Home Assistant",
|
||||
@@ -1177,7 +1181,9 @@
|
||||
"no_automations": "We couldn’t find any editable automations",
|
||||
"add_automation": "Add automation",
|
||||
"only_editable": "Only automations defined in automations.yaml are editable.",
|
||||
"dev_only_editable": "Only automations defined in automations.yaml are debuggable.",
|
||||
"edit_automation": "Edit automation",
|
||||
"dev_automation": "Debug automation",
|
||||
"show_info_automation": "Show info about automation",
|
||||
"delete_automation": "Delete automation",
|
||||
"delete_confirm": "Are you sure you want to delete this automation?",
|
||||
@@ -1235,8 +1241,8 @@
|
||||
"queued": "Queue length",
|
||||
"parallel": "Max number of parallel runs"
|
||||
},
|
||||
"edit_yaml": "Edit as YAML",
|
||||
"edit_ui": "Edit with UI",
|
||||
"edit_yaml": "Edit in YAML",
|
||||
"edit_ui": "Edit in visual editor",
|
||||
"copy_to_clipboard": "Copy to Clipboard",
|
||||
"triggers": {
|
||||
"name": "Trigger",
|
||||
@@ -1247,7 +1253,7 @@
|
||||
"duplicate": "Duplicate",
|
||||
"delete": "[%key:ui::panel::mailbox::delete_button%]",
|
||||
"delete_confirm": "Are you sure you want to delete this?",
|
||||
"unsupported_platform": "No UI support for platform: {platform}",
|
||||
"unsupported_platform": "No visual editor support for platform: {platform}",
|
||||
"type_select": "Trigger type",
|
||||
"type": {
|
||||
"device": {
|
||||
@@ -1349,7 +1355,7 @@
|
||||
"duplicate": "[%key:ui::panel::config::automation::editor::triggers::duplicate%]",
|
||||
"delete": "[%key:ui::panel::mailbox::delete_button%]",
|
||||
"delete_confirm": "[%key:ui::panel::config::automation::editor::triggers::delete_confirm%]",
|
||||
"unsupported_condition": "No UI support for condition: {condition}",
|
||||
"unsupported_condition": "No visual editor support for condition: {condition}",
|
||||
"type_select": "Condition type",
|
||||
"type": {
|
||||
"and": {
|
||||
@@ -1361,7 +1367,9 @@
|
||||
"extra_fields": {
|
||||
"above": "Above",
|
||||
"below": "Below",
|
||||
"for": "Duration"
|
||||
"for": "Duration",
|
||||
"hvac_mode": "HVAC mode",
|
||||
"preset_mode": "Preset mode"
|
||||
}
|
||||
},
|
||||
"not": {
|
||||
@@ -1425,7 +1433,7 @@
|
||||
"duplicate": "[%key:ui::panel::config::automation::editor::triggers::duplicate%]",
|
||||
"delete": "[%key:ui::panel::mailbox::delete_button%]",
|
||||
"delete_confirm": "[%key:ui::panel::config::automation::editor::triggers::delete_confirm%]",
|
||||
"unsupported_action": "No UI support for action: {action}",
|
||||
"unsupported_action": "No visual editor support for action: {action}",
|
||||
"type_select": "Action type",
|
||||
"type": {
|
||||
"service": {
|
||||
@@ -1461,7 +1469,12 @@
|
||||
"code": "Code",
|
||||
"message": "Message",
|
||||
"title": "Title",
|
||||
"position": "[%key:ui::card::cover::position%]"
|
||||
"position": "[%key:ui::card::cover::position%]",
|
||||
"mode": "Mode",
|
||||
"humidity": "Humidity",
|
||||
"value": "Value",
|
||||
"brightness_pct": "[%key:ui::card::light::brightness%]",
|
||||
"flash": "Flash"
|
||||
}
|
||||
},
|
||||
"scene": {
|
||||
@@ -1531,6 +1544,8 @@
|
||||
"add_blueprint": "Import blueprint",
|
||||
"use_blueprint": "Create automation",
|
||||
"delete_blueprint": "Delete blueprint",
|
||||
"share_blueprint": "Share blueprint",
|
||||
"share_blueprint_no_url": "Unable to share blueprint: no source url",
|
||||
"discover_more": "Discover more blueprints"
|
||||
},
|
||||
"add": {
|
||||
@@ -1757,13 +1772,13 @@
|
||||
"enable_state_reporting": "Enable State Reporting",
|
||||
"info_state_reporting": "If you enable state reporting, Home Assistant will send all state changes of exposed entities to Google. This allows you to always see the latest states in the Google app.",
|
||||
"security_devices": "Security Devices",
|
||||
"enter_pin_info": "Please enter a pin to interact with security devices. Security devices are doors, garage doors and locks. You will be asked to say/enter this pin when interacting with such devices via Google Assistant.",
|
||||
"devices_pin": "Security Devices Pin",
|
||||
"enter_pin_info": "Please enter a PIN to interact with security devices. Security devices are doors, garage doors and locks. You will be asked to say/enter this PIN when interacting with such devices via Google Assistant.",
|
||||
"devices_pin": "Security Devices PIN",
|
||||
"enter_pin_hint": "Enter a PIN to use security devices",
|
||||
"sync_entities": "Sync Entities to Google",
|
||||
"sync_entities_404_message": "Failed to sync your entities to Google, ask Google 'Hey Google, sync my devices' to sync your entities.",
|
||||
"manage_entities": "Manage Entities",
|
||||
"enter_pin_error": "Unable to store pin:"
|
||||
"enter_pin_error": "Unable to store PIN:"
|
||||
},
|
||||
"webhooks": {
|
||||
"title": "Webhooks",
|
||||
@@ -2035,7 +2050,7 @@
|
||||
"new": "Set up a new integration",
|
||||
"confirm_new": "Do you want to set up {integration}?",
|
||||
"add_integration": "Add integration",
|
||||
"no_integrations": "Seems like you don't have any integations configured yet. Click on the button below to add your first integration!",
|
||||
"no_integrations": "Seems like you don't have any integrations configured yet. Click on the button below to add your first integration!",
|
||||
"note_about_integrations": "Not all integrations can be configured via the UI yet.",
|
||||
"note_about_website_reference": "More are available on the ",
|
||||
"home_assistant_website": "Home Assistant website",
|
||||
@@ -2097,7 +2112,7 @@
|
||||
"integration": "integration",
|
||||
"device": "device"
|
||||
},
|
||||
"disable_confirm": "Are you sure you want to disable this config entry? It's devices and entities will be disabled."
|
||||
"disable_confirm": "Are you sure you want to disable this config entry? Its devices and entities will be disabled."
|
||||
}
|
||||
},
|
||||
"config_flow": {
|
||||
@@ -2202,7 +2217,7 @@
|
||||
"node_query_stages": {
|
||||
"protocolinfo": "Obtaining basic Z-Wave capabilities of this node from the controller",
|
||||
"probe": "Checking if the node is awake/alive",
|
||||
"wakeup": "Setting up support for wakeup queues and messages",
|
||||
"wakeup": "Setting up support for wake-up queues and messages",
|
||||
"manufacturerspecific1": "Obtaining manufacturer and product ID codes from the node",
|
||||
"nodeinfo": "Obtaining supported command classes from the node",
|
||||
"nodeplusinfo": "Obtaining Z-Wave+ information from the node",
|
||||
@@ -2224,8 +2239,8 @@
|
||||
"complete": "Node Refresh Complete",
|
||||
"description": "This will tell OpenZWave to re-interview a node and update the node's command classes, capabilities, and values.",
|
||||
"battery_note": "If the node is battery powered, be sure to wake it before proceeding",
|
||||
"wakeup_header": "Wakeup Instructions for",
|
||||
"wakeup_instructions_source": "Wakeup instructions are sourced from the OpenZWave community device database.",
|
||||
"wakeup_header": "Wake-up Instructions for",
|
||||
"wakeup_instructions_source": "Wake-up instructions are sourced from the OpenZWave community device database.",
|
||||
"start_refresh_button": "Start Refresh",
|
||||
"refreshing_description": "Refreshing node information...",
|
||||
"node_status": "Node Status",
|
||||
@@ -2308,7 +2323,7 @@
|
||||
"spinner": "Searching for ZHA Zigbee devices...",
|
||||
"pairing_mode": "Make sure your devices are in pairing mode. Check the instructions of your device on how to do this.",
|
||||
"discovered_text": "Devices will show up here once discovered.",
|
||||
"no_devices_found": "No devices were found, make sure they are in paring mode and keep them awake while discovering is running.",
|
||||
"no_devices_found": "No devices were found, make sure they are in pairing mode and keep them awake while discovering is running.",
|
||||
"search_again": "Search Again"
|
||||
},
|
||||
"add_device": "Add Device",
|
||||
@@ -2370,6 +2385,7 @@
|
||||
"caption": "Visualization",
|
||||
"highlight_label": "Highlight Devices",
|
||||
"zoom_label": "Zoom To Device",
|
||||
"auto_zoom": "Auto Zoom",
|
||||
"refresh_topology": "Refresh Topology"
|
||||
},
|
||||
"group_binding": {
|
||||
@@ -2393,7 +2409,7 @@
|
||||
"instance": "Instance",
|
||||
"index": "Index",
|
||||
"unknown": "unknown",
|
||||
"wakeup_interval": "Wakeup Interval"
|
||||
"wakeup_interval": "Wake-up Interval"
|
||||
},
|
||||
"migration": {
|
||||
"ozw": {
|
||||
@@ -2444,7 +2460,7 @@
|
||||
"node_config": {
|
||||
"header": "Node Configuration Options",
|
||||
"seconds": "seconds",
|
||||
"set_wakeup": "Set Wakeup Interval",
|
||||
"set_wakeup": "Set Wake-up Interval",
|
||||
"config_parameter": "Configuration Parameter",
|
||||
"config_value": "Configuration Value",
|
||||
"true": "True",
|
||||
@@ -2505,7 +2521,17 @@
|
||||
"device_info": {
|
||||
"zwave_info": "Z-Wave Info",
|
||||
"node_status": "Node Status",
|
||||
"node_ready": "Node Ready"
|
||||
"node_ready": "Node Ready",
|
||||
"device_config": "Configure Device"
|
||||
},
|
||||
"node_config": {
|
||||
"header": "Z-Wave Device Configuration",
|
||||
"introduction": "Manage and adjust device (node) specific configuration parameters for the selected device",
|
||||
"attribution": "Device configuration parameters and descriptions are provided by the {device_database}",
|
||||
"zwave_js_device_database": "Z-Wave JS Device Database",
|
||||
"battery_device_notice": "Battery devices must be awake to update their config. Please refer to your device manual for instructions on how to wake the device.",
|
||||
"parameter_is_read_only": "This parameter is read-only.",
|
||||
"error_device_not_found": "Device not found"
|
||||
},
|
||||
"node_status": {
|
||||
"unknown": "Unknown",
|
||||
@@ -3418,6 +3444,17 @@
|
||||
"complete_access": "It will have access to all data in Home Assistant.",
|
||||
"hide_message": "Check docs for the panel_custom component to hide this message"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"go_back": "Go back",
|
||||
"supervisor": {
|
||||
"title": "Could not load the Supervisor panel!",
|
||||
"wait": "If you just started, make sure you have given the supervisor enough time to start.",
|
||||
"ask": "Ask for help",
|
||||
"reboot": "Try a reboot of the host",
|
||||
"observer": "Check the Observer",
|
||||
"system_health": "Check System Health"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3425,7 +3462,6 @@
|
||||
"addon": {
|
||||
"failed_to_reset": "Failed to reset add-on configuration, {error}",
|
||||
"failed_to_save": "Failed to save add-on configuration, {error}",
|
||||
|
||||
"state": {
|
||||
"installed": "Add-on is installed",
|
||||
"not_installed": "Add-on is not installed",
|
||||
@@ -3466,8 +3502,8 @@
|
||||
"hostname": "Hostname",
|
||||
"new_update_available": "{name} {version} is available",
|
||||
"not_available_arch": "This add-on is not compatible with the processor of your device or the operating system you have installed on your device.",
|
||||
"not_available_version": "You are unning Home Assistant {core_version_installed}, to update to this version of the add-on you need at least version {core_version_needed} of Home Assistan",
|
||||
"visit_addon_page": "Visit the {name} page for more detals",
|
||||
"not_available_version": "You are running Home Assistant {core_version_installed}, to update to this version of the add-on you need at least version {core_version_needed} of Home Assistant",
|
||||
"visit_addon_page": "Visit the {name} page for more details",
|
||||
"restart": "restart",
|
||||
"start": "start",
|
||||
"stop": "stop",
|
||||
@@ -3475,13 +3511,11 @@
|
||||
"uninstall": "uninstall",
|
||||
"rebuild": "rebuild",
|
||||
"open_web_ui": "Open web UI",
|
||||
|
||||
"protection_mode": {
|
||||
"title": "Warning: Protection mode is disabled!",
|
||||
"content": "Protection mode on this add-on is disabled! This gives the add-on full access to the entire system, which adds security risks, and could damage your system when used incorrectly. Only disable the protection mode if you know, need AND trust the source of this add-on.",
|
||||
"enable": "Enable Protection mode"
|
||||
},
|
||||
|
||||
"capability": {
|
||||
"stage": {
|
||||
"title": "Add-on Stage",
|
||||
@@ -3548,7 +3582,6 @@
|
||||
"admin": "admin"
|
||||
}
|
||||
},
|
||||
|
||||
"option": {
|
||||
"boot": {
|
||||
"title": "Start on boot",
|
||||
@@ -3571,7 +3604,6 @@
|
||||
"description": "Blocks elevated system access from the add-on"
|
||||
}
|
||||
},
|
||||
|
||||
"action_error": {
|
||||
"uninstall": "Failed to uninstall add-on",
|
||||
"install": "Failed to install add-on",
|
||||
@@ -3615,11 +3647,9 @@
|
||||
"update_available": "{count, plural,\n one {Update}\n other {{count} Updates}\n} pending",
|
||||
"update": "Update",
|
||||
"version": "Version",
|
||||
|
||||
"error": {
|
||||
"unknown": "Unknown error",
|
||||
"update_failed": "Update failed",
|
||||
"lost_connectivity": "The Supervisor has lost connectivity, check the Supervisor logs and your network settings."
|
||||
"update_failed": "Update failed"
|
||||
}
|
||||
},
|
||||
"confirm": {
|
||||
@@ -3694,6 +3724,7 @@
|
||||
"share_diagonstics_description": "Would you want to automatically share crash reports and diagnostic information when the Supervisor encounters unexpected errors? {line_break} This will allow us to fix the problems, the information is only accessible to the Home Assistant Core team and will not be shared with others.{line_break} The data does not include any private/sensitive information and you can disable this in settings at any time you want.",
|
||||
"unsupported_reason": {
|
||||
"container": "Containers known to cause issues",
|
||||
"content-trust": "Content-trust validation is disabled",
|
||||
"dbus": "DBUS",
|
||||
"docker_configuration": "Docker Configuration",
|
||||
"docker_version": "Docker Version",
|
||||
@@ -3708,7 +3739,8 @@
|
||||
"privileged": "Supervisor is not privileged",
|
||||
"supervisor": "Supervisor was not able to update",
|
||||
"setup": "Setup of the Supervisor failed",
|
||||
"docker": "The Docker environment is not working properly"
|
||||
"docker": "The Docker environment is not working properly",
|
||||
"untrusted": "Detected untrusted content"
|
||||
}
|
||||
},
|
||||
"host": {
|
||||
@@ -3759,7 +3791,6 @@
|
||||
"password_protection": "Password protection",
|
||||
"password_protected": "password protected",
|
||||
"enter_password": "Please enter a password.",
|
||||
|
||||
"folder": {
|
||||
"homeassistant": "Home Assistant configuration",
|
||||
"ssl": "SSL",
|
||||
@@ -3772,7 +3803,7 @@
|
||||
"network": {
|
||||
"title": "Network settings",
|
||||
"connected_to": "Connected to {ssid}",
|
||||
"scan_ap": "Scan for accesspoints",
|
||||
"scan_ap": "Scan for access points",
|
||||
"open": "Open",
|
||||
"wep": "WEP",
|
||||
"wpa": "wpa-psk",
|
||||
|
||||
+1
-1
@@ -168,7 +168,7 @@ export interface Resources {
|
||||
export interface Context {
|
||||
id: string;
|
||||
parent_id?: string;
|
||||
user_id?: string;
|
||||
user_id?: string | null;
|
||||
}
|
||||
|
||||
export interface ServiceCallResponse {
|
||||
|
||||
@@ -40,6 +40,8 @@ const hassAttributeUtil = {
|
||||
humidifier: ["dehumidifier", "humidifier"],
|
||||
sensor: [
|
||||
"battery",
|
||||
"carbon_dioxide",
|
||||
"carbon_monoxide",
|
||||
"current",
|
||||
"energy",
|
||||
"humidity",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
"logbook": "سجل",
|
||||
"mailbox": "البريد",
|
||||
"map": "خريطة",
|
||||
"media_browser": "متصفح الوسائط",
|
||||
"profile": "الملف الشخصي",
|
||||
"shopping_list": "قائمة التسوق",
|
||||
"states": "نظرة عامة"
|
||||
@@ -77,6 +78,54 @@
|
||||
"unknown": "غير معروف"
|
||||
}
|
||||
},
|
||||
"supervisor": {
|
||||
"common": {
|
||||
"close": "إغلق"
|
||||
},
|
||||
"dialog": {
|
||||
"network": {
|
||||
"dhcp": "DHCP",
|
||||
"disabled": "معطل",
|
||||
"dns_servers": "خوادم DNS",
|
||||
"failed_to_change": "فشل تغيير إعدادات الشبكة",
|
||||
"gateway": "عنوان البوابة",
|
||||
"ip_netmask": "عنوان IP / قناع الشبكة",
|
||||
"static": "ثابتة",
|
||||
"unsaved": "لديك تغييرات غير محفوظة ، ستضيع هذه التغييرات إذا قمت بتغيير علامات التبويب ، هل تريد المتابعة؟",
|
||||
"warning": "إذا كنت تقوم بتغيير عناوين Wi-Fi أو IP أو البوابة ، فقد تفقد الاتصال!"
|
||||
},
|
||||
"registries": {
|
||||
"add_new_registry": "إضافة سجل جديد",
|
||||
"add_registry": "إضافة سجل",
|
||||
"failed_to_add": "فشل في إضافة السجل",
|
||||
"failed_to_remove": "فشل في إزالة السجل",
|
||||
"no_registries": "لم يتم تكوين سجلات",
|
||||
"password": "كلمة السر",
|
||||
"registry": "سجل",
|
||||
"remove": "إزالة",
|
||||
"title_add": "إضافة سجل حاوية جديد",
|
||||
"title_manage": "إدارة سجلات الحاويات",
|
||||
"username": "اسم المستخدم"
|
||||
},
|
||||
"repositories": {
|
||||
"remove": "إزالة",
|
||||
"title": "إدارة مستودعات الإضافات"
|
||||
},
|
||||
"restart_addon": {
|
||||
"confirm_text": "أعد تشغيل الإضافة",
|
||||
"text": "هل تريد إعادة تشغيل الإضافة بالتغييرات التي قمت بها؟"
|
||||
},
|
||||
"update": {
|
||||
"create_snapshot": "قم بإنشاء لقطة من {name} قبل التحديث",
|
||||
"snapshot": "لقط",
|
||||
"snapshotting": "إنشاء لقطة لـ {name}",
|
||||
"updating": "تحديث {name} إلى الإصدار {version}"
|
||||
}
|
||||
},
|
||||
"my": {
|
||||
"error_addon_not_found": "لم يتم العثور على الإضافة"
|
||||
}
|
||||
},
|
||||
"ui": {
|
||||
"auth_store": {
|
||||
"ask": "هل تريد حفظ هذا الدخول؟",
|
||||
@@ -230,6 +279,9 @@
|
||||
"loading_history": "جارٍ تحميل سجل الحالات ...",
|
||||
"no_history_found": "لم يتم العثور على سجل الحالات."
|
||||
},
|
||||
"logbook": {
|
||||
"show_trace": "عرض التتبع"
|
||||
},
|
||||
"related-items": {
|
||||
"integration": "تكامل"
|
||||
},
|
||||
@@ -411,6 +463,7 @@
|
||||
"device_id": {
|
||||
"action": "أضف إجراء",
|
||||
"extra_fields": {
|
||||
"mode": "الوضع",
|
||||
"position": "مكان"
|
||||
}
|
||||
},
|
||||
@@ -1051,6 +1104,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"supervisor": {
|
||||
"ask": "طلب المساعدة",
|
||||
"observer": "تحقق من المراقب",
|
||||
"reboot": "حاول إعادة تشغيل المضيف",
|
||||
"system_health": "تحقق من صحة النظام",
|
||||
"title": "تعذر تحميل لوحة المشرف!",
|
||||
"wait": "إذا كنت قد بدأت للتو ، فتأكد من منح المشرف الوقت الكافي للبدء."
|
||||
}
|
||||
},
|
||||
"history": {
|
||||
"ranges": {
|
||||
"last_week": "الأسبوع الماضي",
|
||||
|
||||
+770
-48
File diff suppressed because it is too large
Load Diff
@@ -148,13 +148,15 @@
|
||||
"title": "Autenticació de Home Assistant"
|
||||
},
|
||||
"docker_api": {
|
||||
"description": "Aquest complement, per petició del seu autor, demana accés a la instància de Docker del teu sistema. Aquest mode porporciona un control complet de tot el teu sistema Home Assistant al complement. Això genera possibles riscos de seguretat i podria fer malbé el sistema si no s'utilitza adequadament. Per aquesta raó, aquesta funció afecta negativament al nivell de seguretat del complement. \n\nAquest nivell d'accés no s'atorga automàticament i cal que el confirms. Per fer-ho, has de desactivar manualment el mode de protecció del complement. Desactiva el mode de protecció només si coneixes i confies en l'origen del complement.",
|
||||
"title": "Accés complet a Docker"
|
||||
},
|
||||
"full_access": {
|
||||
"description": "Aquest complement té accés complet al maquinari del teu sistema per petició del seu autor. Aquest accés és similar al mode privilegiat de Docker. Com que això genera possibles riscos de seguretat, aquesta funció afecta negativament al nivell de seguretat del complement. \n\nAquest accés no s'atorga automàticament i cal que ho confirms. Per fer-ho, has de desactivar manualment el mode de protecció del complement. Desactiva el mode de protecció només si coneixes i confies en l'origen del complement.",
|
||||
"description": "Aquest complement té accés complet al maquinari del teu sistema per petició del seu autor. Aquest accés és similar al mode privilegiat de Docker. Com que això genera possibles riscos de seguretat, aquesta funció afecta negativament al nivell de seguretat del complement. \n\nAquest accés no s'atorga automàticament i cal que el confirms. Per fer-ho, has de desactivar manualment el mode de protecció del complement. Desactiva el mode de protecció només si coneixes i confies en l'origen del complement.",
|
||||
"title": "Accés complet al maquinari"
|
||||
},
|
||||
"hassio_api": {
|
||||
"description": "Aquest complement té accés a l'API del Supervisor per petició del seu autor. Per defecte, el complement pot accedir a informació de la versió del teu sistema. Si demana a l'API accés de gestió o d'administrador, obtindrà accés per controlar diferents parts de Home Assistant. Aquest permís s'indica amb aquesta insígnia i afecta negativament al nivell de seguretat del complement.",
|
||||
"title": "Accés a l'API del Supervisor"
|
||||
},
|
||||
"homeassistant_api": {
|
||||
@@ -165,6 +167,10 @@
|
||||
"description": "Els complements normalment s'executen dins la seva pròpia capa de xarxa aïllada, cosa que els impedeix accedir a la xarxa del sistema operatiu amfitrió. En alguns casos, aquest aïllament pot limitar la prestació dels serveis del complement. Per tant, l'aïllament pot ser eliminat per l'autor del complement; en aquest cas, el complement té un accés complet a les capacitats de xarxa del dispositiu amfitrió. Això li porporciona més capacitats però en redueix la seguretat, per tant, el nivell de seguretat del complement es reduirà quan aquesta opció s'utilitzi.",
|
||||
"title": "Xarxa amfitrió"
|
||||
},
|
||||
"host_pid": {
|
||||
"description": "Habitualment, els processos que executen els complements estan aïllats dels altres processos del sistema. L'autor del complement ha demanat tenir accés i poder crear processos del sistema amfitrió. Aquest mode dóna accés i control total de tot el teu sistema Home Assistant al complement. Això genera possibles riscos de seguretat i podria fer malbé el sistema si no s'utilitza adequadament. Per aquesta raó, aquesta funció afecta negativament al nivell de seguretat del complement. \n\nAquest nivell d'accés no s'atorga automàticament i cal que el confirms. Per fer-ho, has de desactivar manualment el mode de protecció del complement. Desactiva el mode de protecció només si coneixes i confies en l'origen del complement.",
|
||||
"title": "Espai de noms de processos de l'amfitrió"
|
||||
},
|
||||
"ingress": {
|
||||
"description": "Aquest complement utilitza Ingress per poder incrustar la seva interfície de manera segura a Home Assistant.",
|
||||
"title": "Ingress"
|
||||
@@ -220,6 +226,7 @@
|
||||
"title": "Mostra a la barra lateral"
|
||||
},
|
||||
"protected": {
|
||||
"description": "Bloqueja l'accés privilegiat del complement al sistema",
|
||||
"title": "Mode de protecció"
|
||||
},
|
||||
"watchdog": {
|
||||
@@ -439,6 +446,7 @@
|
||||
"beta_backup": "Assegura't que tens còpies de seguretat de les teves dades abans d'activar aquesta funció.",
|
||||
"beta_join_confirm": "Vols unir-te al canal beta?",
|
||||
"beta_release_items": "Això inclou les versions beta de:",
|
||||
"beta_warning": "Les versions beta són per a verificadors i els primers que vulguin provar-la, però poden tenir canvis de codi inestables",
|
||||
"channel": "Canal",
|
||||
"cpu_usage": "Ús de CPU del Supervisor",
|
||||
"failed_to_reload": "No s'ha pogut tornar a carregar el Supervisor",
|
||||
@@ -459,14 +467,18 @@
|
||||
"docker": "L'entorn Docker no està funcionant correctament",
|
||||
"privileged": "El Supervisor no és privilegiat",
|
||||
"setup": "Ha fallat la configuració del Supervisor",
|
||||
"supervisor": "El Supervisor no s'ha pogut actualitzar"
|
||||
"supervisor": "El Supervisor no s'ha pogut actualitzar",
|
||||
"untrusted": "S'ha detectat algun contingut que no és de confiança"
|
||||
},
|
||||
"unhealthy_title": "La teva instal·lació no és bona",
|
||||
"unsupported_description": "A continuació es mostra una llista de problemes relacionats amb la instal·lació, fes clic als enllaços per obtenir informació sobre com resoldre'ls.",
|
||||
"unsupported_reason": {
|
||||
"container": "Els contenidors són coneguts per causar problemes",
|
||||
"content-trust": "Validació de continguts de confiança desactivada",
|
||||
"dbus": "DBUS",
|
||||
"docker_configuration": "Configuració de Docker",
|
||||
"docker_version": "Versió de Docker",
|
||||
"job_conditions": "Condicions 'job' ignorades",
|
||||
"lxc": "LXC",
|
||||
"network_manager": "Gestor de xarxa",
|
||||
"os": "Sistema operatiu",
|
||||
@@ -497,7 +509,7 @@
|
||||
},
|
||||
"automation": {
|
||||
"last_triggered": "Última execució",
|
||||
"trigger": "Executar accions"
|
||||
"trigger": "Executa accions"
|
||||
},
|
||||
"camera": {
|
||||
"not_available": "Imatge no disponible"
|
||||
@@ -775,7 +787,8 @@
|
||||
"was_unlocked": "s'ha desbloquejat",
|
||||
"was_unplugged": "s'ha desendollat",
|
||||
"was_unsafe": "és insegur"
|
||||
}
|
||||
},
|
||||
"show_trace": "Mostra la traça"
|
||||
},
|
||||
"media-browser": {
|
||||
"audio_not_supported": "El teu navegador no és compatible amb l'element d'àudio.",
|
||||
@@ -1135,6 +1148,7 @@
|
||||
"buttons": {
|
||||
"add": "Afegeix dispositius a través d'aquest dispositiu",
|
||||
"clusters": "Gestiona clústers",
|
||||
"device_children": "Mostra fills",
|
||||
"reconfigure": "Reconfigurar dispositiu",
|
||||
"remove": "Eliminar dispositiu",
|
||||
"view_in_visualization": "Mostra a la visualització",
|
||||
@@ -1143,6 +1157,7 @@
|
||||
"confirmations": {
|
||||
"remove": "Estàs segur que vols eliminar el dispositiu?"
|
||||
},
|
||||
"device_children": "Dispositiu Zigbee fill",
|
||||
"device_signature": "Signatura Zigbee del dispositiu",
|
||||
"last_seen": "Vist per últim cop",
|
||||
"manuf": "per {manufacturer}",
|
||||
@@ -1177,6 +1192,7 @@
|
||||
"key_missing": "Falta la clau obligatòria \"{key}\".",
|
||||
"key_not_expected": "No s'està esperant la clau \"{key}\" o no és compatible amb l'editor visual.",
|
||||
"key_wrong_type": "L'editor visual no admet el valor proporcionat de \"{key}\". ({type_correct}) és compatible, però s'ha rebut ({type_wrong}).",
|
||||
"no_template_editor_support": "Les plantilles no són compatibles amb l'editor visual",
|
||||
"no_type_provided": "No s'ha proporcionat cap tipus."
|
||||
}
|
||||
},
|
||||
@@ -1284,10 +1300,15 @@
|
||||
"device_id": {
|
||||
"action": "Acció",
|
||||
"extra_fields": {
|
||||
"brightness_pct": "Brillantor",
|
||||
"code": "Codi",
|
||||
"flash": "Flaix",
|
||||
"humidity": "Humitat",
|
||||
"message": "Missatge",
|
||||
"mode": "Mode",
|
||||
"position": "Posició",
|
||||
"title": "Títol"
|
||||
"title": "Títol",
|
||||
"value": "Valor"
|
||||
},
|
||||
"label": "Dispositiu"
|
||||
},
|
||||
@@ -1332,7 +1353,7 @@
|
||||
"wait_template": "Plantilla d'espera"
|
||||
}
|
||||
},
|
||||
"unsupported_action": "La IU no és compatible amb l'acció: {action}"
|
||||
"unsupported_action": "Acció no compatible amb l'editor visual: {action}"
|
||||
},
|
||||
"alias": "Nom",
|
||||
"blueprint": {
|
||||
@@ -1360,7 +1381,9 @@
|
||||
"extra_fields": {
|
||||
"above": "A sobre",
|
||||
"below": "A sota",
|
||||
"for": "Durada"
|
||||
"for": "Durada",
|
||||
"hvac_mode": "Mode HVAC",
|
||||
"preset_mode": "Mode predefinit"
|
||||
},
|
||||
"label": "Dispositiu"
|
||||
},
|
||||
@@ -1415,7 +1438,7 @@
|
||||
"zone": "Zona"
|
||||
}
|
||||
},
|
||||
"unsupported_condition": "La IU no és compatible amb la condició: {condition}"
|
||||
"unsupported_condition": "Condició no compatible amb l'editor visual: {condition}"
|
||||
},
|
||||
"copy_to_clipboard": "Copia al porta-retalls",
|
||||
"default_name": "Nova automatització",
|
||||
@@ -1423,8 +1446,8 @@
|
||||
"label": "Descripció",
|
||||
"placeholder": "Descripció opcional"
|
||||
},
|
||||
"edit_ui": "Edita a través d'interfície",
|
||||
"edit_yaml": "Edita com a YAML",
|
||||
"edit_ui": "Edita amb l'editor visual",
|
||||
"edit_yaml": "Edita en YAML",
|
||||
"enable_disable": "Activa/desactiva automatització",
|
||||
"introduction": "Utilitza les automatitzacions per donar vida a casa teva.",
|
||||
"load_error_not_editable": "Només les automatitzacions a automations.yaml són editables.",
|
||||
@@ -1545,7 +1568,7 @@
|
||||
"zone": "Zona"
|
||||
}
|
||||
},
|
||||
"unsupported_platform": "La IU no és compatible amb la plataforma: {platform}"
|
||||
"unsupported_platform": "Plataforma no compatible amb l'editor visual: {platform}"
|
||||
},
|
||||
"unsaved_confirm": "Hi ha canvis no desats. Segur que vols sortir?"
|
||||
},
|
||||
@@ -1553,6 +1576,8 @@
|
||||
"add_automation": "Afegeix automatització",
|
||||
"delete_automation": "Elimina l'automatització",
|
||||
"delete_confirm": "Estàs segur que vols eliminar aquesta automatització?",
|
||||
"dev_automation": "Depurar automatització",
|
||||
"dev_only_editable": "Només es poden depurar les automatitzacions definides al fitxer automations.yaml.",
|
||||
"duplicate": "Duplica",
|
||||
"duplicate_automation": "Duplica l'automatització",
|
||||
"edit_automation": "Edita automatització",
|
||||
@@ -1616,6 +1641,8 @@
|
||||
},
|
||||
"introduction": "La configuració dels blueprints et permet importar-ne i gestionar-los.",
|
||||
"learn_more": "Més informació sobre l'ús dels blueprints",
|
||||
"share_blueprint": "Comparteix blueprint",
|
||||
"share_blueprint_no_url": "No s'ha pogut compartir el blueprint: no hi ha cap URL origen",
|
||||
"use_blueprint": "Crea automatització"
|
||||
}
|
||||
},
|
||||
@@ -1643,9 +1670,9 @@
|
||||
"devices_pin": "PIN dels dispositius de seguretat",
|
||||
"enable_ha_skill": "Activa l'auxiliar de Home Assistant per Google Assistant",
|
||||
"enable_state_reporting": "Activa els informes d'estat",
|
||||
"enter_pin_error": "No s'ha pogut desar el pin:",
|
||||
"enter_pin_error": "No s'ha pogut desar el PIN:",
|
||||
"enter_pin_hint": "Introdueix un PIN per utilitzar dispositius de seguretat",
|
||||
"enter_pin_info": "Introdueix un codi PIN per interactuar amb dispositius de seguretat. Aquests dispositius són portes, garatges o panys, per exemple. Se't demanarà que introdueixis (o diguis) aquest PIN quan interactuïs amb aquests dispositius mitjançant Google Assistant.",
|
||||
"enter_pin_info": "Introdueix un PIN per interactuar amb dispositius de seguretat. Aquests dispositius són, per exemple, portes, garatges o panys. Se't demanarà que introdueixis o diguis aquest PIN quan interactuïs amb aquests dispositius mitjançant Google Assistant.",
|
||||
"info": "Amb la integració de Google Assistant per Home Assistant Cloud podràs controlar tots els dispositius de Home Assistant a través dels dispositius compatibles amb Google Assistant.",
|
||||
"info_state_reporting": "Si actives els informes d'estat, Home Assistant enviarà a Google tots els canvis d'estat de les entitats exposades. Això et permetrà veure els últims estats a l'aplicació de Google.",
|
||||
"manage_entities": "Gestió d'entitats",
|
||||
@@ -2335,7 +2362,7 @@
|
||||
"session": "Obtenint valors inusualment canviants del node",
|
||||
"static": "Obtenint valors estàtics del dispositiu",
|
||||
"versions": "Obtenint informació de programari i versions de classes de comandes",
|
||||
"wakeup": "Configurant el suport per a cues i missatges"
|
||||
"wakeup": "Configurant el suport per a cues de despertar i missatges"
|
||||
},
|
||||
"node": {
|
||||
"button": "Detalls del node",
|
||||
@@ -2359,8 +2386,8 @@
|
||||
"start_refresh_button": "Inicia l'actualització",
|
||||
"step": "Pas",
|
||||
"title": "Informació d'actualització del node",
|
||||
"wakeup_header": "Instruccions en despertar de",
|
||||
"wakeup_instructions_source": "Les instruccions en despertar provenen de la base de dades de dispositius de la comunitat OpenZWave."
|
||||
"wakeup_header": "Instruccions per despertar de",
|
||||
"wakeup_instructions_source": "Les instruccions per despertar provenen de la base de dades de dispositius de la comunitat OpenZWave."
|
||||
},
|
||||
"select_instance": {
|
||||
"header": "Selecciona una instància d'OpenZWave",
|
||||
@@ -2636,7 +2663,7 @@
|
||||
"add_device": "Afegeix dispositiu",
|
||||
"add_device_page": {
|
||||
"discovered_text": "Els dispositius apareixeran aquí un cop descoberts.",
|
||||
"no_devices_found": "No s'han trobat dispositius, assegura't que estiguin en mode vinculació i manten-los desperts mentre s'estiguin descoberint.",
|
||||
"no_devices_found": "No s'han trobat dispositius, assegura't que estiguin en mode vinculació i manten-los desperts mentre s'estiguin descobrint.",
|
||||
"pairing_mode": "Assegura't que els dispositiu estiguin en mode vinculació. Consulta les instruccions del dispositiu per saber com fer-ho.",
|
||||
"search_again": "Torna a cercar",
|
||||
"spinner": "S'estan cercant dispositius ZHA Zigbee..."
|
||||
@@ -2712,6 +2739,7 @@
|
||||
"caption": "Xarxa"
|
||||
},
|
||||
"visualization": {
|
||||
"auto_zoom": "Zoom automàtic",
|
||||
"caption": "Visualització",
|
||||
"header": "Visualització de xarxa",
|
||||
"highlight_label": "Ressalta els dispositius",
|
||||
@@ -2799,6 +2827,9 @@
|
||||
"connecting": "Connectant",
|
||||
"unknown": "Desconegut"
|
||||
},
|
||||
"node_config": {
|
||||
"error_device_not_found": "Dispositiu no trobat"
|
||||
},
|
||||
"node_status": {
|
||||
"alive": "Viu",
|
||||
"asleep": "Adormit",
|
||||
@@ -2824,7 +2855,7 @@
|
||||
"instance": "Instància",
|
||||
"unknown": "desconegut",
|
||||
"value": "Valor",
|
||||
"wakeup_interval": "Interval en despertar"
|
||||
"wakeup_interval": "Interval per despertar-se"
|
||||
},
|
||||
"description": "Gestiona la teva xarxa Z-Wave",
|
||||
"learn_more": "Més informació sobre Z-Wave",
|
||||
@@ -2853,7 +2884,7 @@
|
||||
"header": "Opcions de configuració del node",
|
||||
"seconds": "segons",
|
||||
"set_config_parameter": "Defineix el paràmetre de configuració",
|
||||
"set_wakeup": "Estableix l'interval en despertar",
|
||||
"set_wakeup": "Estableix l'interval per despertar-se",
|
||||
"true": "Cert"
|
||||
},
|
||||
"node_management": {
|
||||
@@ -2988,6 +3019,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"go_back": "Torna",
|
||||
"supervisor": {
|
||||
"ask": "Sol·licita ajuda",
|
||||
"observer": "Comprova l'observador",
|
||||
"reboot": "Intenta reiniciar l'amfitrió",
|
||||
"system_health": "Comprova l'estat del sistema",
|
||||
"title": "No s'ha pogut carregar el panell del Supervisor!",
|
||||
"wait": "Si acabes de començar, assegura't que has deixat passar prou temps perquè el Supervisor s'iniciï."
|
||||
}
|
||||
},
|
||||
"history": {
|
||||
"ranges": {
|
||||
"last_week": "La setmana passada",
|
||||
|
||||
+207
-13
@@ -112,27 +112,85 @@
|
||||
"output": "Výstup"
|
||||
},
|
||||
"network": {
|
||||
"container": "Kontejner",
|
||||
"disabled": "Zakázáno",
|
||||
"header": "Síť",
|
||||
"host": "Hostitel"
|
||||
},
|
||||
"no_configuration": "Tento doplňek neposkytuje konfiguraci s kterou byste si mohli hrát...",
|
||||
"options": {
|
||||
"edit_in_ui": "Upravit v uživatelském rozhraní",
|
||||
"edit_in_yaml": "Upravit přímo YAML",
|
||||
"header": "Možnosti",
|
||||
"invalid_yaml": "Neplatný YAML"
|
||||
"invalid_yaml": "Neplatný YAML",
|
||||
"show_unused_optional": "Zobrazit nepoužívané volitelné možnosti konfigurace"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"action_error": {
|
||||
"get_changelog": "Nepodařilo se získat seznam změn doplňku",
|
||||
"go_to_config": "Spuštění doplňku se nezdařilo - ověření konfigurace selhalo!",
|
||||
"install": "Instalace doplňku se nezdařila",
|
||||
"restart": "Restartování doplňku se nezdařilo",
|
||||
"start": "Spuštění doplňku se nezdařilo",
|
||||
"start_invalid_config": "Přejít do konfigurace",
|
||||
"stop": "Zastavení doplňku se nezdařilo",
|
||||
"uninstall": "Odinstalace doplňku se nezdařila",
|
||||
"validate_config": "Nepodařilo se ověřit konfiguraci doplňku"
|
||||
},
|
||||
"capability": {
|
||||
"apparmor": {
|
||||
"description": "AppArmor ('Application Armor') je modul zabezpečení jádra systému Linux, který omezuje možnosti doplňků, jako je přístup k síti, přístup k soketům a oprávnění číst, zapisovat nebo spouštět konkrétní soubory. \n\nAutoři doplňků mohou poskytnout své bezpečnostní profily optimalizované pro doplněk nebo požádat o jejich deaktivaci. Pokud je AppArmor zakázán, zvýší se bezpečnostní rizika a proto má negativní dopad na skóre zabezpečení doplňku.",
|
||||
"title": "AppArmor"
|
||||
},
|
||||
"auth_api": {
|
||||
"description": "Doplněk může ověřovat uživatele pomocí Home Assistant, což umožňuje doplňkům možnost přihlašovat se do aplikací spuštěných uvnitř doplňků pomocí uživatelského jména / hesla Home Assistant. Tento odznak označuje, zda autor doplňku tuto schopnost požaduje.",
|
||||
"title": "Autentifikace Home Assistant"
|
||||
},
|
||||
"docker_api": {
|
||||
"description": "Autor doplňku požádal, aby měl doplněk správcovský přístup k instanci Dockeru spuštěné ve vašem systému. Tento režim poskytuje doplňku plný přístup a kontrolu nad celým vaším systémem Home Assistant, což zvyšuje bezpečnostní rizika a při zneužití může váš systém poškodit. Proto tato funkce negativně ovlivňuje skóre zabezpečení doplňku. \n\nTato úroveň přístupu není udělena automaticky a je třeba ji potvrdit. Chcete-li to provést, musíte ručně deaktivovat režim ochrany doplňku. Režim ochrany deaktivujte, pouze pokud víte, co děláte, potřebujete to a důvěřujete zdroji tohoto doplňku.",
|
||||
"title": "Úplný přístup k Dockeru"
|
||||
},
|
||||
"full_access": {
|
||||
"description": "Tento doplněk získá úplný přístup k hardwaru vašeho systému na žádost autora doplňku. Přístup je srovnatelný s privilegovaným režimem v Dockeru. Protože to představuje možná bezpečnostní rizika, tato funkce negativně ovlivňuje skóre zabezpečení doplňku. \n\nTato úroveň přístupu není udělena automaticky a je třeba ji potvrdit. Chcete-li to provést, musíte ručně deaktivovat režim ochrany doplňku. Režim ochrany deaktivujte, pouze pokud víte co děláte, potřebujete to a důvěřujete zdroji tohoto doplňku.",
|
||||
"title": "Plný přístup k hardwaru"
|
||||
},
|
||||
"hassio_api": {
|
||||
"description": "Doplňku byl na žádost autora doplňku umožněn přístup k rozhraní Supervisor API. Ve výchozím nastavení má doplněk přístup k obecným informacím o verzi vašeho systému. Když doplněk požaduje přístup k rozhraní API na úrovni „manažer“ nebo „správce“, získá přístup k ovládání více částí systému Home Assistant. Toto oprávnění je označeno tímto odznakem a negativně ovlivní skóre zabezpečení doplňku.",
|
||||
"title": "Přístup k rozhraní Supervisor API"
|
||||
},
|
||||
"homeassistant_api": {
|
||||
"description": "Tento doplněk má přístup k vaší spuštěné instanci Home Assistant přímo přes Home Assistant API. Tento režim taktéž zajištuje autentifikaci pro doplněk, což umožňuje doplňku komunikovat s Home Assistant bez nutnosti dalších ověřovacích tokenů.",
|
||||
"title": "Přístup k API Home Assistant"
|
||||
},
|
||||
"host_network": {
|
||||
"description": "Doplňky obvykle běží ve své vlastní izolované síťové vrstvě, což jim brání v přístupu k síti hostitelského operačního systému. V některých případech může tato izolace sítě omezit doplňky při poskytování jejich služeb a proto může izolace být zrušena autorem doplňku, což doplňku poskytne plný přístup k síťovým funkcím hostitelského počítače. To dává doplňku více síťových funkcí, ale snižuje zabezpečení, proto se sníží bezpečnostní hodnocení doplňku, pokud doplněk tuto možnost použije.",
|
||||
"title": "Hostitelská síť"
|
||||
},
|
||||
"host_pid": {
|
||||
"description": "Obvykle procesy, které doplněk spouští, jsou izolovány od všech ostatních systémových procesů. Autor doplňku požádal, aby měl doplněk přístup k systémovým procesům běžícím na instanci hostitelského systému a umožnil doplňku také spouštět procesy v hostitelském systému. Tento režim poskytuje doplňku plný přístup a kontrolu nad celým vaším systémem Home Assistant, což zvyšuje bezpečnostní rizika a při zneužití může váš systém poškodit. Proto tato funkce negativně ovlivňuje skóre zabezpečení doplňku. \n\nTato úroveň přístupu není udělena automaticky a je třeba ji potvrdit. Chcete-li to provést, musíte ručně deaktivovat režim ochrany doplňku. Režim ochrany deaktivujte, pouze pokud víte, co děláte, potřebujete to a důvěřujete zdroji tohoto doplňku.",
|
||||
"title": "Obor názvů hostitelských procesů"
|
||||
},
|
||||
"ingress": {
|
||||
"description": "Tento doplněk používá Ingress k bezpečné integraci svého rozhraní do Home Assistant.",
|
||||
"title": "Ingress"
|
||||
},
|
||||
"label": {
|
||||
"apparmor": "apparmor",
|
||||
"auth": "autentifikace",
|
||||
"docker": "docker",
|
||||
"hardware": "hardware",
|
||||
"hass": "hass",
|
||||
"hassio": "hassio",
|
||||
"host": "hostitel"
|
||||
"host": "hostitel",
|
||||
"host_pid": "hostitelský pid",
|
||||
"ingress": "ingress",
|
||||
"rating": "hodnocení",
|
||||
"stage": "fáze"
|
||||
},
|
||||
"rating": {
|
||||
"description": "Home Assistant poskytuje každému z doplňků hodnocení zabezpečení, které označuje rizika spojená s používáním tohoto doplňku. Čím více přístupu doplněk ve vašem systému vyžaduje, tím nižší je skóre, čímž se zvyšují možná bezpečnostní rizika. \n\nSkóre je na stupnici od 1 do 6. Kde 1 je nejnižší skóre (považováno za nejméně bezpečné a nejvyšší riziko) a skóre 6 je nejvyšší skóre (považováno za nejbezpečnější a nejnižší riziko).",
|
||||
"title": "Bezpečnostní hodnocení doplňku"
|
||||
},
|
||||
"role": {
|
||||
"admin": "admin",
|
||||
@@ -140,19 +198,62 @@
|
||||
"default": "výchozí",
|
||||
"homeassistant": "homeassistant",
|
||||
"manager": "správce"
|
||||
},
|
||||
"stage": {
|
||||
"description": "Doplňky mohou mít jednu ze tří fází: \n\n {icon_stable} **Stabilní**: Tyto doplňky jsou připraveny k produkčnímu nasazení.\n\n {icon_experimental} **Experimentální**: Mohou obsahovat chyby a mohou být nedokončené. \n\n {icon_deprecated} **Zastaralé**: Tyto doplňky již nebudou dostávat žádné aktualizace.",
|
||||
"title": "Fáze doplňku"
|
||||
}
|
||||
},
|
||||
"changelog": "Seznam změn",
|
||||
"cpu_usage": "Využití procesoru doplňkem",
|
||||
"hostname": "Název hostitele",
|
||||
"install": "nainstalovat",
|
||||
"new_update_available": "{name} {verze} je k dispozici",
|
||||
"not_available_arch": "Tento doplněk není kompatibilní s procesorem vašeho zařízení nebo operačním systémem, který jste do zařízení nainstalovali.",
|
||||
"not_available_version": "Používáte Home Assistant {core_version_installed}, pro aktualizaci na tuto verzi doplňku potřebujete alespoň Home Assistant ve verzi {core_version_needed}",
|
||||
"open_web_ui": "Otevřít webové rozhraní",
|
||||
"option": {
|
||||
"auto_update": {
|
||||
"description": "Automaticky aktualizovat doplněk, pokud je k dispozici nová verze",
|
||||
"title": "Automatická aktualizace"
|
||||
},
|
||||
"boot": {
|
||||
"description": "Spustit doplněk při spuštění systému",
|
||||
"title": "Spustit při spuštění"
|
||||
},
|
||||
"ingress_panel": {
|
||||
"description": "Přidejte si tento doplněk na svůj postranní panel",
|
||||
"title": "Zobrazit v postranním panelu"
|
||||
},
|
||||
"protected": {
|
||||
"description": "Blokuje doplňku zvýšený přístup do systému",
|
||||
"title": "Režim ochrany"
|
||||
},
|
||||
"watchdog": {
|
||||
"description": "Toto spustí doplněk, pokud dojde k jeho selhání",
|
||||
"title": "Hlídací pes"
|
||||
}
|
||||
}
|
||||
},
|
||||
"protection_mode": {
|
||||
"content": "Režim ochrany v tomto doplňku je zakázán! To poskytuje doplněku plný přístup k celému systému, což zvyšuje bezpečnostní rizika a mohlo by poškodit systém při nesprávném použití. Režim ochrany zakažte pouze v případě, že víte, co děláte, je to potřeba a důvěřujete zdroji tohoto doplňku.",
|
||||
"enable": "Povolit režim ochrany",
|
||||
"title": "Upozornění: Režim ochrany je zakázán!"
|
||||
},
|
||||
"ram_usage": "Využití paměti RAM doplňkem",
|
||||
"rebuild": "obnovit",
|
||||
"restart": "restartovat",
|
||||
"start": "spustit",
|
||||
"stop": "zastavit",
|
||||
"uninstall": "odinstalovat",
|
||||
"visit_addon_page": "Další podrobnosti naleznete na stránce {name}"
|
||||
},
|
||||
"documentation": {
|
||||
"get_documentation": "Nepodařilo se získat dokumentaci k doplňku, {error}"
|
||||
},
|
||||
"failed_to_reset": "Obnovení konfigurace doplňku se nezdařilo, {error}",
|
||||
"failed_to_save": "Uložení konfigurace doplňku se nezdařilo, {error}",
|
||||
"logs": {
|
||||
"get_logs": "Nepodařilo se získat protokoly o doplňcích, {error}"
|
||||
},
|
||||
"panel": {
|
||||
"configuration": "Nastavení",
|
||||
@@ -162,15 +263,20 @@
|
||||
},
|
||||
"state": {
|
||||
"installed": "Doplněk je nainstalován",
|
||||
"not_available": "Doplněk není ve vašem systému k dispozici",
|
||||
"not_installed": "Doplněk není nainstalován"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"cancel": "Zrušit",
|
||||
"close": "Zavřít",
|
||||
"description": "Popis",
|
||||
"error": {
|
||||
"unknown": "Neznámá chyba"
|
||||
"unknown": "Neznámá chyba",
|
||||
"update_failed": "Aktualizace se nezdařila"
|
||||
},
|
||||
"failed_to_restart_name": "Restartování {name} se nezdařilo",
|
||||
"failed_to_update_name": "Aktualizace {name} se nezdařila",
|
||||
"learn_more": "Další informace",
|
||||
"new_version_available": "K dispozici je nová verze",
|
||||
"newest_version": "Nejnovější verze",
|
||||
@@ -178,9 +284,13 @@
|
||||
"refresh": "Obnovit",
|
||||
"release_notes": "Poznámky k vydání",
|
||||
"reload": "Nově načíst",
|
||||
"reset_defaults": "Obnovit výchozí hodnoty",
|
||||
"reset_options": "Obnovit možnosti",
|
||||
"restart": "Restartovat",
|
||||
"restart_name": "Restartovat {name}",
|
||||
"running_version": "Aktuálně používáte verzi {version}",
|
||||
"save": "Uložit",
|
||||
"show_more": "Zobrazit o tom více informací",
|
||||
"update": "Aktualizovat",
|
||||
"update_available": "{count, plural,\n one {Aktualizace}\n few {{count} aktualizace}\n other {{count} aktualizací}\n}",
|
||||
"version": "Verze",
|
||||
@@ -192,6 +302,7 @@
|
||||
"title": "Obnovit možnosti"
|
||||
},
|
||||
"restart": {
|
||||
"text": "Opravdu chcete restartovat {name}?",
|
||||
"title": "Restartovat {name}"
|
||||
},
|
||||
"update": {
|
||||
@@ -203,7 +314,8 @@
|
||||
"addon_new_version": "K dispozici je nová verze",
|
||||
"addon_running": "Doplněk je spuštěn",
|
||||
"addon_stopped": "Doplněk je zastaven",
|
||||
"addons": "Doplňky"
|
||||
"addons": "Doplňky",
|
||||
"no_addons": "Zatím nemáte nainstalované žádné doplňky. Chcete-li začít, přejděte do obchodu s doplňky."
|
||||
},
|
||||
"dialog": {
|
||||
"network": {
|
||||
@@ -211,11 +323,15 @@
|
||||
"dhcp": "DHCP",
|
||||
"disabled": "Zakázáno",
|
||||
"dns_servers": "Servery DNS",
|
||||
"failed_to_change": "Nepodařilo se změnit nastavení sítě",
|
||||
"gateway": "IP adresa brány",
|
||||
"ip_netmask": "IP adresa/Maska sítě",
|
||||
"open": "Otevřít",
|
||||
"scan_ap": "Hledat přístupové body",
|
||||
"static": "Statická",
|
||||
"title": "Nastavení sítě",
|
||||
"unsaved": "Máte neuložené změny, které budou ztraceny, pokud změníte záložku. Chcete pokračovat?",
|
||||
"warning": "Pokud měníte nastavení Wi-Fi, IP adresu nebo adresu brány, můžete ztratit připojení!",
|
||||
"wep": "WEP",
|
||||
"wpa": "wpa-psk"
|
||||
},
|
||||
@@ -228,6 +344,8 @@
|
||||
"password": "Heslo",
|
||||
"registry": "Registr",
|
||||
"remove": "Odebrat",
|
||||
"title_add": "Přidat nový registr kontejnerů",
|
||||
"title_manage": "Spravovat registry kontejnerů",
|
||||
"username": "Uživatelské jméno"
|
||||
},
|
||||
"repositories": {
|
||||
@@ -240,14 +358,15 @@
|
||||
"text": "Chcete doplněk restartovat se svými změnami?"
|
||||
},
|
||||
"update": {
|
||||
"create_snapshot": "Vytvořit zálohu \"{name}\" před aktualizací",
|
||||
"create_snapshot": "Vytvořit zálohu {name} před aktualizací",
|
||||
"snapshot": "Záloha",
|
||||
"snapshotting": "Vytváří se záloha \"{name}\"",
|
||||
"updating": "Aktualizuje se \"{name}\" na verzi {version}"
|
||||
"snapshotting": "Vytváří se záloha {name}",
|
||||
"updating": "Aktualizuje se {name} na verzi {version}"
|
||||
}
|
||||
},
|
||||
"my": {
|
||||
"error": "Nastala neznámá chyba",
|
||||
"error_addon_not_found": "Doplněk nebyl nalezen",
|
||||
"faq_link": "Časté dotazy týkající se My Home Assistant",
|
||||
"not_supported": "Toto přesměrování není vaší instancí Home Assistant podporováno. Zkontrolujte {link} pro podporovaná přesměrování a verzi, ve které byla zavedena."
|
||||
},
|
||||
@@ -264,6 +383,7 @@
|
||||
"create": "Vytvořit",
|
||||
"create_blocked_not_running": "Vytvoření zálohy není momentálně možné, protože systém je ve \"{state}\".",
|
||||
"create_snapshot": "Vytvořit zálohu",
|
||||
"description": "Snímky umožňují snadno zálohovat a obnovovat všechna data instance Home Assistant.",
|
||||
"enter_password": "Prosím zadejte heslo.",
|
||||
"folder": {
|
||||
"addons/local": "Místní doplňky",
|
||||
@@ -285,14 +405,29 @@
|
||||
"upload_snapshot": "Nahrát zálohu"
|
||||
},
|
||||
"store": {
|
||||
"missing_addons": "Chybí doplňky? Na stránce svého uživatelského profilu povolte pokročilý režim",
|
||||
"no_results_found": "V {repository} nebyly nalezeny žádné výsledky.",
|
||||
"registries": "Registry",
|
||||
"repositories": "Repozitáře"
|
||||
},
|
||||
"system": {
|
||||
"core": {
|
||||
"cpu_usage": "Využití procesoru jádrem",
|
||||
"ram_usage": "Využití paměti RAM jádrem"
|
||||
},
|
||||
"host": {
|
||||
"change": "Změnit",
|
||||
"change_hostname": "Změnit název hostitele",
|
||||
"confirm_reboot": "Opravdu chcete restartovat hostitele?",
|
||||
"confirm_shutdown": "Opravdu chcete vypnout hostitele?",
|
||||
"deployment": "Nasazení",
|
||||
"docker_version": "Verze Dockeru",
|
||||
"emmc_lifetime_used": "Použitá životnost eMMC",
|
||||
"failed_to_get_hardware_list": "Nepodařilo se získat seznam hardwaru",
|
||||
"failed_to_import_from_usb": "Import z USB se nezdařil",
|
||||
"failed_to_reboot": "Nepodařilo se restartovat hostitele",
|
||||
"failed_to_set_hostname": "Nastavení názvu hostitele se nezdařilo",
|
||||
"failed_to_shutdown": "Nepodařilo se vypnout hostitele",
|
||||
"hardware": "Hardware",
|
||||
"hostname": "Název hostitele",
|
||||
"import_from_usb": "Importovat z USB",
|
||||
@@ -303,25 +438,52 @@
|
||||
"shutdown_host": "Vypnout hostitele",
|
||||
"used_space": "Použité místo"
|
||||
},
|
||||
"log": {
|
||||
"get_logs": "Nepodařilo se získat protokoly {provider}, {error}",
|
||||
"log_provider": "Poskytovatel protokolu"
|
||||
},
|
||||
"supervisor": {
|
||||
"beta_backup": "Před aktivací této funkce se ujistěte, že máte zálohy svých dat.",
|
||||
"beta_join_confirm": "Chcete se připojit k beta kanálu?",
|
||||
"beta_release_items": "To zahrnuje beta verze pro:",
|
||||
"beta_warning": "Beta verze jsou určeny pro testery a nedočkavce a mohou obsahovat nestabilní změny kódu",
|
||||
"channel": "Kanál",
|
||||
"cpu_usage": "Využití procesoru Supervisorem",
|
||||
"failed_to_reload": "Nové načtení Supervisora se nezdařilo",
|
||||
"failed_to_set_option": "Nastavení možnosti Supervisora se nezdařilo",
|
||||
"failed_to_update": "Aktualizace Supervisora se nezdařila",
|
||||
"join_beta_action": "Připojit se k beta kanálu",
|
||||
"join_beta_description": "Získejte beta aktualizace pro Home Assistant (RC), Supervisor a hostitele",
|
||||
"leave_beta_action": "Opustit beta kanál",
|
||||
"leave_beta_description": "Získejte stabilní aktualizace pro Home Assistant, Supervisor a hostitele",
|
||||
"ram_usage": "Využití paměti RAM Supervisorem",
|
||||
"reload_supervisor": "Nově načíst Supervisor",
|
||||
"share_diagnostics": "Sdílet diagnostické informace",
|
||||
"share_diagnostics_description": "Sdílejte zprávy o selhání a diagnostické informace.",
|
||||
"share_diagonstics_description": "Chcete automaticky sdílet zprávy o selhání a diagnostické informace, když Supervisor narazí na neočekávané chyby? {line_break} To nám umožní vyřešit problémy, informace jsou přístupné pouze týmu Home Assistant Core a nebudou sdíleny s ostatními. {line_break} Data neobsahují žádné soukromé / citlivé informace a tato volba může být kdykoliv deaktivována v nastavení.",
|
||||
"share_diagonstics_title": "Pomozte vylepšit Home Asistent",
|
||||
"unhealthy_description": "Používáním instalace, která není v pořádku způsobí problémy. Níže je uveden seznam problémů nalezených ve vaší instalaci. Kliknutím na odkazy se dozvíte, jak tyto problémy vyřešit.",
|
||||
"unhealthy_reason": {
|
||||
"docker": "Prostředí Docker nefunguje správně",
|
||||
"privileged": "Supervisor není privilegovaný",
|
||||
"setup": "Nastavení Supervisora se nezdařilo",
|
||||
"supervisor": "Supervisor se nepodařilo aktualizovat"
|
||||
},
|
||||
"unhealthy_title": "Instalace není v pořádku",
|
||||
"unsupported_description": "Níže je uveden seznam problémů nalezených ve vaší instalaci. Kliknutím na odkazy se dozvíte, jak tyto problémy vyřešit.",
|
||||
"unsupported_reason": {
|
||||
"container": "Kontejnery, o nichž je známo, že způsobují problémy",
|
||||
"dbus": "DBUS",
|
||||
"docker_configuration": "Konfigurace Dockeru",
|
||||
"docker_version": "Verze Dockeru",
|
||||
"job_conditions": "Ignorované podmínky úlohy",
|
||||
"lxc": "LXC",
|
||||
"network_manager": "Správce sítě",
|
||||
"os": "Operační systém",
|
||||
"privileged": "Supervisor není privilegovaný",
|
||||
"systemd": "Systemd"
|
||||
},
|
||||
"unsupported_title": "Používáte nepodporovanou instalaci",
|
||||
"update_supervisor": "Aktualizovat Supervisor",
|
||||
"warning": "VAROVÁNÍ"
|
||||
}
|
||||
@@ -851,6 +1013,9 @@
|
||||
"person": {
|
||||
"create_zone": "Vytvořit zónu z aktuálního umístění"
|
||||
},
|
||||
"remote": {
|
||||
"activity": "Současná aktivita"
|
||||
},
|
||||
"restored": {
|
||||
"confirm_remove_text": "Opravdu chcete tuto entitu odebrat?",
|
||||
"confirm_remove_title": "Odebrat entitu?",
|
||||
@@ -980,13 +1145,16 @@
|
||||
"buttons": {
|
||||
"add": "Přidejte zařízení prostřednictvím tohoto zařízení",
|
||||
"clusters": "Správa clusterů",
|
||||
"device_children": "Zobrazit potomky",
|
||||
"reconfigure": "Přenastavit zařízení",
|
||||
"remove": "Odebrat zařízení",
|
||||
"view_in_visualization": "Zobrazit ve vizualizaci",
|
||||
"zigbee_information": "Podpis zařízení Zigbee"
|
||||
},
|
||||
"confirmations": {
|
||||
"remove": "Opravdu chcete zařízení odebrat?"
|
||||
},
|
||||
"device_children": "Potomci Zigbee zařízení",
|
||||
"device_signature": "Podpis zařízení Zigbee",
|
||||
"last_seen": "Naposledy viděn",
|
||||
"manuf": "od {manufacturer}",
|
||||
@@ -1021,6 +1189,7 @@
|
||||
"key_missing": "Chybí požadovaný klíč \"{key}\".",
|
||||
"key_not_expected": "Klíč \"{key}\" není vizuálním editorem očekáván nebo podporován.",
|
||||
"key_wrong_type": "Zadávanou hodnotu \"{key}\" nepodporuje vizuální editor. Podporuje ({type_correct}), ale obdržel ({type_wrong}).",
|
||||
"no_template_editor_support": "Šablony nejsou podporovány v uživatelském rozhraní",
|
||||
"no_type_provided": "Není k dispozici žádný typ."
|
||||
}
|
||||
},
|
||||
@@ -1128,10 +1297,15 @@
|
||||
"device_id": {
|
||||
"action": "Akce",
|
||||
"extra_fields": {
|
||||
"brightness_pct": "Jas",
|
||||
"code": "Kód",
|
||||
"flash": "Blikat",
|
||||
"humidity": "Vlhkost vzduchu",
|
||||
"message": "Zpráva",
|
||||
"mode": "Režim",
|
||||
"position": "Pozice",
|
||||
"title": "Název"
|
||||
"title": "Název",
|
||||
"value": "Hodnota"
|
||||
},
|
||||
"label": "Zařízení"
|
||||
},
|
||||
@@ -1204,7 +1378,9 @@
|
||||
"extra_fields": {
|
||||
"above": "Větší než",
|
||||
"below": "Menší než",
|
||||
"for": "Doba trvání"
|
||||
"for": "Doba trvání",
|
||||
"hvac_mode": "Režim HVAC",
|
||||
"preset_mode": "Předvolba"
|
||||
},
|
||||
"label": "Zařízení"
|
||||
},
|
||||
@@ -1397,6 +1573,8 @@
|
||||
"add_automation": "Přidat automatizaci",
|
||||
"delete_automation": "Odstranit automatizaci",
|
||||
"delete_confirm": "Opravdu chcete odstranit tuto automatizaci?",
|
||||
"dev_automation": "Debugování automatizace",
|
||||
"dev_only_editable": "Pouze automatizace definované v automations.yaml jsou debugovatelné",
|
||||
"duplicate": "Duplikát",
|
||||
"duplicate_automation": "Duplikovat automatizaci",
|
||||
"edit_automation": "Upravit automatizaci",
|
||||
@@ -1460,6 +1638,8 @@
|
||||
},
|
||||
"introduction": "Nastavení šablon vám umožňuje importovat a spravovat vaše šablony.",
|
||||
"learn_more": "Další informace o používání šablon",
|
||||
"share_blueprint": "Sdílet šablonu",
|
||||
"share_blueprint_no_url": "Nelze sdílet šablonu: žádná zdrojová URL adresa",
|
||||
"use_blueprint": "Vytvořit automatizaci"
|
||||
}
|
||||
},
|
||||
@@ -1487,9 +1667,9 @@
|
||||
"devices_pin": "PIN pro zabezpečovací zařízení",
|
||||
"enable_ha_skill": "Povolte Home Assistant skill pro Google Assistant",
|
||||
"enable_state_reporting": "Povolit hlášení stavu",
|
||||
"enter_pin_error": "Nelze uložit pin:",
|
||||
"enter_pin_error": "Nelze uložit PIN:",
|
||||
"enter_pin_hint": "Chcete-li používat zabezpečovací zařízení, zadejte kód PIN",
|
||||
"enter_pin_info": "Chcete-li komunikovat se zabezpečovacími zařízeními, zadejte kód PIN. Zabezpečovací zařízení jsou dveře, garážová vrata a zámky. Při interakci s takovými zařízeními budete požádáni o zadání / zadání tohoto kódu PIN pomocí Google Assistant.",
|
||||
"enter_pin_info": "Chcete-li komunikovat se zabezpečovacími zařízeními, zadejte kód PIN. Zabezpečovací zařízení jsou dveře, garážová vrata a zámky. Při interakci s takovými zařízeními budete požádáni o zadání tohoto PIN kódu pomocí Google Assistant.",
|
||||
"info": "Díky integraci Google Assistant pro Home Assistant Cloud budete moci ovládat všechna zařízení v Home Assistant pomocí jakéhokoli zařízení podporujícího Google Assistant.",
|
||||
"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 Google. Toto vám umožní sledovat vždy aktuální stavy entit v aplikaci Google.",
|
||||
"manage_entities": "Správa entit",
|
||||
@@ -2480,7 +2660,7 @@
|
||||
"add_device": "Přidat zařízení",
|
||||
"add_device_page": {
|
||||
"discovered_text": "Jakmile se objeví nalezne, zobrazí se zde.",
|
||||
"no_devices_found": "Žádná zařízení nalezena, ujistěte se, že jsou v režimu párování a udržujte je zapnuté, zatímco je objevování spuštěno.",
|
||||
"no_devices_found": "Nebyla nalezena žádná zařízení, ujistěte se, že jsou v režimu párování a udržujte je v aktivním stavu, zatímco je objevování spuštěno.",
|
||||
"pairing_mode": "Zkontrolujte, zda jsou vaše zařízení v režimu párování. Postupujte podle pokynů svého zařízení.",
|
||||
"search_again": "Hledat znovu",
|
||||
"spinner": "Hledání zařízení ZHA Zigbee ..."
|
||||
@@ -2556,9 +2736,11 @@
|
||||
"caption": "Síť"
|
||||
},
|
||||
"visualization": {
|
||||
"auto_zoom": "Automatické přiblížení",
|
||||
"caption": "Vizualizace",
|
||||
"header": "Vizualizace sítě",
|
||||
"highlight_label": "Zvýraznit zařízení",
|
||||
"refresh_topology": "Aktualizovat topologii",
|
||||
"zoom_label": "Přiblížit na zařízení"
|
||||
}
|
||||
},
|
||||
@@ -2642,6 +2824,10 @@
|
||||
"connecting": "Připojování",
|
||||
"unknown": "Nezjištěno"
|
||||
},
|
||||
"node_config": {
|
||||
"error_device_not_found": "Zařízení nenalezeno",
|
||||
"parameter_is_read_only": "Tento parametr je jen pro čtení."
|
||||
},
|
||||
"node_status": {
|
||||
"alive": "Naživu",
|
||||
"asleep": "Spící",
|
||||
@@ -2831,6 +3017,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"go_back": "Vrátit se",
|
||||
"supervisor": {
|
||||
"ask": "Požádat o pomoc",
|
||||
"system_health": "Kontrola stavu systému"
|
||||
}
|
||||
},
|
||||
"history": {
|
||||
"ranges": {
|
||||
"last_week": "Minulý týden",
|
||||
@@ -3236,6 +3429,7 @@
|
||||
"error_remove": "Nelze odstranit nastavení: {error}",
|
||||
"error_save_yaml": "Nelze uložit YAML: {error}",
|
||||
"header": "Upravit nastavení",
|
||||
"lovelace_changed": "Konfigurace Lovelace byla aktualizována, chcete načíst aktualizovanou konfiguraci do editoru a přijít o aktuální změny?",
|
||||
"reload": "Nově načíst",
|
||||
"resources_moved": "Zdroje by již neměly být přidávány do konfigurace Lovelace, ale mohou být přidávány v panelu nastavení Lovelace.",
|
||||
"save": "Uložit",
|
||||
|
||||
+483
-22
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"config_entry": {
|
||||
"disabled_by": {
|
||||
"config_entry": "Konfigurationstilstand",
|
||||
"config_entry": "Konfigurationsparameter",
|
||||
"device": "Enhed",
|
||||
"integration": "Integration",
|
||||
"user": "Bruger"
|
||||
@@ -103,33 +103,234 @@
|
||||
}
|
||||
},
|
||||
"supervisor": {
|
||||
"addon": {
|
||||
"configuration": {
|
||||
"audio": {
|
||||
"default": "Standard",
|
||||
"header": "Lyd",
|
||||
"input": "Input",
|
||||
"output": "Output"
|
||||
},
|
||||
"network": {
|
||||
"container": "Container",
|
||||
"disabled": "Deaktiveret",
|
||||
"header": "Netværk",
|
||||
"host": "Vært"
|
||||
},
|
||||
"no_configuration": "Dette tilføjelsesprogram har ingen konfiguration, som du kan tilpasse...",
|
||||
"options": {
|
||||
"edit_in_ui": "Rediger i brugergrænsefladen",
|
||||
"edit_in_yaml": "Rediger i YAML",
|
||||
"header": "Indstillinger",
|
||||
"invalid_yaml": "Ugyldig YAML",
|
||||
"show_unused_optional": "Vis valgfri konfigurationsindstillinger, der ikke er anvendt"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"action_error": {
|
||||
"get_changelog": "Ændringsloggen for tilføjelsesprogrammet kunne ikke hentes",
|
||||
"go_to_config": "Tilføjelsesprogrammet kunne ikke startes - validering af konfigurationen mislykkedes!",
|
||||
"install": "Tilføjelsesprogrammet kunne ikke installeres",
|
||||
"restart": "Tilføjelsesprogrammet kunne ikke genstartes",
|
||||
"start": "Tilføjelsesprogrammet kunne ikke startes",
|
||||
"start_invalid_config": "Gå til konfiguration",
|
||||
"stop": "Tilføjelsesprogrammet kunne ikke stoppes",
|
||||
"uninstall": "Tilføjelsesprogrammet kunne ikke fjernes",
|
||||
"validate_config": "Konfigurationen af tilføjelsesprogrammet kunne ikke valideres"
|
||||
},
|
||||
"capability": {
|
||||
"apparmor": {
|
||||
"description": "AppArmor ('Application Armor') er et Linux-kernesikkerhedsmodul, der begrænser tilføjelsesprogrammets adgang til netværket, adgang til netværkstrafik samt tilladelse til at læse, skrive eller afvikle bestemte filer.\n\nTilføjelsesprogrammets udviklere kan optimere sikkerhedsindstillingerne for tilføjelsesprogrammet eller anmode om, at de deaktiveres. Hvis AppArmor er deaktiveret, vil det øge sikkerhedsrisiciene og har derfor en negativ indvirkning på sikkerhedsscoren for tilføjelsesprogrammet.",
|
||||
"title": "AppArmor"
|
||||
},
|
||||
"auth_api": {
|
||||
"description": "Et tilføjelsesprogram kan godkende Home Assistant brugere, så tilføjelsesprogrammet giver brugerne mulighed for at logge ind på programmer, der kører i tilføjelsesprogrammet ved hjælp af deres Home Assistant brugernavn/adgangskode. Dette symbol angiver, om udvikleren af tilføjelsesprogrammet har anvendt denne funktion.",
|
||||
"title": "Home Assistant autentifikation"
|
||||
},
|
||||
"docker_api": {
|
||||
"description": "Tilføjelsesprogrammets udviklere har anmodet om at få adgang til administration af Docker på dit system. Dette giver tilføjelsesprogrammet fuld adgang til og kontrol med hele dit Home Assistant system, hvilket medfører sikkerhedsrisici og kan beskadige dit system. Derfor påvirker dette sikkerhedsvurderingen for tilføjelsesprogrammet negativt.\n\nAdgangen tildeles ikke automatisk og skal bekræftes af dig. Du skal derfor deaktivere beskyttelsestilstanden på tilføjelsesprogrammet manuelt. Deaktiver kun beskyttelsestilstanden, hvis du kender OG har tillid til udviklerne af dette tilføjelsesprogram.",
|
||||
"title": "Fuld adgang til Docker"
|
||||
},
|
||||
"full_access": {
|
||||
"description": "Dette tilføjelsesprogram får fuld adgang til systemets hardware efter anmodning fra tilføjelsesprogrammets udviklere. Adgangen kan sammenlignes med den privilegerede tilstand i Docker. Da dette medfører mulige sikkerhedsrisici, påvirker dette tilføjelsesprogrammets sikkerhedsvurdering negativt.\n\nAdgangen tildeles ikke automatisk og skal bekræftes af dig. Du skal derfor deaktivere beskyttelsestilstanden på tilføjelsesprogrammet manuelt. Deaktiver kun beskyttelsestilstanden, hvis du kender OG har tillid til udviklerne af dette tilføjelsesprogram.",
|
||||
"title": "Fuld adgang til hardware"
|
||||
},
|
||||
"hassio_api": {
|
||||
"description": "Tilføjelsesprogrammet har fået adgang til Supervisor API efter anmodning fra tilføjelsesprogrammets udviklere. Som standard kan tilføjelsesprogrammet få adgang til generelle versionsoplysninger om dit system. Når tilføjelsesprogrammet anmoder om 'Manager' eller 'Administrator' adgangsrettigheder til API'et, får tilføjelsesprogrammet adgang til at kontrollere flere dele af dit Home Assistant system. Denne tilladelse er fremhævet med dette symbol og vil påvirke tilføjelsesprogrammets sikkerhedsvurdering negativt.",
|
||||
"title": "Adgang til Supervisor API"
|
||||
},
|
||||
"homeassistant_api": {
|
||||
"description": "Dette tilføjelsesprogram har tilladelse til at tilgå dit Home Assistant system via API kald. Denne tilstand håndterer også godkendelse for tilføjelsesprogrammet, hvilket gør det muligt for tilføjelsesprogrammet at interagere med Home Assistant uden yderligere godkendelse.",
|
||||
"title": "Home Assistant API-adgang"
|
||||
},
|
||||
"host_network": {
|
||||
"description": "Tilføjelsesprogrammer kører normalt i deres eget isolerede netværkslag, hvilket forhindrer dem i at få adgang til netværket på værtsoperativsystemet. I nogle tilfælde kan netværksisolationen begrænse tilføjelsesprogrammets funktionalitet, og derfor kan isolationen ophæves af udvikleren af tilføjelsesprogrammet, hvilket kan give programmet fuld adgang til værtsmaskinens netværksfunktioner. Dette reducerer sikkerheden og påvirker derfor sikkerhedsvurderingen af tilføjelsesprogrammet, når denne indstilling bruges af tilføjelsesprogrammet.",
|
||||
"title": "Værtsnetværk"
|
||||
},
|
||||
"host_pid": {
|
||||
"description": "Normalt er de processer, som tilføjelsesprogrammet kører, isoleret fra alle andre systemprocesser. Tilføjelsesprogrammets udviklere har anmodet om at få adgang til de systemprocesser, der kører på værtsoperativsystemet, og give tilføjelsesprogrammet mulighed for også at afvikle processer på værtssystemet. Dette giver tilføjelsesprogrammet fuld adgang til og kontrol til hele dit Home Assistant system, hvilket medfører sikkerhedsrisici og kan beskadige dit system. Derfor påvirker dette sikkerhedsvurderingen for tilføjelsesprogrammet negativt.\n\nDette adgangsniveau gives ikke automatisk og skal bekræftes af dig. Du skal derfor deaktivere beskyttelsestilstanden på tilføjelsesprogrammet manuelt. Deaktiver kun beskyttelsestilstanden, hvis du kender OG har tillid til udviklerne af dette tilføjelsesprogram.",
|
||||
"title": "Navneområde for værtsprocesser"
|
||||
},
|
||||
"ingress": {
|
||||
"description": "Denne tilføjelse bruger Ingress til at integrere sin grænseflade sikkert i Home Assistant.",
|
||||
"title": "Ingress"
|
||||
},
|
||||
"label": {
|
||||
"apparmor": "apparmor",
|
||||
"auth": "godkendelse",
|
||||
"docker": "docker",
|
||||
"hardware": "hardware",
|
||||
"hass": "hass",
|
||||
"hassio": "hassio",
|
||||
"host": "vært",
|
||||
"host_pid": "vært pid",
|
||||
"ingress": "ingress",
|
||||
"rating": "bedømmelse",
|
||||
"stage": "Fase"
|
||||
},
|
||||
"rating": {
|
||||
"description": "Home Assistant viser en sikkerhedsvurdering for hvert tilføjelsesprogram. Vurderingen angiver risici forbundet med brugen af det pågældende tilføjelsesprogram. Sikkerhedsvurderingen tager bl.a. hensyn til hvilken adgang et givet tilføjelsesprogram kræver til dit system.\n\nSikkerhedsvurderingen giver en score på en skala fra 1 til 6, hvor 1 er den laveste score (betragtes som den mest usikre og højeste risiko), og en score på 6 er den højeste score (betragtes som den mest sikre og laveste risiko).",
|
||||
"title": "Sikkerhedsklassifikation for tilføjelsesprogram"
|
||||
},
|
||||
"role": {
|
||||
"admin": "Administrator",
|
||||
"backup": "sikkerhedskopi",
|
||||
"default": "Standard",
|
||||
"homeassistant": "homeassistant",
|
||||
"manager": "Manager"
|
||||
},
|
||||
"stage": {
|
||||
"description": "Tilføjelsesprogrammer kan have en af tre faser:\n\n{icon_stable} **Stabil**: Disse tilføjelsesprogrammer er klar til brug i produktionen.\n\n{icon_experimental} **Eksperimentel**: Disse tilføjelsesprogrammer indeholde fejl og kan være ufærdige.\n\n{icon_deprecated} **Forældet**: Disse tilføjelsesprogrammer modtager ikke længere opdateringer.",
|
||||
"title": "Fase for tilføjelsesprogram"
|
||||
}
|
||||
},
|
||||
"changelog": "Ændringshistorik",
|
||||
"cpu_usage": "Tilføjelsesprogrammets forbrug af CPU",
|
||||
"hostname": "Værtsnavn",
|
||||
"install": "installer",
|
||||
"new_update_available": "{name} {version} er tilgængelig",
|
||||
"not_available_arch": "Dette tilføjelsesprogram er ikke kompatibelt med processoren på enheden eller det operativsystem, du har installeret på enheden.",
|
||||
"not_available_version": "Du kører Home Assistant {core_version_installed}. For at opdatere dette tilføjelsesprogram, skal du køre version {core_version_needed} eller nyere versioner af Home Assistant",
|
||||
"open_web_ui": "Åbn webbrugergrænseflade",
|
||||
"option": {
|
||||
"auto_update": {
|
||||
"description": "Opdater automatisk tilføjelsesprogrammet, når en ny version er tilgængelig",
|
||||
"title": "Automatisk opdatering"
|
||||
},
|
||||
"boot": {
|
||||
"description": "Start tilføjelsesprogrammet under en systemstart",
|
||||
"title": "Start ved opstart"
|
||||
},
|
||||
"ingress_panel": {
|
||||
"description": "Føj dette tilføjelsesprogram til sidepanelet",
|
||||
"title": "Vis i sidepanel"
|
||||
},
|
||||
"protected": {
|
||||
"description": "Blokerer forhøjet systemadgang fra tilføjelsesprogrammet",
|
||||
"title": "Beskyttelsestilstand"
|
||||
},
|
||||
"watchdog": {
|
||||
"description": "Dette starter tilføjelsesprogrammet, hvis det går ned",
|
||||
"title": "Vagthund"
|
||||
}
|
||||
},
|
||||
"protection_mode": {
|
||||
"content": "Beskyttelsestilstand på dette tilføjelsesprogram er deaktiveret! Dette giver tilføjelsesprogrammet fuld adgang til hele systemet, hvilket medfører sikkerhedsrisici og kan beskadige dit system. Deaktiver kun beskyttelsestilstanden, hvis du kender, har brug for og har tillid til udvikleren bag dette tilføjelsesprogram.",
|
||||
"enable": "Aktivér beskyttelsestilstand",
|
||||
"title": "Advarsel: Beskyttelsestilstand er deaktiveret!"
|
||||
},
|
||||
"ram_usage": "Tilføjelsesprogrammets forbrug af RAM",
|
||||
"rebuild": "genopbyg",
|
||||
"restart": "genstart",
|
||||
"start": "start",
|
||||
"stop": "stop",
|
||||
"uninstall": "afinstaller",
|
||||
"visit_addon_page": "Besøg siden {name} for at få flere oplysninger"
|
||||
},
|
||||
"documentation": {
|
||||
"get_documentation": "Dokumentationen for tilføjelsesprogrammet kunne ikke hentes, {error}"
|
||||
},
|
||||
"failed_to_reset": "Konfigurationen af tilføjelsesprogrammet kunne ikke nulstilles, {error}",
|
||||
"failed_to_save": "Konfigurationen af tilføjelsesprogrammet kunne ikke gemmes, {error}",
|
||||
"logs": {
|
||||
"get_logs": "Logfiler for tilføjelsesprogrammet kunne ikke hentes, {error}"
|
||||
},
|
||||
"panel": {
|
||||
"configuration": "Konfiguration",
|
||||
"documentation": "Dokumentation",
|
||||
"info": "Info",
|
||||
"log": "Logfil"
|
||||
},
|
||||
"state": {
|
||||
"installed": "Tilføjelsesprogrammet er installeret",
|
||||
"not_available": "Tilføjelsesprogrammet er ikke tilgængeligt på dit system",
|
||||
"not_installed": "Tilføjelsesprogrammet er ikke installeret"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"cancel": "Afbryd",
|
||||
"cancel": "Annuller",
|
||||
"close": "Luk",
|
||||
"description": "Beskrivelse",
|
||||
"error": {
|
||||
"unknown": "Ukendt fejl",
|
||||
"update_failed": "Opdateringen mislykkedes"
|
||||
},
|
||||
"failed_to_restart_name": "Ude af stand til at genstarte {name}",
|
||||
"failed_to_update_name": "Ude af stand til at updatere {name}",
|
||||
"learn_more": "Lær mere",
|
||||
"new_version_available": "Ny version tilgængelig",
|
||||
"newest_version": "Nyeste version",
|
||||
"no": "Nej",
|
||||
"refresh": "Opdater",
|
||||
"release_notes": "Udgivelses noter",
|
||||
"reload": "Genindlæs",
|
||||
"reset_defaults": "gendan standardindstillinger",
|
||||
"reset_options": "Genstart indstillinger",
|
||||
"restart": "Genstart",
|
||||
"restart_name": "Genstart {name}",
|
||||
"save": "Gem"
|
||||
"running_version": "Du bruger pt. version",
|
||||
"save": "Gem",
|
||||
"show_more": "Vis flere oplysninger om dette",
|
||||
"update": "Opdater",
|
||||
"update_available": "{count, plural,\n one {opdatering}\n other {{count} opdateringer}\n} afventer",
|
||||
"version": "Version",
|
||||
"yes": "Ja"
|
||||
},
|
||||
"confirm": {
|
||||
"reset_options": {
|
||||
"text": "Er du sikker på, at du vil nulstille alle dine indstillinger?",
|
||||
"title": "Nulstil indstillinger"
|
||||
},
|
||||
"restart": {
|
||||
"text": "Er du sikker på at du vil genstarte {name}?",
|
||||
"title": "Genstart {name}"
|
||||
},
|
||||
"update": {
|
||||
"text": "Er du sikker på, at du vil opdatere {name} til version {version} ?",
|
||||
"title": "Opdater {name}"
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"addon_new_version": "En ny version er tilgængelig",
|
||||
"addon_running": "Tilføjelsesprogrammet kører",
|
||||
"addon_stopped": "Tilføjelsesprogrammet er stoppet",
|
||||
"addons": "Tilføjelsesprogrammer",
|
||||
"no_addons": "Du har endnu ikke installeret nogen tilføjelsesprogrammer. Gå over til butikken for tilføjelsesprogrammer for at komme i gang!"
|
||||
},
|
||||
"dialog": {
|
||||
"network": {
|
||||
"connected_to": "Forbundet til {ssid}",
|
||||
"dhcp": "DHCP",
|
||||
"disabled": "Deaktiveret",
|
||||
"dns_servers": "DNS servere",
|
||||
"failed_to_change": "Ændring af netværksindstillingerne fejlede",
|
||||
"gateway": "Gateway adresse",
|
||||
"ip_netmask": "IP adresse/netmaske",
|
||||
"open": "Åben",
|
||||
"scan_ap": "Scan for adgangspunkter",
|
||||
"static": "Statisk",
|
||||
"title": "Netværksindstillinger",
|
||||
"unsaved": "Du har ikke gemte ændringer, hvis du fortsætter, vil disse gå tabt",
|
||||
"warning": "Hvis du ændrer på Wi-Fi, IP eller Gateway adresser, vil du måske miste forbindelsen!",
|
||||
"wep": "WEP",
|
||||
"wpa": "wpa-psk"
|
||||
@@ -143,6 +344,7 @@
|
||||
"password": "Kodeord",
|
||||
"registry": "Registry",
|
||||
"remove": "Fjern",
|
||||
"title_add": "Tilføj nyt containerregister",
|
||||
"title_manage": "Håndtér container registries",
|
||||
"username": "Brugernavn"
|
||||
},
|
||||
@@ -162,6 +364,18 @@
|
||||
"updating": "Opdaterer {name} til version {version}"
|
||||
}
|
||||
},
|
||||
"my": {
|
||||
"error": "Der opstod en ukendt fejl",
|
||||
"error_addon_not_found": "Add-on ikke fundet",
|
||||
"faq_link": "Ofte stillede spørgsmål om Home Assistant",
|
||||
"not_supported": "Denne omdirigering understøttes ikke af din Home Assistant installation. Kontroller {link} for de understøttede omdirigeringer og den version, de blev introduceret i."
|
||||
},
|
||||
"panel": {
|
||||
"dashboard": "Betjeningspanel",
|
||||
"snapshots": "Snapshots",
|
||||
"store": "Butik for tilføjelsesprogrammer",
|
||||
"system": "System"
|
||||
},
|
||||
"snapshot": {
|
||||
"addons": "Tilføjelser",
|
||||
"available_snapshots": "Tilgængelige snapshots",
|
||||
@@ -190,16 +404,30 @@
|
||||
"type": "Type",
|
||||
"upload_snapshot": "Opload snapshot"
|
||||
},
|
||||
"store": {
|
||||
"missing_addons": "Mangler du tilføjelsesprogrammer? Aktivér avanceret tilstand på din brugerprofilside.",
|
||||
"no_results_found": "Der blev ikke fundet nogen resultater i {repository}.",
|
||||
"registries": "Registre",
|
||||
"repositories": "Tilføjelsesregistre"
|
||||
},
|
||||
"system": {
|
||||
"core": {
|
||||
"cpu_usage": "Core CPU forbrug",
|
||||
"ram_usage": "Core RAM forbrug"
|
||||
},
|
||||
"host": {
|
||||
"change": "Ændre",
|
||||
"change_hostname": "Skift værtsnavn",
|
||||
"confirm_reboot": "Er du sikker på, at du vil genstarte værten?",
|
||||
"confirm_shutdown": "Er du sikker på, at du vil lukke værten ned?",
|
||||
"deployment": "Installation",
|
||||
"docker_version": "Docker-version",
|
||||
"emmc_lifetime_used": "Anvendt eMMC levetid",
|
||||
"failed_to_get_hardware_list": "Hardwarelisten kunne ikke hentes",
|
||||
"failed_to_import_from_usb": "Importer fra USB fejlede",
|
||||
"failed_to_reboot": "Kunne ikke genstarte host maskinen",
|
||||
"failed_to_set_hostname": "Indstilling af værtsnavn mislykkedes",
|
||||
"failed_to_shutdown": "Fejlede nedlukning af host",
|
||||
"hardware": "Hardware",
|
||||
"hostname": "Værtsnavn",
|
||||
"import_from_usb": "Importer fra USB",
|
||||
@@ -210,12 +438,54 @@
|
||||
"shutdown_host": "Sluk vært",
|
||||
"used_space": "Plads forbrug"
|
||||
},
|
||||
"log": {
|
||||
"get_logs": "Kunne ikke hente {provider} -logfiler, {error}",
|
||||
"log_provider": "Logudbyder"
|
||||
},
|
||||
"supervisor": {
|
||||
"beta_backup": "Sørg for, at du har sikkerhedskopier af dine data, før du aktiverer denne funktion.",
|
||||
"beta_join_confirm": "Vil du tilmelde dig beta-kanalen?",
|
||||
"beta_release_items": "Dette omfatter betaversioner af:",
|
||||
"beta_warning": "Betaversioner er henvendt til testere og tidlige brugere og kan indeholde ustabil kode",
|
||||
"channel": "Kanal",
|
||||
"cpu_usage": "Supervisor CPU forbrug",
|
||||
"failed_to_reload": "Supervisor kunne ikke genindlæses",
|
||||
"failed_to_set_option": "Indstillingen af Supervisor kunne ikke gennemføres",
|
||||
"failed_to_update": "Supervisor kunne ikke opdateres",
|
||||
"join_beta_action": "Deltag i beta-kanal",
|
||||
"join_beta_description": "Få beta-opdateringer til Home Assistant (RCs), Supervisor og værtsmaskinen",
|
||||
"leave_beta_action": "Forlad betakanal",
|
||||
"leave_beta_description": "Få stabile opdateringer til Home Assistant, Supervisor og værtsmaskinen",
|
||||
"ram_usage": "Supervisor RAM forbrug",
|
||||
"reload_supervisor": "Genindlæs Supervisor",
|
||||
"share_diagnostics": "Del diagnostik",
|
||||
"share_diagnostics_description": "Del oplysninger om nedbrud og diagnosticeringsinformationer.",
|
||||
"share_diagonstics_description": "Ønsker du automatisk at dele rapporter og diagnosticeringsoplysninger når supervisoren oplever uventede fejl? {line_break} Dette vil lade os fikse problemerne, informationerene er kun tilgængelige for Home Assistant Core teamet og vil ikke blive delt med andre. {line_break} Dataene indeholder ikke private/følsomme informationer og du kan slå det fra i indstillingerne til hver en tid.",
|
||||
"share_diagonstics_title": "Hjælp med at forbedre Home Assistant",
|
||||
"unhealthy_description": "At køre en usund installation vil forårsage problemer. Nedenfor er en liste over problemer, der er fundet med din installation. Klik på linkene for at lære, hvordan du kan løse problemerne.",
|
||||
"unhealthy_reason": {
|
||||
"docker": "Docker-miljøet fungerer ikke korrekt",
|
||||
"privileged": "Supervisor er ikke privilegeret",
|
||||
"setup": "Opsætning af Supervisor mislykkedes",
|
||||
"supervisor": "Supervisor kunne ikke opdateres"
|
||||
},
|
||||
"unhealthy_title": "Din installation er usund",
|
||||
"unsupported_description": "Nedenfor er en liste over problemer, der er fundet med din installation. Klik på linkene for at lære, hvordan du kan løse problemerne.",
|
||||
"unsupported_reason": {
|
||||
"container": "Containere, der erfaringsmæssigt giver problemer",
|
||||
"dbus": "DBUS",
|
||||
"docker_configuration": "Konfiguration af Docker",
|
||||
"docker_version": "Docker version",
|
||||
"os": "Operativsystem"
|
||||
}
|
||||
"job_conditions": "Ignorerede jobbetingelser",
|
||||
"lxc": "LXC",
|
||||
"network_manager": "Netværksadministrator",
|
||||
"os": "Operativsystem",
|
||||
"privileged": "Supervisor er ikke privilegeret",
|
||||
"systemd": "Systemd"
|
||||
},
|
||||
"unsupported_title": "Du anvender en ikke-understøttet installation",
|
||||
"update_supervisor": "Opdater Supervisor",
|
||||
"warning": "ADVARSEL"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -276,6 +546,7 @@
|
||||
"direction": "Retning",
|
||||
"forward": "Frem",
|
||||
"oscillate": "Sving",
|
||||
"preset_mode": "Forudindstillet tilstand",
|
||||
"reverse": "Baglæns",
|
||||
"speed": "Hastighed"
|
||||
},
|
||||
@@ -316,7 +587,8 @@
|
||||
},
|
||||
"script": {
|
||||
"cancel": "Annuller",
|
||||
"cancel_multiple": "Annuller {number}"
|
||||
"cancel_multiple": "Annuller {number}",
|
||||
"run": "Kør"
|
||||
},
|
||||
"service": {
|
||||
"run": "Kør"
|
||||
@@ -411,6 +683,19 @@
|
||||
"yes": "Ja"
|
||||
},
|
||||
"components": {
|
||||
"addon-picker": {
|
||||
"addon": "Tilføjelsesprogram",
|
||||
"error": {
|
||||
"fetch_addons": {
|
||||
"description": "Der opstod en fejl under indlæsningen af tilføjelsesprogrammer.",
|
||||
"title": "Fejl ved indlæsning af tilføjelsesprogrammer"
|
||||
},
|
||||
"no_supervisor": {
|
||||
"description": "Ingen supervisor blev fundet, så tilføjelsesprogrammer kunne ikke indlæses.",
|
||||
"title": "Supervisor blev ikke fundet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"area-picker": {
|
||||
"add_dialog": {
|
||||
"add": "Tilføj",
|
||||
@@ -477,8 +762,10 @@
|
||||
"messages": {
|
||||
"became_unavailable": "blev utilgængelig",
|
||||
"changed_to_state": "ændret til {state}",
|
||||
"cleared_device_class": "ryddet (ingen {device_class} registreret)",
|
||||
"cleared_device_class": "ingen {device_class} registreret",
|
||||
"detected_device_class": "registreret {device_class}",
|
||||
"is_closing": "lukker",
|
||||
"is_opening": "åbner",
|
||||
"rose": "stod op",
|
||||
"set": "gik ned",
|
||||
"turned_off": "blev slukket",
|
||||
@@ -583,6 +870,12 @@
|
||||
"week": "{count} {count, plural,\n one {uge}\n other {uger}\n} siden"
|
||||
}
|
||||
},
|
||||
"service-control": {
|
||||
"required": "Dette felt er påkrævet",
|
||||
"service_data": "Service data",
|
||||
"target": "Mål",
|
||||
"target_description": "Hvad skal denne tjeneste bruge som mål områder, enheder eller entiteter."
|
||||
},
|
||||
"service-picker": {
|
||||
"service": "Tjeneste"
|
||||
},
|
||||
@@ -632,9 +925,9 @@
|
||||
"enabled_restart_confirm": "Genstart Home Assistant for at fuldføre aktiveringen af entiteterne",
|
||||
"entity_id": "Entitets-id",
|
||||
"follow_device_area": "Følg enhedsområde",
|
||||
"icon": "Brugerdefineret ikon",
|
||||
"icon": "Ikon",
|
||||
"icon_error": "Ikoner skal være i formatet 'præfiks:ikonnavn', fx. 'mdi:home'",
|
||||
"name": "Brugerdefineret navn",
|
||||
"name": "Navn",
|
||||
"note": "Bemærk: Alle integrationer virker muligvis ikke med endnu.",
|
||||
"open_device_settings": "Åbn enhedsindstillinger",
|
||||
"unavailable": "Denne entitet er ikke tilgængelig i øjeblikket.",
|
||||
@@ -795,6 +1088,7 @@
|
||||
"scene": "Scener",
|
||||
"script": "Scripts",
|
||||
"server_control": "Serveradministration",
|
||||
"tag": "Tags",
|
||||
"users": "Brugere",
|
||||
"zone": "Zoner"
|
||||
},
|
||||
@@ -853,6 +1147,7 @@
|
||||
"clusters": "Administrer klynger",
|
||||
"reconfigure": "Genkonfigurer enhed",
|
||||
"remove": "Fjern enhed",
|
||||
"view_in_visualization": "Vis i Visualisering",
|
||||
"zigbee_information": "Zigbee-enhedssignatur"
|
||||
},
|
||||
"confirmations": {
|
||||
@@ -892,6 +1187,7 @@
|
||||
"key_missing": "Påkrævede nøgle \"{key}\" mangler.",
|
||||
"key_not_expected": "Nøglen \"{key}\" er ikke forventet eller understøttes ikke af den visuelle editor.",
|
||||
"key_wrong_type": "Den angivne værdi for \"{key}\" understøttes ikke af den visuelle editor. Vi understøtter ( {type_correct} ) men modtog ( {type_wrong} ).",
|
||||
"no_template_editor_support": "Skabeloner understøttes ikke i visuel editor",
|
||||
"no_type_provided": "Der er ikke angivet nogen type."
|
||||
}
|
||||
},
|
||||
@@ -931,7 +1227,7 @@
|
||||
"confirmation_text": "Alle enheder i dette område vil blive utildelte.",
|
||||
"confirmation_title": "Er du sikker på, at du vil slette dette område?"
|
||||
},
|
||||
"description": "Administrer områder i dit hjem",
|
||||
"description": "Tilknyt enheder og entiteter til områder",
|
||||
"editor": {
|
||||
"area_id": "Område-id",
|
||||
"create": "Opret",
|
||||
@@ -999,13 +1295,17 @@
|
||||
"device_id": {
|
||||
"action": "Handling",
|
||||
"extra_fields": {
|
||||
"code": "Kode"
|
||||
"code": "Kode",
|
||||
"message": "Besked",
|
||||
"position": "Position",
|
||||
"title": "Titel"
|
||||
},
|
||||
"label": "Enhed"
|
||||
},
|
||||
"event": {
|
||||
"event": "Hændelse:",
|
||||
"label": "Afsend hændelse"
|
||||
"label": "Afsend hændelse",
|
||||
"service_data": "Service data"
|
||||
},
|
||||
"repeat": {
|
||||
"label": "Gentag",
|
||||
@@ -1134,8 +1434,8 @@
|
||||
"label": "Beskrivelse",
|
||||
"placeholder": "Valgfri beskrivelse"
|
||||
},
|
||||
"edit_ui": "Rediger brugerflade",
|
||||
"edit_yaml": "Rediger med YAML",
|
||||
"edit_ui": "Rediger via brugerfladen",
|
||||
"edit_yaml": "Rediger i YAML",
|
||||
"enable_disable": "Aktiver/deaktiver automatisering",
|
||||
"introduction": "Brug automatiseringer til at vække dit hjem til live.",
|
||||
"load_error_not_editable": "Kun automatiseringer i 'automations.yaml' kan redigeres.",
|
||||
@@ -1171,13 +1471,15 @@
|
||||
"extra_fields": {
|
||||
"above": "Over",
|
||||
"below": "Under",
|
||||
"for": "Varighed"
|
||||
"for": "Varighed",
|
||||
"zone": "Zone"
|
||||
},
|
||||
"label": "Enhed",
|
||||
"trigger": "Udløser"
|
||||
},
|
||||
"event": {
|
||||
"context_user_pick": "Tilføj bruger",
|
||||
"context_user_picked": "Brugerinitieret hændelse",
|
||||
"context_users": "Begræns til begivenheder udløst af",
|
||||
"event_data": "Hændelsesdata",
|
||||
"event_type": "Hændelsestype",
|
||||
@@ -1325,6 +1627,8 @@
|
||||
},
|
||||
"introduction": "Blueprintkonfigurationen giver dig mulighed for at importere og administrere dine blueprints.",
|
||||
"learn_more": "Lær mere om brugen af blueprints",
|
||||
"share_blueprint": "Del Blueprint",
|
||||
"share_blueprint_no_url": "Kan ikke dele Blueprint: no soure url",
|
||||
"use_blueprint": "Opret automation"
|
||||
}
|
||||
},
|
||||
@@ -1382,12 +1686,19 @@
|
||||
"sign_out": "Log ud",
|
||||
"thank_you_note": "Tak for at du er en del af Home Assistant Cloud. Det er på grund af folk som dig, at vi er i stand til at skabe en god hjemmeautomatiseringsoplevelse for alle. Tak skal du have!",
|
||||
"tts": {
|
||||
"default_language": "Standardsprog",
|
||||
"dialog": {
|
||||
"example_message": "Hej {name}, kan du afspille tekst på enhver understøttet medieafspiller!",
|
||||
"header": "Prøv Tekst til tale",
|
||||
"play": "Afspil",
|
||||
"target": "Modtager",
|
||||
"target_browser": "Gennemse"
|
||||
}
|
||||
},
|
||||
"female": "Kvinde",
|
||||
"info": "Personliggør dit hjem ved at få det til at tale med dig ved hjælp af vores Tekst-til-tale-tjenester. Du kan bruge dette i automatiseringer og scripts ved hjælp af tjenesten {service}.",
|
||||
"male": "Mand",
|
||||
"title": "Tekst til tale",
|
||||
"try": "Prøv"
|
||||
},
|
||||
"webhooks": {
|
||||
"disable_hook_error_msg": "Webhook kunne ikke deaktiveres:",
|
||||
@@ -1584,6 +1895,7 @@
|
||||
"cant_edit": "Du kan kun redigere elementer, der er oprettet i brugerfladen.",
|
||||
"caption": "Enheder",
|
||||
"confirm_delete": "Er du sikker på, at du vil slette denne enhed?",
|
||||
"confirm_disable_config_entry": "Der er ikke flere enheder til konfigurationen {entry_name} . Vil du i stedet deaktivere konfigurationen?",
|
||||
"confirm_rename_entity_ids": "Vil du også omdøbe entitet-id'et for dine entiteter?",
|
||||
"confirm_rename_entity_ids_warning": "Dette ændrer ikke nogen konfiguration (automatiseringer, scripts, scener, dashboards mv.), der i øjeblikket bruger disse enheder! Du skal selv opdatere dem for at bruge de nye entitets-id'er!",
|
||||
"data_table": {
|
||||
@@ -1696,7 +2008,8 @@
|
||||
},
|
||||
"filtering": {
|
||||
"clear": "Ryd",
|
||||
"filtering_by": "Filtrering efter"
|
||||
"filtering_by": "Filtrering efter",
|
||||
"show": "Vis"
|
||||
},
|
||||
"header": "Konfigurer Home Assistant",
|
||||
"helpers": {
|
||||
@@ -1767,7 +2080,19 @@
|
||||
"delete_confirm": "Er du sikker på, at du vil fjerne denne integration?",
|
||||
"device_unavailable": "Enheden er utilgængelig",
|
||||
"devices": "{count} {count, plural,\n one {enhed}\n other {enheder}\n}",
|
||||
"disable_restart_confirm": "Genstart Home Assistant for at fuldføre deaktivering af denne integration",
|
||||
"disable": {
|
||||
"disable_confirm": "Er du sikker på, at du vil deaktivere denne integration? Integrationens enheder og entiteter vil blive deaktiveret.",
|
||||
"disabled": "Deaktiveret",
|
||||
"disabled_by": {
|
||||
"device": "enhed",
|
||||
"integration": "integration",
|
||||
"user": "bruger"
|
||||
},
|
||||
"disabled_cause": "Deaktiveret af {cause}"
|
||||
},
|
||||
"documentation": "Dokumentation",
|
||||
"enable_restart_confirm": "Genstart Home Assistant for at fuldføre aktivering af denne integration",
|
||||
"entities": "{count} {count, plural,\n one {entitet}\n other {entiteter}\n}",
|
||||
"entity_unavailable": "Entiteten er utilgængelig",
|
||||
"firmware": "Firmware: {version}",
|
||||
@@ -1787,8 +2112,10 @@
|
||||
"config_flow": {
|
||||
"aborted": "Afbrudt",
|
||||
"close": "Luk",
|
||||
"could_not_load": "Konfigurationsflow kunne ikke indlæses",
|
||||
"created_config": "Oprettede konfiguration for {name}.",
|
||||
"dismiss": "Afvis dialog",
|
||||
"error": "Fejl",
|
||||
"error_saving_area": "Fejl ved lagring af område: {error}",
|
||||
"external_step": {
|
||||
"description": "Dette trin kræver, at du besøger et eksternt websted.",
|
||||
@@ -1797,12 +2124,22 @@
|
||||
"finish": "Afslut",
|
||||
"loading_first_time": "Vent mens integrationen installeres",
|
||||
"not_all_required_fields": "Ikke alle påkrævede felter er udfyldt.",
|
||||
"pick_flow_step": {
|
||||
"new_flow": "Nej, konfigurer en anden forekomst af {integration}",
|
||||
"title": "Vi opdagede disse, vil du oprette dem?"
|
||||
},
|
||||
"submit": "Send"
|
||||
},
|
||||
"configure": "Konfigurer",
|
||||
"configured": "Konfigureret",
|
||||
"confirm_new": "Vil du konfigurere {integration} ?",
|
||||
"description": "Administrer integrationer",
|
||||
"details": "Integrationsdetaljer",
|
||||
"disable": {
|
||||
"disabled_integrations": "{number} er deaktiveret",
|
||||
"hide_disabled": "Skjul deaktiverede integrationer",
|
||||
"show_disabled": "Vis deaktiverede integrationer"
|
||||
},
|
||||
"discovered": "Fundet",
|
||||
"home_assistant_website": "Home Assistants hjemmeside",
|
||||
"ignore": {
|
||||
@@ -1987,11 +2324,32 @@
|
||||
},
|
||||
"node_config": {
|
||||
"header": "Konfiguration af node",
|
||||
"introduction": "Administrer de forskellige konfigurationsparametre for en Z-Wave-node."
|
||||
"help_source": "Beskrivelser af konfigurationsparametre og hjælpetekster leveres af OpenZWave-projektet.",
|
||||
"introduction": "Administrer de forskellige konfigurationsparametre for en Z-Wave-node.",
|
||||
"wakeup_help": "Batteridrevne noder skal være vågne for at ændre deres konfiguration. Hvis noden ikke er vågen, vil OpenZWave forsøge at opdatere nodens konfiguration, næste gang den vågner, hvilket kan være flere timer (eller dage) senere. Følg disse trin for at vække enheden:"
|
||||
},
|
||||
"node_metadata": {
|
||||
"product_manual": "Brugervejledning"
|
||||
},
|
||||
"node_query_stages": {
|
||||
"associations": "Opdaterer tilknytningsgrupper og medlemskaber",
|
||||
"cacheload": "Indlæser oplysninger fra OpenZWave cache-filen. Batteridrevne noder forbliver på dette trin, indtil noden vågner op.",
|
||||
"complete": "Interviewprocessen er fuldført",
|
||||
"configuration": "Henter konfigurationsværdier fra noden",
|
||||
"dynamic": "Henter ofte skiftende værdier fra noden",
|
||||
"instances": "Henter oplysninger om, hvilke forekomster eller kanaler, som en enhed understøtter",
|
||||
"manufacturerspecific1": "Henter producent- og produkt-ID-koder fra noden",
|
||||
"manufacturerspecific2": "Henter yderligere producent- og produkt-ID-koder fra noden",
|
||||
"neighbors": "Henter en liste over nodens naboer",
|
||||
"nodeinfo": "Henter understøttede kommandoklasser fra noden",
|
||||
"nodeplusinfo": "Henter Z-Wave + -oplysninger fra noden",
|
||||
"probe": "Kontrollerer, om noden er vågen / i live",
|
||||
"protocolinfo": "Henter oplysninger fra controlleren om grundlæggende Z-Wave-funktioner for denne node",
|
||||
"session": "Henter værdier fra noden, som sjældent opdateres",
|
||||
"static": "Henter statiske værdier fra enheden",
|
||||
"versions": "Henter oplysninger om firmware- og kommandoklasseversioner",
|
||||
"wakeup": "Konfigurerer understøttelse af vækningskøer og meddelelser"
|
||||
},
|
||||
"node": {
|
||||
"button": "Nodeoplysninger",
|
||||
"not_found": "Noden blev ikke fundet"
|
||||
@@ -2008,6 +2366,7 @@
|
||||
"battery_note": "Hvis noden er batteridrevet, skal du sørge for at vække den, før du fortsætter",
|
||||
"button": "Opdater node",
|
||||
"complete": "Opdatering af noder er fuldført",
|
||||
"description": "Dette vil få OpenZWave til at genindlæse en node og opdatere nodens kommandoklasser, funktioner og værdier.",
|
||||
"node_status": "Nodestatus",
|
||||
"refreshing_description": "Opdaterer nodeoplysninger ...",
|
||||
"start_refresh_button": "Start opdatering",
|
||||
@@ -2018,7 +2377,8 @@
|
||||
},
|
||||
"select_instance": {
|
||||
"header": "Vælg en OpenZWave-instans",
|
||||
"introduction": "Du kører mere end én OpenZWave instans. Hvilken instans vil du administrere?"
|
||||
"introduction": "Du kører mere end én OpenZWave instans. Hvilken instans vil du administrere?",
|
||||
"none_found": "Vi kunne ikke finde en OpenZWave instans. Hvis dette skyldes en fejl, skal du kontrollere din OpenZWave- og MQTT-konfiguration og sikre, at Home Assistant kan kommunikere med din MQTT-mægler."
|
||||
},
|
||||
"services": {
|
||||
"add_node": "Tilføj node",
|
||||
@@ -2226,7 +2586,8 @@
|
||||
"new_tag": "Nyt tag",
|
||||
"tag_id": "Tag-ID",
|
||||
"tag_id_placeholder": "Genereres automatisk, hvis feltet efterlades tomt",
|
||||
"update": "Opdater"
|
||||
"update": "Opdater",
|
||||
"usage": "Et tag kan udløse en automatisering, når det scannes, du kan bruge NFC-tags, QR-koder eller enhver anden form for tag. Brug vores {companion_link} til at skrive dette tag til et programmerbart NFC-tag eller opret en QR-kode nedenfor."
|
||||
},
|
||||
"edit": "Rediger",
|
||||
"headers": {
|
||||
@@ -2367,6 +2728,7 @@
|
||||
"caption": "Visualisering",
|
||||
"header": "Netværksvisualisering",
|
||||
"highlight_label": "Fremhæv enheder",
|
||||
"refresh_topology": "Opdater topologi",
|
||||
"zoom_label": "Zoom til enhed"
|
||||
}
|
||||
},
|
||||
@@ -2399,6 +2761,75 @@
|
||||
"introduction": "Zoner giver dig mulighed for at angive bestemte områder på jorden. Når en person er inden for en zone, vil tilstanden antage navnet fra zonen. Zoner kan også bruges som udløser eller tilstand inde i automatiseringsopsætninger.",
|
||||
"no_zones_created_yet": "Det ser ud til, at du ikke har oprettet nogen zoner endnu."
|
||||
},
|
||||
"zwave_js": {
|
||||
"add_node": {
|
||||
"cancel_inclusion": "Afbryd inklusionstilstand",
|
||||
"controller_in_inclusion_mode": "Din Z-Wave-controller er nu i inklusionstilstand.",
|
||||
"follow_device_instructions": "Følg instruktionerne, der fulgte med din enhed for at starte parring af enheden.",
|
||||
"inclusion_failed": "Noden kunne ikke tilføjes. Se i logfilerne for at få flere oplysninger.",
|
||||
"inclusion_finished": "Noden er blevet tilføjet. Det kan tage et par minutter før alle enheder dukker op, mens konfiguration af noden fuldføres.",
|
||||
"introduction": "Denne guide hjælper dig med at føje en node til dit Z-Wave-netværk.",
|
||||
"secure_inclusion_warning": "Sikre enheder kræver ekstra båndbredde. For mange sikre enheder kan gøre dit Z-Wave-netværk langsomt. Det anbefaler kun at bruge sikker inklusion til de enheder, hvor det er nødvendigt. For eksempel til låse eller garageportåbnere.",
|
||||
"start_inclusion": "Start inklusionstilstand",
|
||||
"start_secure_inclusion": "Start sikker inklusion",
|
||||
"title": "Tilføj en Z-Wave-node",
|
||||
"use_secure_inclusion": "Brug sikker inklusion",
|
||||
"view_device": "Vis enhed"
|
||||
},
|
||||
"button": "Konfigurer",
|
||||
"common": {
|
||||
"add_node": "Tilføj node",
|
||||
"close": "Luk",
|
||||
"home_id": "Hjem-id",
|
||||
"network": "Netværk",
|
||||
"node_id": "Node-id",
|
||||
"remove_node": "Fjern node"
|
||||
},
|
||||
"dashboard": {
|
||||
"driver_version": "Driverversion",
|
||||
"dump_dead_nodes_text": "Nogle af dine noder svarede ikke og antages døde. De vil ikke blive eksporteret.",
|
||||
"dump_dead_nodes_title": "Nogle af dine noder er døde",
|
||||
"dump_debug": "Download et udtræk af dit netværk for at hjælpe med at diagnosticere problemer",
|
||||
"dump_not_ready_confirm": "Hent",
|
||||
"dump_not_ready_text": "Hvis du opretter en eksport, når ikke alle noder er klar, kan du mangle nødvendige data i udtrækket. Vent på, at dit netværk søger på alle noder. Vil du fortsætte med eksporten?",
|
||||
"dump_not_ready_title": "Ikke alle noder er klar endnu",
|
||||
"header": "Administrer dit Z-Wave-netværk",
|
||||
"home_id": "Hjem-id",
|
||||
"introduction": "Administrer dit Z-Wave-netværk og Z-Wave-noder",
|
||||
"nodes_ready": "Noder er klar",
|
||||
"server_version": "Serverversion"
|
||||
},
|
||||
"device_info": {
|
||||
"node_ready": "Node klar",
|
||||
"node_status": "Nodestatus",
|
||||
"zwave_info": "Z-Wave-info"
|
||||
},
|
||||
"navigation": {
|
||||
"network": "Netværk"
|
||||
},
|
||||
"network_status": {
|
||||
"connected": "Forbundet",
|
||||
"connecting": "Forbinder",
|
||||
"unknown": "Ukendt"
|
||||
},
|
||||
"node_status": {
|
||||
"alive": "I live",
|
||||
"asleep": "Dvale",
|
||||
"awake": "Vågen",
|
||||
"dead": "Død",
|
||||
"unknown": "Ukendt"
|
||||
},
|
||||
"remove_node": {
|
||||
"cancel_exclusion": "Annuller udelukkelse",
|
||||
"controller_in_exclusion_mode": "Din Z-Wave-controller er nu i eksklusionstilstand.",
|
||||
"exclusion_failed": "Noden kunne ikke fjernes. Se i logfilerne for at få flere oplysninger.",
|
||||
"exclusion_finished": "Node {id} er fjernet fra dit Z-Wave-netværk.",
|
||||
"follow_device_instructions": "Følg de anvisninger, der fulgte med enheden, for at foretage eksklusion på enheden.",
|
||||
"introduction": "Fjern en node fra dit Z-Wave-netværk, og fjern den tilknyttede enhed og entiteter fra Home Assistant.",
|
||||
"start_exclusion": "Start eksklusion",
|
||||
"title": "Fjern en Z-Wave-node"
|
||||
}
|
||||
},
|
||||
"zwave": {
|
||||
"button": "Konfigurer",
|
||||
"common": {
|
||||
@@ -2410,6 +2841,12 @@
|
||||
},
|
||||
"description": "Administrer dit Z-Wave-netværk",
|
||||
"learn_more": "Lær mere om Z-Wave",
|
||||
"migration": {
|
||||
"ozw": {
|
||||
"header": "Migrer til OpenZWave",
|
||||
"introduction": "Denne guide hjælper dig med at migrere fra den tidligere Z-Wave-integration til OpenZWave-integrationen, der i øjeblikket er i betaversion."
|
||||
}
|
||||
},
|
||||
"network_management": {
|
||||
"header": "Administration af Z-Wave-netværk",
|
||||
"introduction": "Kør kommandoer, der påvirker Z-Wave-netværket. Du får ikke feedback på, om de fleste kommandoer lykkedes, men du kan kontrollere OZW-loggen for at forsøge at finde ud af det."
|
||||
@@ -2513,17 +2950,23 @@
|
||||
"type": "Hændelsestype"
|
||||
},
|
||||
"services": {
|
||||
"accepts_target": "Et mål for denne tjeneste kan angives, for eksempel: `entity_id: light.bed_light`",
|
||||
"all_parameters": "Alle tilgængelige parametre",
|
||||
"call_service": "Kald tjeneste",
|
||||
"column_description": "Beskrivelse",
|
||||
"column_example": "Eksempel",
|
||||
"column_parameter": "Parameter",
|
||||
"description": "Tjenesteværktøjet til udviklere giver dig mulighed for at kalde alle tilgængelige tjenester i Home Assistant.",
|
||||
"fill_example_data": "Udfyld eksempeldata",
|
||||
"title": "Tjenester"
|
||||
"title": "Tjenester",
|
||||
"ui_mode": "Gå til brugergrænsefladetilstand",
|
||||
"yaml_mode": "Gå til YAML-tilstand",
|
||||
"yaml_parameters": "Parametre er kun tilgængelige i YAML-tilstand"
|
||||
},
|
||||
"states": {
|
||||
"alert_entity_field": "Entitet er et obligatorisk felt",
|
||||
"attributes": "Egenskaber",
|
||||
"copy_id": "Kopier id til Udklipsholder",
|
||||
"current_entities": "Aktuelle entiteter",
|
||||
"description1": "Sæt repræsentationen af en enhed i Home Assistant.",
|
||||
"description2": "Dette vil ikke kommunikere med den faktiske enhed.",
|
||||
@@ -2581,6 +3024,14 @@
|
||||
"yaml_unsupported": "Du kan ikke bruge denne funktion, når du bruger Lovelace-brugerfladen i YAML-tilstand."
|
||||
},
|
||||
"cards": {
|
||||
"actions": {
|
||||
"action_confirmation": "Er du sikker på, at du vil afvikle handlingen \" {action} \"?",
|
||||
"no_entity_more_info": "Der er ikke angivet en entitet til visning af dialogboksen med flere oplysninger",
|
||||
"no_entity_toggle": "Der er ikke angivet en entitet, som skal slås til/fra",
|
||||
"no_navigation_path": "Der er ikke angivet nogen navigationssti",
|
||||
"no_service": "Der er ikke angivet en tjeneste, som skal afvikles",
|
||||
"no_url": "Der er ikke angivet en URL-adresse, der skal åbnes"
|
||||
},
|
||||
"confirm_delete": "Er du sikker på, at du vil slette dette kort?",
|
||||
"empty_state": {
|
||||
"go_to_integrations_page": "Gå til integrationssiden.",
|
||||
@@ -2644,7 +3095,7 @@
|
||||
"name": "Alarmpanel"
|
||||
},
|
||||
"button": {
|
||||
"default_action_help": "Standardhandlingen afhænger af entitetens muligheder, den skifte enten tilstand, eller flere oplysninger vises.",
|
||||
"default_action_help": "Standardhandlingen afhænger af entitetens muligheder. Den skifter enten tilstand eller flere oplysninger vises.",
|
||||
"description": "Med knapkortet kan du tilføje knapper til at udføre opgaver.",
|
||||
"name": "Knap"
|
||||
},
|
||||
@@ -2955,6 +3406,8 @@
|
||||
"error_remove": "Ude af stand til at fjerne konfiguration: {error}",
|
||||
"error_save_yaml": "Kunne ikke gemme YAML: {error}",
|
||||
"header": "Rediger konfiguration",
|
||||
"lovelace_changed": "Lovelace-konfigurationen blev opdateret. Vil du indlæse den opdaterede konfiguration i editoren og miste dine aktuelle ændringer?",
|
||||
"reload": "Genindlæs",
|
||||
"resources_moved": "Ressourcer bør ikke længere føjes til Lovelace-konfigurationen, men kan tilføjes i Lovelace-konfigurationspanelet.",
|
||||
"save": "Gem",
|
||||
"saved": "Gemt",
|
||||
@@ -3040,6 +3493,14 @@
|
||||
"empty": "Du har ingen beskeder",
|
||||
"playback_title": "Afspilning af besked"
|
||||
},
|
||||
"my": {
|
||||
"component_not_loaded": "Denne omdirigering understøttes ikke af din Home Assistant installation. Du skal bruge integrationen {integration} for at kunne bruge denne omdirigering.",
|
||||
"documentation": "dokumentation",
|
||||
"error": "Der opstod en ukendt fejl",
|
||||
"faq_link": "Ofte stillede spørgsmål om Home Assistant",
|
||||
"no_supervisor": "Denne omdirigering understøttes ikke af din Home Assistant-installation. Dette understøttes af enten Home Assistant Operating System eller Home Assistant Supervised installationsmetoden. Se {docs_link} for flere oplysninger.",
|
||||
"not_supported": "Denne omdirigering understøttes ikke af din Home Assistant installation. Kontroller {link} for de understøttede omdirigeringer og den version, de blev introduceret i."
|
||||
},
|
||||
"page-authorize": {
|
||||
"abort_intro": "Login afbrudt",
|
||||
"authorizing_client": "Du er ved at give {clientId} adgang til din Home Assistant-instans.",
|
||||
|
||||
@@ -315,7 +315,7 @@
|
||||
"addon_running": "Add-on wird ausgeführt",
|
||||
"addon_stopped": "Add-on ist gestoppt",
|
||||
"addons": "Add-ons",
|
||||
"no_addons": "Du hast noch keine Add-ons installiert. Gehe zum Add-on-Shop, um loszulegen!"
|
||||
"no_addons": "Du hast noch keine Add-ons installiert. Gehe zum Add-on Store, um loszulegen!"
|
||||
},
|
||||
"dialog": {
|
||||
"network": {
|
||||
@@ -373,17 +373,17 @@
|
||||
"panel": {
|
||||
"dashboard": "Dashboard",
|
||||
"snapshots": "Datensicherungen",
|
||||
"store": "Add-on Shop",
|
||||
"store": "Add-on Store",
|
||||
"system": "System"
|
||||
},
|
||||
"snapshot": {
|
||||
"addons": "Add-ons",
|
||||
"available_snapshots": "Verfügbare Sicherungen",
|
||||
"available_snapshots": "Verfügbare Datensicherungen",
|
||||
"could_not_create": "Datensicherung konnte nicht erstellt werden",
|
||||
"create": "Erstellen",
|
||||
"create_blocked_not_running": "Das Erstellen eines Snapshots ist derzeit nicht möglich, da sich das System im Zustand {state} befindet.",
|
||||
"create_snapshot": "Datensicherung erstellen",
|
||||
"description": "Sicherungen ermöglichen dir das leichte Speichern und Wiederherstellen von allen Daten aus Home Assistant.",
|
||||
"description": "Datensicherungen ermöglichen dir das leichte Speichern und Wiederherstellen von allen Daten aus Home Assistant.",
|
||||
"enter_password": "Bitte Passwort eingeben.",
|
||||
"folder": {
|
||||
"addons/local": "Lokale Add-ons",
|
||||
@@ -395,7 +395,7 @@
|
||||
"folders": "Ordner",
|
||||
"full_snapshot": "Vollständige Datensicherung",
|
||||
"name": "Name",
|
||||
"no_snapshots": "Du hast bisher keine Sicherungen erstellt.",
|
||||
"no_snapshots": "Du hast bisher keine Datensicherungen erstellt.",
|
||||
"partial_snapshot": "Selektive Datensicherung",
|
||||
"password": "Passwort",
|
||||
"password_protected": "Passwort geschützt",
|
||||
@@ -413,20 +413,20 @@
|
||||
"system": {
|
||||
"core": {
|
||||
"cpu_usage": "Core-CPU Auslastung",
|
||||
"ram_usage": "Core-RAM Nutzung"
|
||||
"ram_usage": "Core Arbeitsspeicherbedarf"
|
||||
},
|
||||
"host": {
|
||||
"change": "Ändern",
|
||||
"change_hostname": "Hostname ändern",
|
||||
"confirm_reboot": "Bist du sicher, dass du den Host neu starten willst?",
|
||||
"confirm_shutdown": "Bist du sicher, dass du den Host herunterfahren willst?",
|
||||
"deployment": "Deployment",
|
||||
"deployment": "Einsatz",
|
||||
"docker_version": "Docker-Version",
|
||||
"emmc_lifetime_used": "eMMC Verschleiß",
|
||||
"emmc_lifetime_used": "eMMC verschlissen",
|
||||
"failed_to_get_hardware_list": "Fehler beim Abrufen der Hardwareliste",
|
||||
"failed_to_import_from_usb": "Fehler beim Importieren von USB",
|
||||
"failed_to_reboot": "Fehler beim Neustart des Hosts",
|
||||
"failed_to_set_hostname": "Das Setzen des Hostnamens ist fehlgeschlagen",
|
||||
"failed_to_set_hostname": "Das Setzen des Hostnamen ist fehlgeschlagen",
|
||||
"failed_to_shutdown": "Fehler beim Herunterfahren des Hosts",
|
||||
"hardware": "Hardware",
|
||||
"hostname": "Hostname",
|
||||
@@ -434,7 +434,7 @@
|
||||
"ip_address": "IP-Adresse",
|
||||
"new_hostname": "Bitte einen neuen Hostnamen eingeben:",
|
||||
"operating_system": "Betriebssystem",
|
||||
"reboot_host": "Host neustarten",
|
||||
"reboot_host": "Host Neustarten",
|
||||
"shutdown_host": "Host herunterfahren",
|
||||
"used_space": "Belegter Speicherplatz"
|
||||
},
|
||||
@@ -457,7 +457,7 @@
|
||||
"leave_beta_action": "Beta-Kanal verlassen",
|
||||
"leave_beta_description": "Erhalte stabile Updates für Home Assistant, Supervisor und Host",
|
||||
"ram_usage": "Arbeitsspeicherbedarf von Supervisor",
|
||||
"reload_supervisor": "Supervisor neu starten",
|
||||
"reload_supervisor": "Supervisor neu laden",
|
||||
"share_diagnostics": "Diagnose teilen",
|
||||
"share_diagnostics_description": "Teile Absturzberichte und Diagnoseinformationen.",
|
||||
"share_diagonstics_description": "Möchtest du Absturzberichte und Diagnoseinformationen automatisch freigeben, wenn der Supervisor auf unerwartete Fehler stößt? {line_break} Auf diese Weise können wir die Probleme beheben. Die Informationen sind nur für das Home Assistant Core Team zugänglich und werden nicht an andere weitergegeben. {line_break} Die Daten enthalten keine privaten/sensiblen Informationen und du kannst diese jederzeit in den Einstellungen deaktivieren.",
|
||||
@@ -478,7 +478,7 @@
|
||||
"docker_version": "Docker Version",
|
||||
"job_conditions": "Ignorierte Jobbedingungen",
|
||||
"lxc": "LXC",
|
||||
"network_manager": "Netzwerk Einstellungen",
|
||||
"network_manager": "Netzwerk-Manager",
|
||||
"os": "Betriebssystem",
|
||||
"privileged": "Der Supervisor ist nicht berechtigt",
|
||||
"systemd": "Systemd"
|
||||
@@ -785,7 +785,8 @@
|
||||
"was_unlocked": "wurde entsperrt",
|
||||
"was_unplugged": "wurde ausgesteckt",
|
||||
"was_unsafe": "war unsicher"
|
||||
}
|
||||
},
|
||||
"show_trace": "Trace anzeigen"
|
||||
},
|
||||
"media-browser": {
|
||||
"audio_not_supported": "Ihr Browser unterstützt das Audioelement nicht.",
|
||||
@@ -1120,7 +1121,7 @@
|
||||
"smtp": "SMTP-Benachrichtigungsdienst neu laden",
|
||||
"statistics": "Statistikentitäten neu laden",
|
||||
"telegram": "Telegram-Benachrichtigungsdienst neu laden",
|
||||
"template": "Templates neu laden",
|
||||
"template": "Template-Entitäten neu laden",
|
||||
"trend": "Trend-Entitäten neu laden",
|
||||
"universal": "Universelle Medien-Player-Entitäten neu laden",
|
||||
"zone": "Zonen neu laden"
|
||||
@@ -1145,6 +1146,7 @@
|
||||
"buttons": {
|
||||
"add": "Geräte über dieses Gerät hinzufügen",
|
||||
"clusters": "Cluster verwalten",
|
||||
"device_children": "Endgeräte anzeigen",
|
||||
"reconfigure": "Gerät neu konfigurieren",
|
||||
"remove": "Gerät entfernen",
|
||||
"view_in_visualization": "Visualisierung in einer Map",
|
||||
@@ -1153,6 +1155,7 @@
|
||||
"confirmations": {
|
||||
"remove": "Möchtest du das Gerät wirklich entfernen?"
|
||||
},
|
||||
"device_children": "Zigbee-Endgeräte",
|
||||
"device_signature": "ZigBee-Gerätesignatur",
|
||||
"last_seen": "Zuletzt gesehen",
|
||||
"manuf": "von {manufacturer}",
|
||||
@@ -1187,6 +1190,7 @@
|
||||
"key_missing": "Erforderlicher Schlüssel \"{key}\" fehlt.",
|
||||
"key_not_expected": "Der Schlüssel \"{key}\" wird vom visuellen Editor nicht erwartet oder nicht unterstützt.",
|
||||
"key_wrong_type": "Der angegebene Wert für \"{key}\" wird vom visuellen Editor nicht unterstützt. Wir unterstützen ({type_correct}), haben aber ({type_wrong}) erhalten.",
|
||||
"no_template_editor_support": "Templates werden im visuellen Editor nicht unterstützt",
|
||||
"no_type_provided": "Kein Typ angegeben."
|
||||
}
|
||||
},
|
||||
@@ -1294,10 +1298,14 @@
|
||||
"device_id": {
|
||||
"action": "Aktion",
|
||||
"extra_fields": {
|
||||
"brightness_pct": "Helligkeit",
|
||||
"code": "Code",
|
||||
"humidity": "Luftfeuchtigkeit",
|
||||
"message": "Nachricht",
|
||||
"mode": "Modus",
|
||||
"position": "Position",
|
||||
"title": "Titel"
|
||||
"title": "Titel",
|
||||
"value": "Wert"
|
||||
},
|
||||
"label": "Gerät"
|
||||
},
|
||||
@@ -1370,7 +1378,9 @@
|
||||
"extra_fields": {
|
||||
"above": "Über",
|
||||
"below": "Unter",
|
||||
"for": "Dauer"
|
||||
"for": "Dauer",
|
||||
"hvac_mode": "HLK-Modus",
|
||||
"preset_mode": "Voreinstellung"
|
||||
},
|
||||
"label": "Gerät"
|
||||
},
|
||||
@@ -1425,7 +1435,7 @@
|
||||
"zone": "Zone"
|
||||
}
|
||||
},
|
||||
"unsupported_condition": "Nicht unterstützte Bedingung: {condition}"
|
||||
"unsupported_condition": "Keine Unterstützung für visuellen Editor für Bedingung: {condition} verfügbar"
|
||||
},
|
||||
"copy_to_clipboard": "In die Zwischenablage kopieren",
|
||||
"default_name": "Neue Automatisierung",
|
||||
@@ -1563,6 +1573,8 @@
|
||||
"add_automation": "Automatisierung hinzufügen",
|
||||
"delete_automation": "Automatisierung löschen",
|
||||
"delete_confirm": "Bist du sicher, dass du diese Automatisierung löschen möchtest?",
|
||||
"dev_automation": "Automatisierung debuggen",
|
||||
"dev_only_editable": "Nur Automatisierungen in automations.yaml können debuggt werden.",
|
||||
"duplicate": "Duplizieren",
|
||||
"duplicate_automation": "Automatisierung duplizieren",
|
||||
"edit_automation": "Automatisierung bearbeiten",
|
||||
@@ -1602,7 +1614,7 @@
|
||||
"header": "Vorlage importieren",
|
||||
"import_btn": "Vorschau Vorlage",
|
||||
"import_header": "Vorlage \"{name}\"",
|
||||
"import_introduction_link": "Du kannst Vorlagen anderer Benutzer aus GitHub und den {community_link} importieren. Gib unten die URL der Vorlage ein.",
|
||||
"import_introduction_link": "Du kannst Blaupausen anderer Benutzer aus GitHub und den {community_link} importieren. Gib unten die URL der Blaupause ein.",
|
||||
"importing": "Vorlage wird geladen...",
|
||||
"raw_blueprint": "Inhalt der Vorlage",
|
||||
"save_btn": "Vorlage importieren",
|
||||
@@ -1626,6 +1638,8 @@
|
||||
},
|
||||
"introduction": "Mit der Vorlagenkonfiguration kannst du deine Vorlagen importieren und verwalten.",
|
||||
"learn_more": "Erfahre mehr über die Benutzung von Vorlagen",
|
||||
"share_blueprint": "Vorlage teilen",
|
||||
"share_blueprint_no_url": "Vorlage kann nicht geteilt werden: Keine Quell-URL",
|
||||
"use_blueprint": "Automatisierung erstellen"
|
||||
}
|
||||
},
|
||||
@@ -2110,7 +2124,7 @@
|
||||
"aborted": "Abgebrochen",
|
||||
"close": "Schließen",
|
||||
"could_not_load": "Der Konfigurationsfluss konnte nicht geladen werden",
|
||||
"created_config": "Erstellte Konfiguration für {name}.",
|
||||
"created_config": "Konfiguration für {name} erstellt.",
|
||||
"dismiss": "Dialog schließen",
|
||||
"error": "Fehler",
|
||||
"error_saving_area": "Fehler beim Speichern des Bereichs: {error}",
|
||||
@@ -2169,7 +2183,7 @@
|
||||
"caption": "Logs",
|
||||
"clear": "Leeren",
|
||||
"description": "Home Assistant Logs einsehen",
|
||||
"details": "Protokolldetails ( {level} )",
|
||||
"details": "Protokolldetails ({level})",
|
||||
"load_full_log": "Vollständiges Home Assistant-Protokoll laden",
|
||||
"loading_log": "Fehlerprotokoll wird geladen...",
|
||||
"multiple_messages": "Die Nachricht ist zum ersten Mal um {time} aufgetreten und erscheint {counter} mal",
|
||||
@@ -2543,7 +2557,7 @@
|
||||
"smtp": "SMTP-Benachrichtigungsdienste neu laden",
|
||||
"statistics": "Statistik-Entitäten neu laden",
|
||||
"telegram": "Telegram-Benachrichtigungsdienste neu laden",
|
||||
"template": "Vorlagenentitäten neu laden",
|
||||
"template": "Template-Entitäten neu laden",
|
||||
"trend": "Trend-Entitäten neu laden",
|
||||
"universal": "Universelle Media Player-Entitäten neu laden",
|
||||
"zone": "Zonen neu laden"
|
||||
@@ -2722,6 +2736,7 @@
|
||||
"caption": "Netzwerk"
|
||||
},
|
||||
"visualization": {
|
||||
"auto_zoom": "Automatischer Zoom",
|
||||
"caption": "Visualisierung",
|
||||
"header": "Netzwerkvisualisierung",
|
||||
"highlight_label": "Geräte hervorheben",
|
||||
@@ -2797,6 +2812,7 @@
|
||||
"server_version": "Serverversion"
|
||||
},
|
||||
"device_info": {
|
||||
"device_config": "Gerät konfigurieren",
|
||||
"node_ready": "Node Bereit",
|
||||
"node_status": "Node Status",
|
||||
"zwave_info": "Z-Wave Info"
|
||||
@@ -2809,6 +2825,15 @@
|
||||
"connecting": "Verbinden",
|
||||
"unknown": "Unbekannt"
|
||||
},
|
||||
"node_config": {
|
||||
"attribution": "Gerätekonfigurationsparameter und -beschreibungen werden von der {device_database} bereitgestellt",
|
||||
"battery_device_notice": "Batteriebetriebene Geräte müssen wach sein, um ihre Konfiguration zu aktualisieren. Anweisungen zum Aufwecken des Geräts findest du im Handbuch deines Geräts.",
|
||||
"error_device_not_found": "Gerät nicht gefunden",
|
||||
"header": "Z-Wave Gerätekonfiguration",
|
||||
"introduction": "Verwalten und Anpassen von gerätespezifischen Konfigurationsparametern (Knoten) für das ausgewählte Gerät",
|
||||
"parameter_is_read_only": "Dieser Parameter ist schreibgeschützt.",
|
||||
"zwave_js_device_database": "Z-Wave JS Gerätedatenbank"
|
||||
},
|
||||
"node_status": {
|
||||
"alive": "Lebendig",
|
||||
"asleep": "Schläft",
|
||||
@@ -2981,23 +3006,34 @@
|
||||
"title": "Zustände"
|
||||
},
|
||||
"templates": {
|
||||
"all_listeners": "Diese Vorlage überwacht alle Zustandsänderungsereignisse.",
|
||||
"all_listeners": "Dieses Template überwacht alle Zustandsänderungsereignisse.",
|
||||
"description": "Vorlagen werden durch die Jinja2-Template-Engine mit einigen für Home Assistant spezifischen Erweiterungen gerendert.",
|
||||
"domain": "Domain",
|
||||
"editor": "Vorlageneditor",
|
||||
"editor": "Template-Editor",
|
||||
"entity": "Entität",
|
||||
"jinja_documentation": "Jinja2 Template Dokumentation",
|
||||
"listeners": "Diese Vorlage überwacht die folgenden Statusänderungsereignisse:",
|
||||
"no_listeners": "Diese Vorlage überwacht keine Ereignisse und wird nicht automatisch aktualisiert.",
|
||||
"reset": "Zurücksetzen auf Demo-Vorlage",
|
||||
"listeners": "Dieses Template überwacht die folgenden Statusänderungsereignisse:",
|
||||
"no_listeners": "Dieses Template überwacht keine Ereignisse und wird nicht automatisch aktualisiert.",
|
||||
"reset": "Zurücksetzen auf Demo-Template",
|
||||
"result_type": "Ergebnistyp",
|
||||
"template_extensions": "Home Assistant-Vorlagenerweiterungen",
|
||||
"time": "Diese Vorlage wird zu Beginn jeder Minute aktualisiert.",
|
||||
"title": "Vorlage",
|
||||
"unknown_error_template": "Unbekannter Fehler beim Rendern der Vorlage"
|
||||
"template_extensions": "Home Assistant-Template Erweiterungen",
|
||||
"time": "Dieses Template wird zu Beginn jeder Minute aktualisiert.",
|
||||
"title": "Template",
|
||||
"unknown_error_template": "Unbekannter Fehler beim Rendern des Templates"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"go_back": "Zurück",
|
||||
"supervisor": {
|
||||
"ask": "Um Hilfe bitten",
|
||||
"observer": "Überprüfe den Observer",
|
||||
"reboot": "Versuche den Host neuzustarten",
|
||||
"system_health": "Überprüfe Systemzustand",
|
||||
"title": "Supervisor-Bedienfeld konnte nicht geladen werden!",
|
||||
"wait": "Wenn du gerade erst hochgefahren hast, dann stelle sicher dass du den Supervisor genug Zeit zum Starten gegeben hast."
|
||||
}
|
||||
},
|
||||
"history": {
|
||||
"ranges": {
|
||||
"last_week": "Letzte Woche",
|
||||
|
||||
@@ -165,11 +165,11 @@
|
||||
},
|
||||
"host_network": {
|
||||
"description": "Τα πρόσθετα συνήθως εκτελούνται στο δικό τους απομονωμένο επίπεδο δικτύου, το οποίο τους εμποδίζει να έχουν πρόσβαση στο δίκτυο του κεντρικού λειτουργικού συστήματος. Σε ορισμένες περιπτώσεις, αυτή η απομόνωση δικτύου μπορεί να περιορίσει τα πρόσθετα στην παροχή των υπηρεσιών τους και ως εκ τούτου, η απομόνωση μπορεί να αρθεί από τον πρόσθετο συντάκτη, παρέχοντας στο πρόσθετο πλήρη πρόσβαση στις δυνατότητες δικτύου του κεντρικού υπολογιστή. Αυτό δίνει στο πρόσθετο περισσότερες δυνατότητες δικτύωσης αλλά μειώνει την ασφάλεια, επομένως, η βαθμολογία ασφαλείας του πρόσθετου θα μειωθεί όταν αυτή η επιλογή χρησιμοποιείται από το πρόσθετο.",
|
||||
"title": "Δίκτυο κεντρικού υπολογιστή"
|
||||
"title": "Δίκτυο διακομιστή"
|
||||
},
|
||||
"host_pid": {
|
||||
"description": "Συνήθως, οι διαδικασίες που εκτελούνται το πρόσθετο, είναι απομονωμένες από όλες τις άλλες διαδικασίες συστήματος. Ο συντάκτης του πρόσθετου ζήτησε από το πρόσθετο να έχει πρόσβαση στις διεργασίες συστήματος που εκτελούνται στην παρουσία του συστήματος κεντρικού υπολογιστή, και επιτρέπει στο πρόσθετο να δημιουργεί διαδικασίες στο σύστημα κεντρικού υπολογιστή. Αυτή η λειτουργία παρέχει στο πρόσθετο πλήρη πρόσβαση και έλεγχο σε ολόκληρο το σύστημα οικιακού βοηθού σας, το οποίο προσθέτει κινδύνους ασφαλείας και ενδέχεται να προκαλέσει βλάβη στο σύστημά σας όταν γίνεται κατάχρηση. Επομένως, αυτή η δυνατότητα επηρεάζει αρνητικά τη βαθμολογία ασφαλείας του πρόσθετου. \n\n Αυτό το επίπεδο πρόσβασης δεν χορηγείται αυτόματα και πρέπει να επιβεβαιωθεί από εσάς. Για να το κάνετε αυτό, πρέπει να απενεργοποιήσετε τη λειτουργία προστασίας στο πρόσθετο με μη αυτόματο τρόπο. Απενεργοποιήστε τη λειτουργία προστασίας μόνο εάν γνωρίζετε, χρειάζεστε και εμπιστεύεστε την πηγή αυτού του πρόσθετου.",
|
||||
"title": "Χώρος ονομάτων διεργασιών κεντρικού υπολογιστή"
|
||||
"title": "Χώρος ονομάτων διεργασιών διακομιστή"
|
||||
},
|
||||
"ingress": {
|
||||
"description": "Αυτό το πρόσθετο χρησιμοποιεί το Ingress για να ενσωματώσει τη διασύνδεσή του με ασφάλεια στο Home Assistant.",
|
||||
@@ -183,8 +183,8 @@
|
||||
"hass": "hass",
|
||||
"hassio": "hassio",
|
||||
"host": "κεντρικός υπολογιστής",
|
||||
"host_pid": "pid κεντρικού υπολογιστή",
|
||||
"ingress": "είσοδος",
|
||||
"host_pid": "pid διακομιστή",
|
||||
"ingress": "ingress",
|
||||
"rating": "εκτίμηση",
|
||||
"stage": "στάδιο"
|
||||
},
|
||||
@@ -195,7 +195,7 @@
|
||||
"role": {
|
||||
"admin": "admin",
|
||||
"backup": "backup",
|
||||
"default": "default",
|
||||
"default": "Προεπιλογή",
|
||||
"homeassistant": "homeassistant",
|
||||
"manager": "manager"
|
||||
},
|
||||
@@ -206,7 +206,7 @@
|
||||
},
|
||||
"changelog": "Changelog",
|
||||
"cpu_usage": "Χρήση CPU πρόσθετου",
|
||||
"hostname": "Όνομα κεντρικού υπολογιστή",
|
||||
"hostname": "Όνομα διακομιστή",
|
||||
"install": "εγκατάσταση",
|
||||
"new_update_available": "{name} {version} είναι διαθέσιμο",
|
||||
"not_available_arch": "Αυτό το πρόσθετο δεν είναι συμβατό με τον επεξεργαστή της συσκευής σας ή το λειτουργικό σύστημα που έχετε εγκαταστήσει στη συσκευή σας.",
|
||||
@@ -269,6 +269,7 @@
|
||||
},
|
||||
"common": {
|
||||
"cancel": "Ακύρωση",
|
||||
"close": "Κλείσιμο",
|
||||
"description": "Περιγραφή",
|
||||
"error": {
|
||||
"unknown": "Άγνωστο σφάλμα",
|
||||
@@ -301,7 +302,8 @@
|
||||
"title": "Επαναφορά επιλογών"
|
||||
},
|
||||
"restart": {
|
||||
"text": "Είστε βέβαιοι ότι θέλετε να επανεκκινήσετε το {name};"
|
||||
"text": "Είστε βέβαιοι ότι θέλετε να επανεκκινήσετε το {name};",
|
||||
"title": "Επανεκκίνηση {name}"
|
||||
},
|
||||
"update": {
|
||||
"text": "Είστε βέβαιοι ότι θέλετε να ενημερώσετε το {name} στην έκδοση {version} ;",
|
||||
@@ -331,7 +333,7 @@
|
||||
"unsaved": "Έχετε μη αποθηκευμένες αλλαγές, αυτές θα χαθούν αν αλλάξετε καρτέλες, θέλετε να συνεχίσετε;",
|
||||
"warning": "Εάν αλλάζετε τις διευθύνσεις Wi-Fi, IP ή πύλης, ενδέχεται να χάσετε τη σύνδεση!",
|
||||
"wep": "WEP",
|
||||
"wpa": "wpa-psk"
|
||||
"wpa": "WPA-psk"
|
||||
},
|
||||
"registries": {
|
||||
"add_new_registry": "Προσθήκη νέου μητρώου",
|
||||
@@ -364,7 +366,9 @@
|
||||
},
|
||||
"my": {
|
||||
"error": "Προέκυψε ένα άγνωστο σφάλμα",
|
||||
"faq_link": "Συχνές ερωτήσεις Home Assistant"
|
||||
"error_addon_not_found": "Το πρόσθετο δεν βρέθηκε",
|
||||
"faq_link": "Συχνές ερωτήσεις Home Assistant",
|
||||
"not_supported": "Αυτή η ανακατεύθυνση δεν υποστηρίζεται από την παρουσία του Home Assistant σας. Ελέγξτε το {link} για τις υποστηριζόμενες ανακατευθύνσεις και την έκδοση που εισήχθησαν."
|
||||
},
|
||||
"panel": {
|
||||
"dashboard": "Πίνακας Επισκόπησης",
|
||||
@@ -402,7 +406,7 @@
|
||||
},
|
||||
"store": {
|
||||
"missing_addons": "Λείπουν πρόσθετα; Ενεργοποίηση λειτουργίας για προχωρημένους στη σελίδα προφίλ χρήστη",
|
||||
"no_results_found": "Δεν βρέθηκαν αποτελέσματα στο {αποθετήριο}.",
|
||||
"no_results_found": "Δεν βρέθηκαν αποτελέσματα στο {repository}.",
|
||||
"registries": "Μητρώα",
|
||||
"repositories": "Αποθετήρια"
|
||||
},
|
||||
@@ -413,25 +417,25 @@
|
||||
},
|
||||
"host": {
|
||||
"change": "Αλλαγή",
|
||||
"change_hostname": "Αλλαγή ονόματος κεντρικού υπολογιστή",
|
||||
"change_hostname": "Αλλαγή ονόματος διακομιστή",
|
||||
"confirm_reboot": "Είστε βέβαιοι ότι θέλετε να επανεκκινήσετε τον κεντρικό υπολογιστή;",
|
||||
"confirm_shutdown": "Είστε βέβαιοι ότι θέλετε να τερματίσετε τη λειτουργία του κεντρικού υπολογιστή;",
|
||||
"confirm_shutdown": "Είστε βέβαιοι ότι θέλετε να τερματίσετε τη λειτουργία του διακομιστή;",
|
||||
"deployment": "Ανάπτυξη",
|
||||
"docker_version": "Έκδοση Docker",
|
||||
"emmc_lifetime_used": "eMMC διάρκεια ζωής που χρησιμοποιήθηκε",
|
||||
"emmc_lifetime_used": "Χρήση eMMC στη διάρκεια ζωής της",
|
||||
"failed_to_get_hardware_list": "Αποτυχία λήψης λίστας υλικού",
|
||||
"failed_to_import_from_usb": "Αποτυχία εισαγωγής από USB",
|
||||
"failed_to_reboot": "Αποτυχία επανεκκίνησης του κεντρικού υπολογιστή",
|
||||
"failed_to_set_hostname": "Η ρύθμιση ονόματος κεντρικού υπολογιστή απέτυχε",
|
||||
"failed_to_shutdown": "Αποτυχία τερματισμού του κεντρικού υπολογιστή",
|
||||
"failed_to_reboot": "Αποτυχία επανεκκίνησης του διακομιστή",
|
||||
"failed_to_set_hostname": "Η ρύθμιση ονόματος διακομιστή απέτυχε",
|
||||
"failed_to_shutdown": "Αποτυχία τερματισμού του διακομιστή",
|
||||
"hardware": "Υλικό",
|
||||
"hostname": "Όνομα κεντρικού υπολογιστή",
|
||||
"hostname": "Όνομα διακομιστή",
|
||||
"import_from_usb": "Εισαγωγή από USB",
|
||||
"ip_address": "Διεύθυνση IP",
|
||||
"new_hostname": "Εισαγάγετε ένα νέο όνομα κεντρικού υπολογιστή:",
|
||||
"new_hostname": "Εισαγάγετε ένα νέο όνομα διακομιστή:",
|
||||
"operating_system": "Λειτουργικό σύστημα",
|
||||
"reboot_host": "Επανεκκίνηση κεντρικού υπολογιστή",
|
||||
"shutdown_host": "Τερματισμός κεντρικού υπολογιστή",
|
||||
"reboot_host": "Επανεκκίνηση διακομιστή",
|
||||
"shutdown_host": "Τερματισμός διακομιστή",
|
||||
"used_space": "Χρησιμοποιημένος χώρος"
|
||||
},
|
||||
"log": {
|
||||
@@ -444,31 +448,33 @@
|
||||
"beta_release_items": "Αυτό περιλαμβάνει εκδόσεις beta για:",
|
||||
"beta_warning": "Οι εκδόσεις beta προορίζονται για δοκιμαστές και πρώτους χρήστες και μπορούν να περιέχουν ασταθείς αλλαγές κώδικα",
|
||||
"channel": "Κανάλι",
|
||||
"cpu_usage": "Χρήση CPU Επόπτη",
|
||||
"failed_to_reload": "Απέτυχε η επαναφόρτωση του Επόπτη",
|
||||
"failed_to_set_option": "Αποτυχία ορισμού επιλογής Επόπτη",
|
||||
"failed_to_update": "Απέτυχε η ενημέρωση του Επόπτη",
|
||||
"cpu_usage": "Χρήση CPU του Supervisor",
|
||||
"failed_to_reload": "Απέτυχε η επαναφόρτωση του Supervisor",
|
||||
"failed_to_set_option": "Αποτυχία ορισμού επιλογής Supervisor",
|
||||
"failed_to_update": "Απέτυχε η ενημέρωση του Supervisor",
|
||||
"join_beta_action": "Εγγραφείτε στο κανάλι beta",
|
||||
"join_beta_description": "Λάβετε ενημερώσεις beta για Home Assistant (RCs), Επόπτη και κεντρικό υπολογιστές",
|
||||
"join_beta_description": "Λάβετε ενημερώσεις beta για Home Assistant (RC),Supervisor και του host",
|
||||
"leave_beta_action": "Αποχώρηση από το κανάλι beta",
|
||||
"leave_beta_description": "Λάβετε σταθερές ενημερώσεις για το Home Assistant, τον Επόπτη και τον κεντρικό υπολογιστή",
|
||||
"ram_usage": "Χρήση μνήμης RAM Επόπτη",
|
||||
"reload_supervisor": "Επαναφόρτωση Επόπτη",
|
||||
"ram_usage": "Χρήση μνήμης RAM του Supervisor",
|
||||
"reload_supervisor": "Επαναφόρτωση Supervisor",
|
||||
"share_diagnostics": "Κοινή χρήση διαγνωστικών",
|
||||
"share_diagnostics_description": "Μοιραστείτε αναφορές σφαλμάτων και διαγνωστικές πληροφορίες.",
|
||||
"share_diagonstics_description": "Θα θέλατε να κοινοποιείτε αυτόματα αναφορές σφαλμάτων και διαγνωστικές πληροφορίες όταν ο επόπτης αντιμετωπίζει απρόσμενα σφάλματα; {line_break} Αυτό θα μας επιτρέψει να διορθώσουμε τα προβλήματα, οι πληροφορίες είναι προσβάσιμες μόνο από την ομάδα του Home Assistant Core και δεν θα κοινοποιηθούν σε άλλους. {line_break} Τα δεδομένα δεν περιλαμβάνουν ιδιωτικές / ευαίσθητες πληροφορίες και μπορείτε να το απενεργοποιήσετε στις ρυθμίσεις όποτε θέλετε.",
|
||||
"share_diagonstics_description": "Θα θέλατε να κοινοποιείτε αυτόματα αναφορές σφαλμάτων και διαγνωστικές πληροφορίες όταν ο Supervisor αντιμετωπίζει απρόσμενα σφάλματα; {line_break} Αυτό θα μας επιτρέψει να διορθώσουμε τα προβλήματα, οι πληροφορίες είναι προσβάσιμες μόνο από την ομάδα του Home Assistant Core και δεν θα κοινοποιηθούν σε άλλους. {line_break} Τα δεδομένα δεν περιλαμβάνουν ιδιωτικές / ευαίσθητες πληροφορίες και μπορείτε να το απενεργοποιήσετε στις ρυθμίσεις όποτε θέλετε.",
|
||||
"share_diagonstics_title": "Βοηθήστε στη βελτίωση του Home Assistant",
|
||||
"unhealthy_description": "Η εκτέλεση μιας ανθυγιεινής εγκατάστασης θα προκαλέσει προβλήματα. Ακολουθεί μια λίστα με ζητήματα που εντοπίστηκαν με την εγκατάστασή σας, κάντε κλικ στους συνδέσμους για να μάθετε πώς μπορείτε να επιλύσετε τα προβλήματα.",
|
||||
"unhealthy_reason": {
|
||||
"docker": "Το περιβάλλον Docker δεν λειτουργεί σωστά",
|
||||
"privileged": "Ο Επόπτης δεν έχει προνόμια",
|
||||
"setup": "Η εγκατάσταση του Επόπτη απέτυχε",
|
||||
"supervisor": "Ο επόπτης δεν μπόρεσε να ενημερωθεί"
|
||||
"supervisor": "Ο επόπτης δεν μπόρεσε να ενημερωθεί",
|
||||
"untrusted": "Εντοπίστηκε αναξιόπιστο περιεχόμενο"
|
||||
},
|
||||
"unhealthy_title": "Η εγκατάστασή σας είναι ανθυγιεινή",
|
||||
"unsupported_description": "Ακολουθεί μια λίστα με ζητήματα που εντοπίστηκαν με την εγκατάστασή σας, κάντε κλικ στους συνδέσμους για να μάθετε πώς μπορείτε να επιλύσετε τα προβλήματα.",
|
||||
"unsupported_reason": {
|
||||
"container": "Κοντέινερ που είναι γνωστά ότι προκαλούν προβλήματα",
|
||||
"content-trust": "Η επικύρωση αξιόπιστου περιεχόμενου είναι απενεργοποιημένη",
|
||||
"dbus": "DBUS",
|
||||
"docker_configuration": "Διαμόρφωση Docker",
|
||||
"docker_version": "Έκδοση Docker",
|
||||
@@ -502,14 +508,14 @@
|
||||
"disarm": "Αφοπλισμός"
|
||||
},
|
||||
"automation": {
|
||||
"last_triggered": "Τελευταίο έναυσμα",
|
||||
"last_triggered": "Τελευταία ενεργοποίηση",
|
||||
"trigger": "Εκτέλεση ενεργειών"
|
||||
},
|
||||
"camera": {
|
||||
"not_available": "Μη διαθέσιμη εικόνα"
|
||||
},
|
||||
"climate": {
|
||||
"aux_heat": "Θερμοκρασία Aux",
|
||||
"aux_heat": "Βοηθητική θέρμανση",
|
||||
"away_mode": "Λειτουργία εκτός σπιτιού",
|
||||
"cooling": "{name} ψύξη",
|
||||
"current_temperature": "{name} τρέχουσα θερμοκρασία",
|
||||
@@ -781,7 +787,8 @@
|
||||
"was_unlocked": "ήταν ξεκλείδωτο",
|
||||
"was_unplugged": "ήταν αποσυνδεδεμένο",
|
||||
"was_unsafe": "δεν ήταν ασφαλές"
|
||||
}
|
||||
},
|
||||
"show_trace": "Εμφάνιση ίχνους"
|
||||
},
|
||||
"media-browser": {
|
||||
"audio_not_supported": "Το πρόγραμμα περιήγησής σας δεν υποστηρίζει το στοιχείο ήχου.",
|
||||
@@ -1009,6 +1016,9 @@
|
||||
"person": {
|
||||
"create_zone": "Δημιουργία ζώνης από την τρέχουσα θέση"
|
||||
},
|
||||
"remote": {
|
||||
"activity": "Τρέχουσα δραστηριότητα"
|
||||
},
|
||||
"restored": {
|
||||
"confirm_remove_text": "Είστε βέβαιοι πως θέλετε να καταργήσετε αυτή την οντότητα;",
|
||||
"confirm_remove_title": "Θέλετε να αφαιρέσετε αυτή την οντότητα;",
|
||||
@@ -1138,6 +1148,7 @@
|
||||
"buttons": {
|
||||
"add": "Προσθήκη συσκευών μέσω αυτής της συσκευής",
|
||||
"clusters": "Διαχείριση συμπλεγμάτων",
|
||||
"device_children": "Προβολή παιδιών",
|
||||
"reconfigure": "Ρυθμίστε Ξανά Τη Συσκευή",
|
||||
"remove": "Κατάργηση συσκευής",
|
||||
"view_in_visualization": "Προβολή στην Απεικόνιση",
|
||||
@@ -1146,6 +1157,7 @@
|
||||
"confirmations": {
|
||||
"remove": "Είστε βέβαιοι ότι θέλετε να καταργήσετε τη συσκευή;"
|
||||
},
|
||||
"device_children": "Παιδιά συσκευής Zigbee",
|
||||
"device_signature": "Υπογραφή συσκευής Zigbee",
|
||||
"last_seen": "Εθεάθη τελευταία",
|
||||
"manuf": "από τον {manufacturer}",
|
||||
@@ -1180,6 +1192,7 @@
|
||||
"key_missing": "Λείπει το απαιτούμενο κλειδί \"{key}\".",
|
||||
"key_not_expected": "Το κλειδί \"{key}\" δεν αναμένεται ή δεν υποστηρίζεται από το οπτικό πρόγραμμα επεξεργασίας.",
|
||||
"key_wrong_type": "Η παρεχόμενη τιμή για το \"{key}\" δεν υποστηρίζεται από το οπτικό πρόγραμμα επεξεργασίας. Υποστηρίζουμε ({type_correct}) αλλά λάβαμε ({type_wrong}).",
|
||||
"no_template_editor_support": "Τα πρότυπα δεν υποστηρίζονται στο οπτικό πρόγραμμα επεξεργασίας",
|
||||
"no_type_provided": "Δεν παρέχεται τύπος."
|
||||
}
|
||||
},
|
||||
@@ -1287,10 +1300,15 @@
|
||||
"device_id": {
|
||||
"action": "Ενέργεια",
|
||||
"extra_fields": {
|
||||
"brightness_pct": "Φωτεινότητα",
|
||||
"code": "Κώδικας",
|
||||
"flash": "Φλας",
|
||||
"humidity": "Υγρασία",
|
||||
"message": "Μήνυμα",
|
||||
"mode": "Λειτουργία",
|
||||
"position": "Θέση",
|
||||
"title": "Τίτλος"
|
||||
"title": "Τίτλος",
|
||||
"value": "Τιμή"
|
||||
},
|
||||
"label": "Συσκευή"
|
||||
},
|
||||
@@ -1335,7 +1353,7 @@
|
||||
"wait_template": "Πρότυπο Αναμονής"
|
||||
}
|
||||
},
|
||||
"unsupported_action": "Χωρίς υποστήριξη διεπαφής χρήστη για ενέργεια: {action}"
|
||||
"unsupported_action": "Χωρίς υποστήριξη οπτικού επεξεργαστή για ενέργεια: {action}"
|
||||
},
|
||||
"alias": "Όνομα",
|
||||
"blueprint": {
|
||||
@@ -1363,7 +1381,9 @@
|
||||
"extra_fields": {
|
||||
"above": "Πάνω από",
|
||||
"below": "Κάτω από",
|
||||
"for": "Διάρκεια"
|
||||
"for": "Διάρκεια",
|
||||
"hvac_mode": "Λειτουργία κλιματισμού",
|
||||
"preset_mode": "Προεπιλεγμένη λειτουργία"
|
||||
},
|
||||
"label": "Συσκευή"
|
||||
},
|
||||
@@ -1418,7 +1438,7 @@
|
||||
"zone": "Ζώνη"
|
||||
}
|
||||
},
|
||||
"unsupported_condition": "Χωρίς υποστήριξη διεπαφής χρήστη για συνθήκη: {condition}"
|
||||
"unsupported_condition": "Χωρίς υποστήριξη οπτικού επεξεργαστή για συνθήκη: {condition}"
|
||||
},
|
||||
"copy_to_clipboard": "Αντιγραφή στο Πρόχειρο",
|
||||
"default_name": "Νέος αυτοματισμός",
|
||||
@@ -1426,8 +1446,8 @@
|
||||
"label": "Περιγραφή",
|
||||
"placeholder": "Προαιρετική περιγραφή"
|
||||
},
|
||||
"edit_ui": "Επεξεργασία με περιβάλλον εργασίας χρήστη",
|
||||
"edit_yaml": "Επεξεργασία ως YAML",
|
||||
"edit_ui": "Επεξεργασία σε οπτικό επεξεργαστή",
|
||||
"edit_yaml": "Επεξεργασία σε YAML",
|
||||
"enable_disable": "Ενεργοποίηση / Απενεργοποίηση αυτοματοποίησης",
|
||||
"introduction": "Χρησιμοποιήστε αυτοματισμούς για να ζωντανέψετε το σπίτι σας.",
|
||||
"load_error_not_editable": "Μόνο οι αυτοματισμοί στο automations.yaml είναι επεξεργάσιμοι.",
|
||||
@@ -1548,7 +1568,7 @@
|
||||
"zone": "Ζώνη"
|
||||
}
|
||||
},
|
||||
"unsupported_platform": "Χωρίς υποστήριξη διεπαφής χρήστη για πλατφόρμα: {platform}"
|
||||
"unsupported_platform": "Χωρίς υποστήριξη οπτικού επεξεργαστή για πλατφόρμα: {platform}"
|
||||
},
|
||||
"unsaved_confirm": "Δεν αποθηκεύσατε τις αλλαγές. Είστε βέβαιοι ότι θέλετε να φύγετε;"
|
||||
},
|
||||
@@ -1556,6 +1576,8 @@
|
||||
"add_automation": "Προσθήκη αυτοματισμού",
|
||||
"delete_automation": "Διαγραφή αυτοματισμού",
|
||||
"delete_confirm": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτόν τον αυτοματισμό;",
|
||||
"dev_automation": "Αυτόματος εντοπισμός σφαλμάτων",
|
||||
"dev_only_editable": "Ο εντοπισμός σφαλμάτων γίνεται μόνο στους αυτοματισμούς που ορίζονται μέσα στο automations.yaml.",
|
||||
"duplicate": "Διπλότυπο",
|
||||
"duplicate_automation": "Διπλή αυτοματοποίηση",
|
||||
"edit_automation": "Επεξεργασία αυτοματισμού",
|
||||
@@ -1619,6 +1641,8 @@
|
||||
},
|
||||
"introduction": "Η διαμόρφωση του σχεδιαγράμματος σας επιτρέπει να εισάγετε και να διαχειρίζεστε τα σχεδιαγράμματά σας.",
|
||||
"learn_more": "Μάθετε περισσότερα σχετικά με τη χρήση σχεδιαγραμμάτων",
|
||||
"share_blueprint": "Κοινή χρήση σχεδίου",
|
||||
"share_blueprint_no_url": "Δεν είναι δυνατή η κοινή χρήση του σχεδίου: δεν υπάρχει διεύθυνση URL προέλευσης",
|
||||
"use_blueprint": "Δημιουργία αυτοματισμού"
|
||||
}
|
||||
},
|
||||
@@ -1643,12 +1667,12 @@
|
||||
"fetching_subscription": "Λήψη συνδρομής…",
|
||||
"google": {
|
||||
"config_documentation": "Τεκμηρίωση παραμετροποίησης",
|
||||
"devices_pin": "Κωδικός pin συσκευών ασφαλείας",
|
||||
"devices_pin": "PIN Συσκευών Ασφαλείας",
|
||||
"enable_ha_skill": "Ενεργοποιήστε την ικανότητα του Home Assistant για τον Google Assistant.",
|
||||
"enable_state_reporting": "Ενεργοποίηση αναφορών κατάστασης",
|
||||
"enter_pin_error": "Δεν είναι δυνατή η αποθήκευση του pin:",
|
||||
"enter_pin_error": "Δεν είναι δυνατή η αποθήκευση του PIN:",
|
||||
"enter_pin_hint": "Πληκτρολογήστε έναν κωδικό PIN για να χρησιμοποιήσετε συσκευές ασφαλείας",
|
||||
"enter_pin_info": "Παρακαλώ εισάγετε έναν κωδικό pin για να αλληλεπιδρούν με τις συσκευές ασφαλείας. Οι συσκευές ασφαλείας είναι πόρτες, γκαράζ, πόρτες και κλειδαριές. Θα σας ζητηθεί να πείτε/εισάγετε αυτό το pin κατά την αλληλεπίδραση με αυτές τις συσκευές μέσω του Google Assistant.",
|
||||
"enter_pin_info": "Παρακαλώ εισάγετε έναν κωδικό PIN για να αλληλεπιδράσετε με συσκευές ασφαλείας. Οι συσκευές ασφαλείας είναι πόρτες, πόρτες χώρων στάθμευσης και κλειδαριές. Θα σας ζητηθεί να πείτε/εισάγετε αυτό το PIN κατά την αλληλεπίδραση με τέτοιες συσκευές μέσω του Google Assistant.",
|
||||
"info": "Με την ενοποίηση του Google Assistant για το Home Assistant Cloud θα έχετε τη δυνατότητα να ελέγχετε όλες τις συσκευές του Home Assistant μέσω οποιασδήποτε συσκευής με ενεργοποιημένο το Google Assistant.",
|
||||
"info_state_reporting": "Αν ενεργοποιήσετε την αναφορά κατάστασης, το Home Assistant θα στείλει όλες τις αλλαγές κατάστασης των εκτεθειμένων οντοτήτων στην Google. Αυτό σας επιτρέπει να βλέπετε πάντα τις τελευταίες καταστάσεις στην εφαρμογή Google.",
|
||||
"manage_entities": "Διαχείριση Οντοτήτων",
|
||||
@@ -2363,7 +2387,7 @@
|
||||
"step": "Βήμα",
|
||||
"title": "Ανανέωση πληροφοριών κόμβου",
|
||||
"wakeup_header": "Οδηγίες αφύπνισης για",
|
||||
"wakeup_instructions_source": "Οι οδηγίες αφύπνισης προέρχονται από τη βάση δεδομένων συσκευών κοινότητας OpenZWave."
|
||||
"wakeup_instructions_source": "Οι οδηγίες αφύπνισης προέρχονται από τη βάση δεδομένων συσκευών της κοινότητας OpenZWave."
|
||||
},
|
||||
"select_instance": {
|
||||
"header": "Επιλέξτε ένα στιγμιότυπο OpenZWave",
|
||||
@@ -2639,7 +2663,7 @@
|
||||
"add_device": "Προσθήκη συσκευής",
|
||||
"add_device_page": {
|
||||
"discovered_text": "Οι συσκευές θα εμφανιστούν εδώ μόλις ανακαλυφθούν.",
|
||||
"no_devices_found": "Δεν βρέθηκαν συσκευές, βεβαιωθείτε ότι βρίσκονται σε λειτουργία ζευγαρώματος και κρατήστε τις ξύπνιες ενώ η ανακάλυψη εκτελείται.",
|
||||
"no_devices_found": "Δεν βρέθηκαν συσκευές, βεβαιωθείτε ότι βρίσκονται σε λειτουργία σύζευξης και κρατήστε τις ξύπνιες ενώ η αναζήτηση εκτελείται.",
|
||||
"pairing_mode": "Βεβαιωθείτε ότι οι συσκευές σας είναι σε λειτουργία σύζευξης. Ελέγξτε τις οδηγίες της συσκευής σας για το πώς να το κάνετε αυτό.",
|
||||
"search_again": "Αναζήτηση ξανά",
|
||||
"spinner": "Αναζήτηση συσκευών ZHA Zigbee…"
|
||||
@@ -2715,6 +2739,7 @@
|
||||
"caption": "Δίκτυο"
|
||||
},
|
||||
"visualization": {
|
||||
"auto_zoom": "Αυτόματο ζουμ",
|
||||
"caption": "Απεικόνιση",
|
||||
"header": "Απεικόνιση δικτύου",
|
||||
"highlight_label": "Επισήμανση συσκευών",
|
||||
@@ -2827,7 +2852,7 @@
|
||||
"instance": "Περίπτωση",
|
||||
"unknown": "Άγνωστο",
|
||||
"value": "Τιμή",
|
||||
"wakeup_interval": "Διάστημα αφύπνισης"
|
||||
"wakeup_interval": "Διάστημα μεταξύ Aφυπνίσεων"
|
||||
},
|
||||
"description": "Διαχειριστείτε το δίκτυο Z-Wave",
|
||||
"learn_more": "Μάθετε περισσότερα σχετικά με το Z-wave",
|
||||
@@ -2856,7 +2881,7 @@
|
||||
"header": "Επιλογές Παραμετροποίησης κόμβου",
|
||||
"seconds": "Δευτερόλεπτα",
|
||||
"set_config_parameter": "Ορίστε την παράμετρο διαμόρφωσης",
|
||||
"set_wakeup": "Ορισμός διαστήματος αφύπνισης",
|
||||
"set_wakeup": "Όρισε διάστημα μεταξύ Αφυπνίσεων",
|
||||
"true": "Αληθής"
|
||||
},
|
||||
"node_management": {
|
||||
@@ -2991,6 +3016,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"go_back": "Πίσω",
|
||||
"supervisor": {
|
||||
"ask": "Ζητήσετε βοήθεια",
|
||||
"observer": "Έλεγχος του Παρατηρητή",
|
||||
"reboot": "Δοκιμάστε μια επανεκκίνηση του διακομιστή",
|
||||
"system_health": "Έλεγχος υγείας συστήματος",
|
||||
"title": "Δεν ήταν δυνατή η φόρτωση του πίνακα Supervisor!",
|
||||
"wait": "Εάν μόλις ξεκινήσατε, βεβαιωθείτε ότι έχετε δώσει στον Supervisor αρκετό χρόνο για να ξεκινήσει."
|
||||
}
|
||||
},
|
||||
"history": {
|
||||
"ranges": {
|
||||
"last_week": "Προηγούμενη εβδομάδα",
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
"install": "install",
|
||||
"new_update_available": "{name} {version} is available",
|
||||
"not_available_arch": "This add-on is not compatible with the processor of your device or the operating system you have installed on your device.",
|
||||
"not_available_version": "You are unning Home Assistant {core_version_installed}, to update to this version of the add-on you need at least version {core_version_needed} of Home Assistan",
|
||||
"not_available_version": "You are running Home Assistant {core_version_installed}, to update to this version of the add-on you need at least version {core_version_needed} of Home Assistant",
|
||||
"open_web_ui": "Open web UI",
|
||||
"option": {
|
||||
"auto_update": {
|
||||
@@ -245,7 +245,7 @@
|
||||
"start": "start",
|
||||
"stop": "stop",
|
||||
"uninstall": "uninstall",
|
||||
"visit_addon_page": "Visit the {name} page for more detals"
|
||||
"visit_addon_page": "Visit the {name} page for more details"
|
||||
},
|
||||
"documentation": {
|
||||
"get_documentation": "Failed to get add-on documentation, {error}"
|
||||
@@ -327,7 +327,7 @@
|
||||
"gateway": "Gateway address",
|
||||
"ip_netmask": "IP address/Netmask",
|
||||
"open": "Open",
|
||||
"scan_ap": "Scan for accesspoints",
|
||||
"scan_ap": "Scan for access points",
|
||||
"static": "Static",
|
||||
"title": "Network settings",
|
||||
"unsaved": "You have unsaved changes, these will get lost if you change tabs, do you want to continue?",
|
||||
@@ -365,7 +365,7 @@
|
||||
}
|
||||
},
|
||||
"my": {
|
||||
"error": "An unknown error occured",
|
||||
"error": "An unknown error occurred",
|
||||
"error_addon_not_found": "Add-on not found",
|
||||
"faq_link": "My Home Assistant FAQ",
|
||||
"not_supported": "This redirect is not supported by your Home Assistant instance. Check the {link} for the supported redirects and the version they where introduced."
|
||||
@@ -467,12 +467,14 @@
|
||||
"docker": "The Docker environment is not working properly",
|
||||
"privileged": "Supervisor is not privileged",
|
||||
"setup": "Setup of the Supervisor failed",
|
||||
"supervisor": "Supervisor was not able to update"
|
||||
"supervisor": "Supervisor was not able to update",
|
||||
"untrusted": "Detected untrusted content"
|
||||
},
|
||||
"unhealthy_title": "Your installation is unhealthy",
|
||||
"unsupported_description": "Below is a list of issues found with your installation, click on the links to learn how you can resolve the issues.",
|
||||
"unsupported_reason": {
|
||||
"container": "Containers known to cause issues",
|
||||
"content-trust": "Content-trust validation is disabled",
|
||||
"dbus": "DBUS",
|
||||
"docker_configuration": "Docker Configuration",
|
||||
"docker_version": "Docker Version",
|
||||
@@ -785,7 +787,8 @@
|
||||
"was_unlocked": "was unlocked",
|
||||
"was_unplugged": "was unplugged",
|
||||
"was_unsafe": "was unsafe"
|
||||
}
|
||||
},
|
||||
"show_trace": "Show trace"
|
||||
},
|
||||
"media-browser": {
|
||||
"audio_not_supported": "Your browser does not support the audio element.",
|
||||
@@ -1145,6 +1148,7 @@
|
||||
"buttons": {
|
||||
"add": "Add Devices via this device",
|
||||
"clusters": "Manage Clusters",
|
||||
"device_children": "View Children",
|
||||
"reconfigure": "Reconfigure Device",
|
||||
"remove": "Remove Device",
|
||||
"view_in_visualization": "View in Visualization",
|
||||
@@ -1153,6 +1157,7 @@
|
||||
"confirmations": {
|
||||
"remove": "Are you sure that you want to remove the device?"
|
||||
},
|
||||
"device_children": "Zigbee device children",
|
||||
"device_signature": "Zigbee device signature",
|
||||
"last_seen": "Last Seen",
|
||||
"manuf": "by {manufacturer}",
|
||||
@@ -1187,6 +1192,7 @@
|
||||
"key_missing": "Required key \"{key}\" is missing.",
|
||||
"key_not_expected": "Key \"{key}\" is not expected or not supported by the visual editor.",
|
||||
"key_wrong_type": "The provided value for \"{key}\" is not supported by the visual editor. We support ({type_correct}) but received ({type_wrong}).",
|
||||
"no_template_editor_support": "Templates not supported in visual editor",
|
||||
"no_type_provided": "No type provided."
|
||||
}
|
||||
},
|
||||
@@ -1294,10 +1300,15 @@
|
||||
"device_id": {
|
||||
"action": "Action",
|
||||
"extra_fields": {
|
||||
"brightness_pct": "Brightness",
|
||||
"code": "Code",
|
||||
"flash": "Flash",
|
||||
"humidity": "Humidity",
|
||||
"message": "Message",
|
||||
"mode": "Mode",
|
||||
"position": "Position",
|
||||
"title": "Title"
|
||||
"title": "Title",
|
||||
"value": "Value"
|
||||
},
|
||||
"label": "Device"
|
||||
},
|
||||
@@ -1342,7 +1353,7 @@
|
||||
"wait_template": "Wait Template"
|
||||
}
|
||||
},
|
||||
"unsupported_action": "No UI support for action: {action}"
|
||||
"unsupported_action": "No visual editor support for action: {action}"
|
||||
},
|
||||
"alias": "Name",
|
||||
"blueprint": {
|
||||
@@ -1370,7 +1381,9 @@
|
||||
"extra_fields": {
|
||||
"above": "Above",
|
||||
"below": "Below",
|
||||
"for": "Duration"
|
||||
"for": "Duration",
|
||||
"hvac_mode": "HVAC mode",
|
||||
"preset_mode": "Preset mode"
|
||||
},
|
||||
"label": "Device"
|
||||
},
|
||||
@@ -1425,7 +1438,7 @@
|
||||
"zone": "Zone"
|
||||
}
|
||||
},
|
||||
"unsupported_condition": "No UI support for condition: {condition}"
|
||||
"unsupported_condition": "No visual editor support for condition: {condition}"
|
||||
},
|
||||
"copy_to_clipboard": "Copy to Clipboard",
|
||||
"default_name": "New Automation",
|
||||
@@ -1433,8 +1446,8 @@
|
||||
"label": "Description",
|
||||
"placeholder": "Optional description"
|
||||
},
|
||||
"edit_ui": "Edit with UI",
|
||||
"edit_yaml": "Edit as YAML",
|
||||
"edit_ui": "Edit in visual editor",
|
||||
"edit_yaml": "Edit in YAML",
|
||||
"enable_disable": "Enable/Disable automation",
|
||||
"introduction": "Use automations to bring your home to life.",
|
||||
"load_error_not_editable": "Only automations in automations.yaml are editable.",
|
||||
@@ -1555,7 +1568,7 @@
|
||||
"zone": "Zone"
|
||||
}
|
||||
},
|
||||
"unsupported_platform": "No UI support for platform: {platform}"
|
||||
"unsupported_platform": "No visual editor support for platform: {platform}"
|
||||
},
|
||||
"unsaved_confirm": "You have unsaved changes. Are you sure you want to leave?"
|
||||
},
|
||||
@@ -1563,6 +1576,8 @@
|
||||
"add_automation": "Add automation",
|
||||
"delete_automation": "Delete automation",
|
||||
"delete_confirm": "Are you sure you want to delete this automation?",
|
||||
"dev_automation": "Debug automation",
|
||||
"dev_only_editable": "Only automations defined in automations.yaml are debuggable.",
|
||||
"duplicate": "Duplicate",
|
||||
"duplicate_automation": "Duplicate automation",
|
||||
"edit_automation": "Edit automation",
|
||||
@@ -1626,6 +1641,8 @@
|
||||
},
|
||||
"introduction": "The blueprint configuration allows you to import and manage your blueprints.",
|
||||
"learn_more": "Learn more about using blueprints",
|
||||
"share_blueprint": "Share blueprint",
|
||||
"share_blueprint_no_url": "Unable to share blueprint: no source url",
|
||||
"use_blueprint": "Create automation"
|
||||
}
|
||||
},
|
||||
@@ -1650,12 +1667,12 @@
|
||||
"fetching_subscription": "Fetching subscription…",
|
||||
"google": {
|
||||
"config_documentation": "Configuration documentation",
|
||||
"devices_pin": "Security Devices Pin",
|
||||
"devices_pin": "Security Devices PIN",
|
||||
"enable_ha_skill": "Activate the Home Assistant skill for Google Assistant",
|
||||
"enable_state_reporting": "Enable State Reporting",
|
||||
"enter_pin_error": "Unable to store pin:",
|
||||
"enter_pin_error": "Unable to store PIN:",
|
||||
"enter_pin_hint": "Enter a PIN to use security devices",
|
||||
"enter_pin_info": "Please enter a pin to interact with security devices. Security devices are doors, garage doors and locks. You will be asked to say/enter this pin when interacting with such devices via Google Assistant.",
|
||||
"enter_pin_info": "Please enter a PIN to interact with security devices. Security devices are doors, garage doors and locks. You will be asked to say/enter this PIN when interacting with such devices via Google Assistant.",
|
||||
"info": "With the Google Assistant integration for Home Assistant Cloud you'll be able to control all your Home Assistant devices via any Google Assistant-enabled device.",
|
||||
"info_state_reporting": "If you enable state reporting, Home Assistant will send all state changes of exposed entities to Google. This allows you to always see the latest states in the Google app.",
|
||||
"manage_entities": "Manage Entities",
|
||||
@@ -2079,7 +2096,7 @@
|
||||
"devices": "{count} {count, plural,\n one {device}\n other {devices}\n}",
|
||||
"disable_restart_confirm": "Restart Home Assistant to finish disabling this integration",
|
||||
"disable": {
|
||||
"disable_confirm": "Are you sure you want to disable this config entry? It's devices and entities will be disabled.",
|
||||
"disable_confirm": "Are you sure you want to disable this config entry? Its devices and entities will be disabled.",
|
||||
"disabled": "Disabled",
|
||||
"disabled_by": {
|
||||
"device": "device",
|
||||
@@ -2153,7 +2170,7 @@
|
||||
"integration": "integration",
|
||||
"integration_not_found": "Integration not found.",
|
||||
"new": "Set up a new integration",
|
||||
"no_integrations": "Seems like you don't have any integations configured yet. Click on the button below to add your first integration!",
|
||||
"no_integrations": "Seems like you don't have any integrations configured yet. Click on the button below to add your first integration!",
|
||||
"none": "Nothing configured yet",
|
||||
"none_found": "No integrations found",
|
||||
"none_found_detail": "Adjust your search criteria.",
|
||||
@@ -2345,7 +2362,7 @@
|
||||
"session": "Obtaining infrequently changing values from the node",
|
||||
"static": "Obtaining static values from the device",
|
||||
"versions": "Obtaining information about firmware and command class versions",
|
||||
"wakeup": "Setting up support for wakeup queues and messages"
|
||||
"wakeup": "Setting up support for wake-up queues and messages"
|
||||
},
|
||||
"node": {
|
||||
"button": "Node Details",
|
||||
@@ -2369,8 +2386,8 @@
|
||||
"start_refresh_button": "Start Refresh",
|
||||
"step": "Step",
|
||||
"title": "Refresh Node Information",
|
||||
"wakeup_header": "Wakeup Instructions for",
|
||||
"wakeup_instructions_source": "Wakeup instructions are sourced from the OpenZWave community device database."
|
||||
"wakeup_header": "Wake-up Instructions for",
|
||||
"wakeup_instructions_source": "Wake-up instructions are sourced from the OpenZWave community device database."
|
||||
},
|
||||
"select_instance": {
|
||||
"header": "Select an OpenZWave Instance",
|
||||
@@ -2646,7 +2663,7 @@
|
||||
"add_device": "Add Device",
|
||||
"add_device_page": {
|
||||
"discovered_text": "Devices will show up here once discovered.",
|
||||
"no_devices_found": "No devices were found, make sure they are in paring mode and keep them awake while discovering is running.",
|
||||
"no_devices_found": "No devices were found, make sure they are in pairing mode and keep them awake while discovering is running.",
|
||||
"pairing_mode": "Make sure your devices are in pairing mode. Check the instructions of your device on how to do this.",
|
||||
"search_again": "Search Again",
|
||||
"spinner": "Searching for ZHA Zigbee devices..."
|
||||
@@ -2722,6 +2739,7 @@
|
||||
"caption": "Network"
|
||||
},
|
||||
"visualization": {
|
||||
"auto_zoom": "Auto Zoom",
|
||||
"caption": "Visualization",
|
||||
"header": "Network Visualization",
|
||||
"highlight_label": "Highlight Devices",
|
||||
@@ -2797,6 +2815,7 @@
|
||||
"server_version": "Server Version"
|
||||
},
|
||||
"device_info": {
|
||||
"device_config": "Configure Device",
|
||||
"node_ready": "Node Ready",
|
||||
"node_status": "Node Status",
|
||||
"zwave_info": "Z-Wave Info"
|
||||
@@ -2809,6 +2828,15 @@
|
||||
"connecting": "Connecting",
|
||||
"unknown": "Unknown"
|
||||
},
|
||||
"node_config": {
|
||||
"attribution": "Device configuration parameters and descriptions are provided by the {device_database}",
|
||||
"battery_device_notice": "Battery devices must be awake to update their config. Please refer to your device manual for instructions on how to wake the device.",
|
||||
"error_device_not_found": "Device not found",
|
||||
"header": "Z-Wave Device Configuration",
|
||||
"introduction": "Manage and adjust device (node) specific configuration parameters for the selected device",
|
||||
"parameter_is_read_only": "This parameter is read-only.",
|
||||
"zwave_js_device_database": "Z-Wave JS Device Database"
|
||||
},
|
||||
"node_status": {
|
||||
"alive": "Alive",
|
||||
"asleep": "Asleep",
|
||||
@@ -2834,7 +2862,7 @@
|
||||
"instance": "Instance",
|
||||
"unknown": "unknown",
|
||||
"value": "Value",
|
||||
"wakeup_interval": "Wakeup Interval"
|
||||
"wakeup_interval": "Wake-up Interval"
|
||||
},
|
||||
"description": "Manage your Z-Wave network",
|
||||
"learn_more": "Learn more about Z-Wave",
|
||||
@@ -2863,7 +2891,7 @@
|
||||
"header": "Node Configuration Options",
|
||||
"seconds": "seconds",
|
||||
"set_config_parameter": "Set Configuration Parameter",
|
||||
"set_wakeup": "Set Wakeup Interval",
|
||||
"set_wakeup": "Set Wake-up Interval",
|
||||
"true": "True"
|
||||
},
|
||||
"node_management": {
|
||||
@@ -2998,6 +3026,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"go_back": "Go back",
|
||||
"supervisor": {
|
||||
"ask": "Ask for help",
|
||||
"observer": "Check the Observer",
|
||||
"reboot": "Try a reboot of the host",
|
||||
"system_health": "Check System Health",
|
||||
"title": "Could not load the Supervisor panel!",
|
||||
"wait": "If you just started, make sure you have given the supervisor enough time to start."
|
||||
}
|
||||
},
|
||||
"history": {
|
||||
"ranges": {
|
||||
"last_week": "Last week",
|
||||
@@ -3493,7 +3532,7 @@
|
||||
"my": {
|
||||
"component_not_loaded": "This redirect is not supported by your Home Assistant instance. You need the integration {integration} to use this redirect.",
|
||||
"documentation": "documentation",
|
||||
"error": "An unknown error occured",
|
||||
"error": "An unknown error occurred",
|
||||
"faq_link": "My Home Assistant FAQ",
|
||||
"no_supervisor": "This redirect is not supported by your Home Assistant installation. It needs either the Home Assistant Operating System or Home Assistant Supervised installation method. For more information, see the {docs_link}.",
|
||||
"not_supported": "This redirect is not supported by your Home Assistant instance. Check the {link} for the supported redirects and the version they where introduced."
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user