mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-30 04:36:36 +00:00
commit
6bbe8ff39f
@ -21,7 +21,7 @@ gulp.task(
|
|||||||
"gen-icons",
|
"gen-icons",
|
||||||
"gen-pages-dev",
|
"gen-pages-dev",
|
||||||
"gen-index-app-dev",
|
"gen-index-app-dev",
|
||||||
"build-translations"
|
gulp.series("create-test-translation", "build-translations")
|
||||||
),
|
),
|
||||||
"copy-static",
|
"copy-static",
|
||||||
"webpack-watch-app"
|
"webpack-watch-app"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const del = require("del");
|
const del = require("del");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const gulp = require("gulp");
|
const gulp = require("gulp");
|
||||||
|
const fs = require("fs");
|
||||||
const foreach = require("gulp-foreach");
|
const foreach = require("gulp-foreach");
|
||||||
const hash = require("gulp-hash");
|
const hash = require("gulp-hash");
|
||||||
const hashFilename = require("gulp-hash-filename");
|
const hashFilename = require("gulp-hash-filename");
|
||||||
@ -72,6 +73,20 @@ function emptyFilter(data) {
|
|||||||
return newData;
|
return newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recursiveEmpty(data) {
|
||||||
|
const newData = {};
|
||||||
|
Object.keys(data).forEach((key) => {
|
||||||
|
if (data[key]) {
|
||||||
|
if (typeof data[key] === "object") {
|
||||||
|
newData[key] = recursiveEmpty(data[key]);
|
||||||
|
} else {
|
||||||
|
newData[key] = "TRANSLATED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return newData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace Lokalise key placeholders with their actual values.
|
* Replace Lokalise key placeholders with their actual values.
|
||||||
*
|
*
|
||||||
@ -108,6 +123,37 @@ gulp.task(taskName, function() {
|
|||||||
});
|
});
|
||||||
tasks.push(taskName);
|
tasks.push(taskName);
|
||||||
|
|
||||||
|
taskName = "create-test-metadata";
|
||||||
|
gulp.task(taskName, function(cb) {
|
||||||
|
fs.writeFile(
|
||||||
|
workDir + "/testMetadata.json",
|
||||||
|
JSON.stringify({
|
||||||
|
test: {
|
||||||
|
nativeName: "Test",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
cb
|
||||||
|
);
|
||||||
|
});
|
||||||
|
tasks.push(taskName);
|
||||||
|
|
||||||
|
taskName = "create-test-translation";
|
||||||
|
gulp.task(
|
||||||
|
taskName,
|
||||||
|
gulp.series("create-test-metadata", function() {
|
||||||
|
return gulp
|
||||||
|
.src("src/translations/en.json")
|
||||||
|
.pipe(
|
||||||
|
transform(function(data, file) {
|
||||||
|
return recursiveEmpty(data);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.pipe(rename("test.json"))
|
||||||
|
.pipe(gulp.dest(workDir));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
tasks.push(taskName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This task will build a master translation file, to be used as the base for
|
* This task will build a master translation file, to be used as the base for
|
||||||
* all languages. This starts with src/translations/en.json, and replaces all
|
* all languages. This starts with src/translations/en.json, and replaces all
|
||||||
@ -138,33 +184,38 @@ taskName = "build-merged-translations";
|
|||||||
gulp.task(
|
gulp.task(
|
||||||
taskName,
|
taskName,
|
||||||
gulp.series("build-master-translation", function() {
|
gulp.series("build-master-translation", function() {
|
||||||
return gulp.src(inDir + "/*.json").pipe(
|
return gulp
|
||||||
foreach(function(stream, file) {
|
.src([inDir + "/*.json", workDir + "/test.json"], { allowEmpty: true })
|
||||||
// For each language generate a merged json file. It begins with the master
|
.pipe(
|
||||||
// translation as a failsafe for untranslated strings, and merges all parent
|
foreach(function(stream, file) {
|
||||||
// tags into one file for each specific subtag
|
// For each language generate a merged json file. It begins with the master
|
||||||
//
|
// translation as a failsafe for untranslated strings, and merges all parent
|
||||||
// TODO: This is a naive interpretation of BCP47 that should be improved.
|
// tags into one file for each specific subtag
|
||||||
// Will be OK for now as long as we don't have anything more complicated
|
//
|
||||||
// than a base translation + region.
|
// TODO: This is a naive interpretation of BCP47 that should be improved.
|
||||||
const tr = path.basename(file.history[0], ".json");
|
// Will be OK for now as long as we don't have anything more complicated
|
||||||
const subtags = tr.split("-");
|
// than a base translation + region.
|
||||||
const src = [workDir + "/translationMaster.json"];
|
const tr = path.basename(file.history[0], ".json");
|
||||||
for (let i = 1; i <= subtags.length; i++) {
|
const subtags = tr.split("-");
|
||||||
const lang = subtags.slice(0, i).join("-");
|
const src = [
|
||||||
src.push(inDir + "/" + lang + ".json");
|
workDir + "/translationMaster.json",
|
||||||
}
|
workDir + "/test.json",
|
||||||
return gulp
|
];
|
||||||
.src(src, { allowEmpty: true })
|
for (let i = 1; i <= subtags.length; i++) {
|
||||||
.pipe(transform((data) => emptyFilter(data)))
|
const lang = subtags.slice(0, i).join("-");
|
||||||
.pipe(
|
src.push(inDir + "/" + lang + ".json");
|
||||||
merge({
|
}
|
||||||
fileName: tr + ".json",
|
return gulp
|
||||||
})
|
.src(src, { allowEmpty: true })
|
||||||
)
|
.pipe(transform((data) => emptyFilter(data)))
|
||||||
.pipe(gulp.dest(fullDir));
|
.pipe(
|
||||||
})
|
merge({
|
||||||
);
|
fileName: tr + ".json",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.pipe(gulp.dest(fullDir));
|
||||||
|
})
|
||||||
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
tasks.push(taskName);
|
tasks.push(taskName);
|
||||||
@ -299,10 +350,14 @@ gulp.task(
|
|||||||
taskName,
|
taskName,
|
||||||
gulp.series("build-translation-fingerprints", function() {
|
gulp.series("build-translation-fingerprints", function() {
|
||||||
return gulp
|
return gulp
|
||||||
.src([
|
.src(
|
||||||
"src/translations/translationMetadata.json",
|
[
|
||||||
workDir + "/translationFingerprints.json",
|
"src/translations/translationMetadata.json",
|
||||||
])
|
workDir + "/testMetadata.json",
|
||||||
|
workDir + "/translationFingerprints.json",
|
||||||
|
],
|
||||||
|
{ allowEmpty: true }
|
||||||
|
)
|
||||||
.pipe(merge({}))
|
.pipe(merge({}))
|
||||||
.pipe(
|
.pipe(
|
||||||
transform(function(data) {
|
transform(function(data) {
|
||||||
|
@ -75,8 +75,9 @@
|
|||||||
"es6-object-assign": "^1.1.0",
|
"es6-object-assign": "^1.1.0",
|
||||||
"fecha": "^3.0.2",
|
"fecha": "^3.0.2",
|
||||||
"fuse.js": "^3.4.4",
|
"fuse.js": "^3.4.4",
|
||||||
|
"google-timezones-json": "^1.0.2",
|
||||||
"hls.js": "^0.12.4",
|
"hls.js": "^0.12.4",
|
||||||
"home-assistant-js-websocket": "^4.1.2",
|
"home-assistant-js-websocket": "^4.2.1",
|
||||||
"intl-messageformat": "^2.2.0",
|
"intl-messageformat": "^2.2.0",
|
||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
"js-yaml": "^3.13.0",
|
"js-yaml": "^3.13.0",
|
||||||
|
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="home-assistant-frontend",
|
name="home-assistant-frontend",
|
||||||
version="20190514.0",
|
version="20190523.0",
|
||||||
description="The Home Assistant frontend",
|
description="The Home Assistant frontend",
|
||||||
url="https://github.com/home-assistant/home-assistant-polymer",
|
url="https://github.com/home-assistant/home-assistant-polymer",
|
||||||
author="The Home Assistant Authors",
|
author="The Home Assistant Authors",
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
import { HomeAssistant } from "../../types";
|
import { UnsubscribeFunc, Connection } from "home-assistant-js-websocket";
|
||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
|
||||||
|
|
||||||
export const subscribeOne = async <T>(
|
export const subscribeOne = async <T>(
|
||||||
hass: HomeAssistant,
|
conn: Connection,
|
||||||
subscribe: (
|
subscribe: (conn: Connection, onChange: (items: T) => void) => UnsubscribeFunc
|
||||||
hass: HomeAssistant,
|
|
||||||
onChange: (items: T) => void
|
|
||||||
) => UnsubscribeFunc
|
|
||||||
) =>
|
) =>
|
||||||
new Promise<T>((resolve) => {
|
new Promise<T>((resolve) => {
|
||||||
const unsub = subscribe(hass, (items) => {
|
const unsub = subscribe(conn, (items) => {
|
||||||
unsub();
|
unsub();
|
||||||
resolve(items);
|
resolve(items);
|
||||||
});
|
});
|
||||||
|
13
src/components/timezone-datalist.ts
Normal file
13
src/components/timezone-datalist.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import timezones from "google-timezones-json";
|
||||||
|
|
||||||
|
export const createTimezoneListEl = () => {
|
||||||
|
const list = document.createElement("datalist");
|
||||||
|
list.id = "timezones";
|
||||||
|
Object.keys(timezones).forEach((key) => {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.value = key;
|
||||||
|
option.innerHTML = timezones[key];
|
||||||
|
list.appendChild(option);
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
import { createCollection } from "home-assistant-js-websocket";
|
import { createCollection, Connection } from "home-assistant-js-websocket";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import { compare } from "../common/string/compare";
|
import { compare } from "../common/string/compare";
|
||||||
import { debounce } from "../common/util/debounce";
|
import { debounce } from "../common/util/debounce";
|
||||||
@ -57,13 +57,13 @@ const subscribeAreaRegistryUpdates = (conn, store) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const subscribeAreaRegistry = (
|
export const subscribeAreaRegistry = (
|
||||||
hass: HomeAssistant,
|
conn: Connection,
|
||||||
onChange: (areas: AreaRegistryEntry[]) => void
|
onChange: (areas: AreaRegistryEntry[]) => void
|
||||||
) =>
|
) =>
|
||||||
createCollection<AreaRegistryEntry[]>(
|
createCollection<AreaRegistryEntry[]>(
|
||||||
"_areaRegistry",
|
"_areaRegistry",
|
||||||
fetchAreaRegistry,
|
fetchAreaRegistry,
|
||||||
subscribeAreaRegistryUpdates,
|
subscribeAreaRegistryUpdates,
|
||||||
hass.connection,
|
conn,
|
||||||
onChange
|
onChange
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import {
|
|||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
export interface AutomationEntity extends HassEntityBase {
|
export interface AutomationEntity extends HassEntityBase {
|
||||||
attributes: HassEntityAttributeBase & {
|
attributes: HassEntityAttributeBase & {
|
||||||
@ -16,3 +17,6 @@ export interface AutomationConfig {
|
|||||||
condition?: any[];
|
condition?: any[];
|
||||||
action: any[];
|
action: any[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteAutomation = (hass: HomeAssistant, id: string) =>
|
||||||
|
hass.callApi("DELETE", `config/automation/config/${id}`);
|
||||||
|
25
src/data/core.ts
Normal file
25
src/data/core.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
import { HassConfig } from "home-assistant-js-websocket";
|
||||||
|
|
||||||
|
export interface ConfigUpdateValues {
|
||||||
|
location_name: string;
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
elevation: number;
|
||||||
|
unit_system: "metric" | "imperial";
|
||||||
|
time_zone: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const saveCoreConfig = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
values: Partial<ConfigUpdateValues>
|
||||||
|
) =>
|
||||||
|
hass.callWS<HassConfig>({
|
||||||
|
type: "config/core/update",
|
||||||
|
...values,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const detectCoreConfig = (hass: HomeAssistant) =>
|
||||||
|
hass.callWS<Partial<ConfigUpdateValues>>({
|
||||||
|
type: "config/core/detect",
|
||||||
|
});
|
@ -1,5 +1,5 @@
|
|||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import { createCollection } from "home-assistant-js-websocket";
|
import { createCollection, Connection } from "home-assistant-js-websocket";
|
||||||
import { debounce } from "../common/util/debounce";
|
import { debounce } from "../common/util/debounce";
|
||||||
|
|
||||||
export interface DeviceRegistryEntry {
|
export interface DeviceRegistryEntry {
|
||||||
@ -50,13 +50,13 @@ const subscribeDeviceRegistryUpdates = (conn, store) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const subscribeDeviceRegistry = (
|
export const subscribeDeviceRegistry = (
|
||||||
hass: HomeAssistant,
|
conn: Connection,
|
||||||
onChange: (devices: DeviceRegistryEntry[]) => void
|
onChange: (devices: DeviceRegistryEntry[]) => void
|
||||||
) =>
|
) =>
|
||||||
createCollection<DeviceRegistryEntry[]>(
|
createCollection<DeviceRegistryEntry[]>(
|
||||||
"_dr",
|
"_dr",
|
||||||
fetchDeviceRegistry,
|
fetchDeviceRegistry,
|
||||||
subscribeDeviceRegistryUpdates,
|
subscribeDeviceRegistryUpdates,
|
||||||
hass.connection,
|
conn,
|
||||||
onChange
|
onChange
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { createCollection } from "home-assistant-js-websocket";
|
import { createCollection, Connection } from "home-assistant-js-websocket";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import computeStateName from "../common/entity/compute_state_name";
|
import computeStateName from "../common/entity/compute_state_name";
|
||||||
import { debounce } from "../common/util/debounce";
|
import { debounce } from "../common/util/debounce";
|
||||||
@ -67,13 +67,13 @@ const subscribeEntityRegistryUpdates = (conn, store) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const subscribeEntityRegistry = (
|
export const subscribeEntityRegistry = (
|
||||||
hass: HomeAssistant,
|
conn: Connection,
|
||||||
onChange: (entities: EntityRegistryEntry[]) => void
|
onChange: (entities: EntityRegistryEntry[]) => void
|
||||||
) =>
|
) =>
|
||||||
createCollection<EntityRegistryEntry[]>(
|
createCollection<EntityRegistryEntry[]>(
|
||||||
"_entityRegistry",
|
"_entityRegistry",
|
||||||
fetchEntityRegistry,
|
fetchEntityRegistry,
|
||||||
subscribeEntityRegistryUpdates,
|
subscribeEntityRegistryUpdates,
|
||||||
hass.connection,
|
conn,
|
||||||
onChange
|
onChange
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { handleFetchPromise } from "../util/hass-call-api";
|
import { handleFetchPromise } from "../util/hass-call-api";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
|
// tslint:disable-next-line: no-empty-interface
|
||||||
|
export interface OnboardingCoreConfigStepResponse {}
|
||||||
|
|
||||||
export interface OnboardingUserStepResponse {
|
export interface OnboardingUserStepResponse {
|
||||||
auth_code: string;
|
auth_code: string;
|
||||||
}
|
}
|
||||||
@ -11,6 +14,7 @@ export interface OnboardingIntegrationStepResponse {
|
|||||||
|
|
||||||
export interface OnboardingResponses {
|
export interface OnboardingResponses {
|
||||||
user: OnboardingUserStepResponse;
|
user: OnboardingUserStepResponse;
|
||||||
|
core_config: OnboardingCoreConfigStepResponse;
|
||||||
integration: OnboardingIntegrationStepResponse;
|
integration: OnboardingIntegrationStepResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +43,12 @@ export const onboardUserStep = (params: {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const onboardCoreConfigStep = (hass: HomeAssistant) =>
|
||||||
|
hass.callApi<OnboardingCoreConfigStepResponse>(
|
||||||
|
"POST",
|
||||||
|
"onboarding/core_config"
|
||||||
|
);
|
||||||
|
|
||||||
export const onboardIntegrationStep = (
|
export const onboardIntegrationStep = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
params: { client_id: string }
|
params: { client_id: string }
|
||||||
|
@ -12,3 +12,6 @@ export const triggerScript = (
|
|||||||
entityId: string,
|
entityId: string,
|
||||||
variables?: {}
|
variables?: {}
|
||||||
) => hass.callService("script", computeObjectId(entityId), variables);
|
) => hass.callService("script", computeObjectId(entityId), variables);
|
||||||
|
|
||||||
|
export const deleteScript = (hass: HomeAssistant, objectId: string) =>
|
||||||
|
hass.callApi("DELETE", `config/script/config/${objectId}`);
|
||||||
|
@ -219,15 +219,18 @@ class ConfigFlowDialog extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _fetchDevices(configEntryId) {
|
private async _fetchDevices(configEntryId) {
|
||||||
this._unsubDevices = subscribeDeviceRegistry(this.hass, (devices) => {
|
this._unsubDevices = subscribeDeviceRegistry(
|
||||||
this._devices = devices.filter((device) =>
|
this.hass.connection,
|
||||||
device.config_entries.includes(configEntryId)
|
(devices) => {
|
||||||
);
|
this._devices = devices.filter((device) =>
|
||||||
});
|
device.config_entries.includes(configEntryId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _fetchAreas() {
|
private async _fetchAreas() {
|
||||||
this._unsubAreas = subscribeAreaRegistry(this.hass, (areas) => {
|
this._unsubAreas = subscribeAreaRegistry(this.hass.connection, (areas) => {
|
||||||
this._areas = areas;
|
this._areas = areas;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -16,4 +16,5 @@ export const demoConfig: HassConfig = {
|
|||||||
config_dir: "/config",
|
config_dir: "/config",
|
||||||
version: "DEMO",
|
version: "DEMO",
|
||||||
whitelist_external_dirs: [],
|
whitelist_external_dirs: [],
|
||||||
|
config_source: "storage",
|
||||||
};
|
};
|
||||||
|
@ -1,37 +1,37 @@
|
|||||||
import "@polymer/paper-spinner/paper-spinner-lite";
|
import "@polymer/paper-spinner/paper-spinner-lite";
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
|
|
||||||
import {
|
import { LitElement, html, CSSResult, css, property } from "lit-element";
|
||||||
LitElement,
|
|
||||||
PropertyDeclarations,
|
|
||||||
html,
|
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
|
||||||
import { removeInitSkeleton } from "../util/init-skeleton";
|
import { removeInitSkeleton } from "../util/init-skeleton";
|
||||||
|
|
||||||
class HaInitPage extends LitElement {
|
class HaInitPage extends LitElement {
|
||||||
public error?: boolean;
|
@property({ type: Boolean }) public error = false;
|
||||||
|
|
||||||
static get properties(): PropertyDeclarations {
|
|
||||||
return {
|
|
||||||
error: {
|
|
||||||
type: Boolean,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
return html`
|
||||||
<div>
|
<div>
|
||||||
<img src="/static/icons/favicon-192x192.png" height="192" />
|
<img src="/static/icons/favicon-192x192.png" height="192" />
|
||||||
<paper-spinner-lite .active=${!this.error}></paper-spinner-lite>
|
|
||||||
${this.error
|
${this.error
|
||||||
? html`
|
? html`
|
||||||
Unable to connect to Home Assistant.
|
<p>Unable to connect to Home Assistant.</p>
|
||||||
<mwc-button @click=${this._retry}>Retry</mwc-button>
|
<mwc-button @click=${this._retry}>Retry</mwc-button>
|
||||||
|
${location.host.includes("ui.nabu.casa")
|
||||||
|
? html`
|
||||||
|
<p>
|
||||||
|
It is possible that you are seeing this screen because
|
||||||
|
your Home Assistant is not currently connected. You can
|
||||||
|
ask it to come online via
|
||||||
|
<a href="https://remote.nabucasa.com/"
|
||||||
|
>the Remote UI portal</a
|
||||||
|
>.
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
`
|
`
|
||||||
: "Loading data"}
|
: html`
|
||||||
|
<paper-spinner-lite active></paper-spinner-lite>
|
||||||
|
<p>Loading data</p>
|
||||||
|
`}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,13 @@ class HaInitPage extends LitElement {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
paper-spinner-lite {
|
paper-spinner-lite {
|
||||||
margin-bottom: 10px;
|
margin-top: 9px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
max-width: 350px;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
createConnection,
|
createConnection,
|
||||||
genClientId,
|
genClientId,
|
||||||
Auth,
|
Auth,
|
||||||
|
subscribeConfig,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
||||||
import {
|
import {
|
||||||
@ -24,6 +25,8 @@ import "./onboarding-create-user";
|
|||||||
import "./onboarding-loading";
|
import "./onboarding-loading";
|
||||||
import { hassUrl } from "../data/auth";
|
import { hassUrl } from "../data/auth";
|
||||||
import { HassElement } from "../state/hass-element";
|
import { HassElement } from "../state/hass-element";
|
||||||
|
import { subscribeOne } from "../common/util/subscribe-one";
|
||||||
|
import { subscribeUser } from "../data/ws-user";
|
||||||
|
|
||||||
interface OnboardingEvent<T extends ValidOnboardingStep> {
|
interface OnboardingEvent<T extends ValidOnboardingStep> {
|
||||||
type: T;
|
type: T;
|
||||||
@ -61,6 +64,13 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
|
|||||||
.language=${this.language}
|
.language=${this.language}
|
||||||
></onboarding-create-user>
|
></onboarding-create-user>
|
||||||
`;
|
`;
|
||||||
|
} else if (step.step === "core_config") {
|
||||||
|
return html`
|
||||||
|
<onboarding-core-config
|
||||||
|
.hass=${this.hass}
|
||||||
|
.onboardingLocalize=${this.localize}
|
||||||
|
></onboarding-core-config>
|
||||||
|
`;
|
||||||
} else if (step.step === "integration") {
|
} else if (step.step === "integration") {
|
||||||
return html`
|
return html`
|
||||||
<onboarding-integrations
|
<onboarding-integrations
|
||||||
@ -75,6 +85,7 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
|
|||||||
super.firstUpdated(changedProps);
|
super.firstUpdated(changedProps);
|
||||||
this._fetchOnboardingSteps();
|
this._fetchOnboardingSteps();
|
||||||
import("./onboarding-integrations");
|
import("./onboarding-integrations");
|
||||||
|
import("./onboarding-core-config");
|
||||||
registerServiceWorker(false);
|
registerServiceWorker(false);
|
||||||
this.addEventListener("onboarding-step", (ev) => this._handleStepDone(ev));
|
this.addEventListener("onboarding-step", (ev) => this._handleStepDone(ev));
|
||||||
}
|
}
|
||||||
@ -106,6 +117,7 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
|
|||||||
const auth = await getAuth({
|
const auth = await getAuth({
|
||||||
hassUrl,
|
hassUrl,
|
||||||
});
|
});
|
||||||
|
history.replaceState(null, "", location.pathname);
|
||||||
await this._connectHass(auth);
|
await this._connectHass(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +150,8 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
|
|||||||
} finally {
|
} finally {
|
||||||
this._loading = false;
|
this._loading = false;
|
||||||
}
|
}
|
||||||
|
} else if (stepResult.type === "core_config") {
|
||||||
|
// We do nothing
|
||||||
} else if (stepResult.type === "integration") {
|
} else if (stepResult.type === "integration") {
|
||||||
const result = stepResult.result as OnboardingResponses["integration"];
|
const result = stepResult.result as OnboardingResponses["integration"];
|
||||||
this._loading = true;
|
this._loading = true;
|
||||||
@ -161,6 +175,12 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
|
|||||||
|
|
||||||
private async _connectHass(auth: Auth) {
|
private async _connectHass(auth: Auth) {
|
||||||
const conn = await createConnection({ auth });
|
const conn = await createConnection({ auth });
|
||||||
|
// Make sure config and user info is loaded before we initialize.
|
||||||
|
// It is needed for the core config step.
|
||||||
|
await Promise.all([
|
||||||
|
subscribeOne(conn, subscribeConfig),
|
||||||
|
subscribeOne(conn, subscribeUser),
|
||||||
|
]);
|
||||||
this.initializeHass(auth, conn);
|
this.initializeHass(auth, conn);
|
||||||
// Load config strings for integrations
|
// Load config strings for integrations
|
||||||
(this as any)._loadFragmentTranslations(this.hass!.language, "config");
|
(this as any)._loadFragmentTranslations(this.hass!.language, "config");
|
||||||
|
320
src/onboarding/onboarding-core-config.ts
Normal file
320
src/onboarding/onboarding-core-config.ts
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
customElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
html,
|
||||||
|
CSSResult,
|
||||||
|
css,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-radio-group/paper-radio-group";
|
||||||
|
import "@polymer/paper-radio-button/paper-radio-button";
|
||||||
|
// tslint:disable-next-line: no-duplicate-imports
|
||||||
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
import {
|
||||||
|
ConfigUpdateValues,
|
||||||
|
detectCoreConfig,
|
||||||
|
saveCoreConfig,
|
||||||
|
} from "../data/core";
|
||||||
|
import { UNIT_C } from "../common/const";
|
||||||
|
import { PolymerChangedEvent } from "../polymer-types";
|
||||||
|
import { onboardCoreConfigStep } from "../data/onboarding";
|
||||||
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { LocalizeFunc } from "../common/translations/localize";
|
||||||
|
import { createTimezoneListEl } from "../components/timezone-datalist";
|
||||||
|
|
||||||
|
@customElement("onboarding-core-config")
|
||||||
|
class OnboardingCoreConfig extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
@property() public onboardingLocalize!: LocalizeFunc;
|
||||||
|
|
||||||
|
@property() private _working = false;
|
||||||
|
|
||||||
|
@property() private _name!: ConfigUpdateValues["location_name"];
|
||||||
|
@property() private _latitude!: string;
|
||||||
|
@property() private _longitude!: string;
|
||||||
|
@property() private _elevation!: string;
|
||||||
|
@property() private _unitSystem!: ConfigUpdateValues["unit_system"];
|
||||||
|
@property() private _timeZone!: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html`
|
||||||
|
<p>
|
||||||
|
${this.onboardingLocalize(
|
||||||
|
"ui.panel.page-onboarding.core-config.intro",
|
||||||
|
"name",
|
||||||
|
this.hass.user!.name
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<paper-input
|
||||||
|
.label=${this.onboardingLocalize(
|
||||||
|
"ui.panel.page-onboarding.core-config.location_name"
|
||||||
|
)}
|
||||||
|
name="name"
|
||||||
|
.disabled=${this._working}
|
||||||
|
.value=${this._nameValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
|
||||||
|
<div class="middle-text">
|
||||||
|
<p>
|
||||||
|
${this.onboardingLocalize(
|
||||||
|
"ui.panel.page-onboarding.core-config.intro_location"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div>
|
||||||
|
${this.onboardingLocalize(
|
||||||
|
"ui.panel.page-onboarding.core-config.intro_location_detect"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<mwc-button @click=${this._detect}>
|
||||||
|
${this.onboardingLocalize(
|
||||||
|
"ui.panel.page-onboarding.core-config.button_detect"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.latitude"
|
||||||
|
)}
|
||||||
|
name="latitude"
|
||||||
|
.disabled=${this._working}
|
||||||
|
.value=${this._latitudeValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.longitude"
|
||||||
|
)}
|
||||||
|
name="longitude"
|
||||||
|
.disabled=${this._working}
|
||||||
|
.value=${this._longitudeValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.time_zone"
|
||||||
|
)}
|
||||||
|
name="timeZone"
|
||||||
|
list="timezones"
|
||||||
|
.disabled=${this._working}
|
||||||
|
.value=${this._timeZoneValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.elevation"
|
||||||
|
)}
|
||||||
|
name="elevation"
|
||||||
|
type="number"
|
||||||
|
.disabled=${this._working}
|
||||||
|
.value=${this._elevationValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
>
|
||||||
|
<span slot="suffix">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.elevation_meters"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</paper-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="flex">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<paper-radio-group class="flex" .selected=${this._unitSystemValue}>
|
||||||
|
<paper-radio-button name="metric" .disabled=${this._working}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system_metric"
|
||||||
|
)}
|
||||||
|
<div class="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.metric_example"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</paper-radio-button>
|
||||||
|
<paper-radio-button name="imperial" .disabled=${this._working}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system_imperial"
|
||||||
|
)}
|
||||||
|
<div class="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.imperial_example"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</paper-radio-button>
|
||||||
|
</paper-radio-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<mwc-button @click=${this._save} .disabled=${this._working}>
|
||||||
|
${this.onboardingLocalize(
|
||||||
|
"ui.panel.page-onboarding.core-config.finish"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
setTimeout(
|
||||||
|
() => this.shadowRoot!.querySelector("paper-input")!.focus(),
|
||||||
|
100
|
||||||
|
);
|
||||||
|
this.addEventListener("keypress", (ev) => {
|
||||||
|
if (ev.keyCode === 13) {
|
||||||
|
this._save(ev);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const input = this.shadowRoot!.querySelector(
|
||||||
|
"[name=timeZone]"
|
||||||
|
) as PaperInputElement;
|
||||||
|
input.inputElement.appendChild(createTimezoneListEl());
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _nameValue() {
|
||||||
|
return this._name !== undefined
|
||||||
|
? this._name
|
||||||
|
: this.onboardingLocalize(
|
||||||
|
"ui.panel.page-onboarding.core-config.location_name_default"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _latitudeValue() {
|
||||||
|
return this._latitude !== undefined
|
||||||
|
? this._latitude
|
||||||
|
: this.hass.config.latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _longitudeValue() {
|
||||||
|
return this._longitude !== undefined
|
||||||
|
? this._longitude
|
||||||
|
: this.hass.config.longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _elevationValue() {
|
||||||
|
return this._elevation !== undefined
|
||||||
|
? this._elevation
|
||||||
|
: this.hass.config.elevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _timeZoneValue() {
|
||||||
|
return this._timeZone !== undefined
|
||||||
|
? this._timeZone
|
||||||
|
: this.hass.config.time_zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _unitSystemValue() {
|
||||||
|
return this._unitSystem !== undefined
|
||||||
|
? this._unitSystem
|
||||||
|
: this.hass.config.unit_system.temperature === UNIT_C
|
||||||
|
? "metric"
|
||||||
|
: "imperial";
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleChange(ev: PolymerChangedEvent<string>) {
|
||||||
|
const target = ev.currentTarget as PaperInputElement;
|
||||||
|
this[`_${target.name}`] = target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _detect() {
|
||||||
|
this._working = true;
|
||||||
|
try {
|
||||||
|
const values = await detectCoreConfig(this.hass);
|
||||||
|
for (const key in values) {
|
||||||
|
if (key === "unit_system") {
|
||||||
|
this._unitSystem = values[key]!;
|
||||||
|
} else if (key === "time_zone") {
|
||||||
|
this._timeZone = values[key]!;
|
||||||
|
} else {
|
||||||
|
this[`_${key}`] = values[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
alert(`Failed to detect location information: ${err.message}`);
|
||||||
|
} finally {
|
||||||
|
this._working = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _save(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this._working = true;
|
||||||
|
try {
|
||||||
|
await saveCoreConfig(this.hass, {
|
||||||
|
location_name: this._nameValue,
|
||||||
|
latitude: Number(this._latitudeValue),
|
||||||
|
longitude: Number(this._longitudeValue),
|
||||||
|
elevation: Number(this._elevationValue),
|
||||||
|
unit_system: this._unitSystemValue,
|
||||||
|
time_zone: this._timeZoneValue,
|
||||||
|
});
|
||||||
|
const result = await onboardCoreConfigStep(this.hass);
|
||||||
|
fireEvent(this, "onboarding-step", {
|
||||||
|
type: "core_config",
|
||||||
|
result,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this._working = false;
|
||||||
|
alert("FAIL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 0 -8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.middle-text {
|
||||||
|
margin: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row > * {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
margin-top: 16px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"onboarding-core-config": OnboardingCoreConfig;
|
||||||
|
}
|
||||||
|
}
|
@ -122,9 +122,12 @@ class HaConfigAreaRegistry extends LitElement {
|
|||||||
protected updated(changedProps) {
|
protected updated(changedProps) {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
if (!this._unsubAreas) {
|
if (!this._unsubAreas) {
|
||||||
this._unsubAreas = subscribeAreaRegistry(this.hass, (areas) => {
|
this._unsubAreas = subscribeAreaRegistry(
|
||||||
this._areas = areas;
|
this.hass.connection,
|
||||||
});
|
(areas) => {
|
||||||
|
this._areas = areas;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,11 @@ import computeStateName from "../../../common/entity/compute_state_name";
|
|||||||
|
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { AutomationEntity, AutomationConfig } from "../../../data/automation";
|
import {
|
||||||
|
AutomationEntity,
|
||||||
|
AutomationConfig,
|
||||||
|
deleteAutomation,
|
||||||
|
} from "../../../data/automation";
|
||||||
import { navigate } from "../../../common/navigate";
|
import { navigate } from "../../../common/navigate";
|
||||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||||
|
|
||||||
@ -33,8 +37,8 @@ function AutomationEditor(mountEl, props, mergeEl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HaAutomationEditor extends LitElement {
|
class HaAutomationEditor extends LitElement {
|
||||||
public hass?: HomeAssistant;
|
public hass!: HomeAssistant;
|
||||||
public automation?: AutomationEntity;
|
public automation!: AutomationEntity;
|
||||||
public isWide?: boolean;
|
public isWide?: boolean;
|
||||||
public creatingNew?: boolean;
|
public creatingNew?: boolean;
|
||||||
private _config?: AutomationConfig;
|
private _config?: AutomationConfig;
|
||||||
@ -85,6 +89,14 @@ class HaAutomationEditor extends LitElement {
|
|||||||
"ui.panel.config.automation.editor.default_name"
|
"ui.panel.config.automation.editor.default_name"
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
${this.creatingNew
|
||||||
|
? ""
|
||||||
|
: html`
|
||||||
|
<paper-icon-button
|
||||||
|
icon="hass:delete"
|
||||||
|
@click=${this._delete}
|
||||||
|
></paper-icon-button>
|
||||||
|
`}
|
||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
</app-header>
|
</app-header>
|
||||||
|
|
||||||
@ -135,18 +147,34 @@ class HaAutomationEditor extends LitElement {
|
|||||||
"GET",
|
"GET",
|
||||||
`config/automation/config/${this.automation.attributes.id}`
|
`config/automation/config/${this.automation.attributes.id}`
|
||||||
)
|
)
|
||||||
.then((config) => {
|
.then(
|
||||||
// Normalize data: ensure trigger, action and condition are lists
|
(config) => {
|
||||||
// Happens when people copy paste their automations into the config
|
// Normalize data: ensure trigger, action and condition are lists
|
||||||
for (const key of ["trigger", "condition", "action"]) {
|
// Happens when people copy paste their automations into the config
|
||||||
const value = config[key];
|
for (const key of ["trigger", "condition", "action"]) {
|
||||||
if (value && !Array.isArray(value)) {
|
const value = config[key];
|
||||||
config[key] = [value];
|
if (value && !Array.isArray(value)) {
|
||||||
|
config[key] = [value];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this._dirty = false;
|
||||||
|
this._config = config;
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
alert(
|
||||||
|
resp.status_code === 404
|
||||||
|
? this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.load_error_not_editable"
|
||||||
|
)
|
||||||
|
: this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.load_error_unknown",
|
||||||
|
"err_no",
|
||||||
|
resp.status_code
|
||||||
|
)
|
||||||
|
);
|
||||||
|
history.back();
|
||||||
}
|
}
|
||||||
this._dirty = false;
|
);
|
||||||
this._config = config;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProps.has("creatingNew") && this.creatingNew && this.hass) {
|
if (changedProps.has("creatingNew") && this.creatingNew && this.hass) {
|
||||||
@ -184,7 +212,6 @@ class HaAutomationEditor extends LitElement {
|
|||||||
this._config = config;
|
this._config = config;
|
||||||
this._errors = undefined;
|
this._errors = undefined;
|
||||||
this._dirty = true;
|
this._dirty = true;
|
||||||
// this._updateComponent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _backTapped(): void {
|
private _backTapped(): void {
|
||||||
@ -199,10 +226,18 @@ class HaAutomationEditor extends LitElement {
|
|||||||
history.back();
|
history.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _delete() {
|
||||||
|
if (!confirm("Are you sure you want to delete this automation?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await deleteAutomation(this.hass, this.automation.attributes.id!);
|
||||||
|
history.back();
|
||||||
|
}
|
||||||
|
|
||||||
private _saveAutomation(): void {
|
private _saveAutomation(): void {
|
||||||
const id = this.creatingNew
|
const id = this.creatingNew
|
||||||
? "" + Date.now()
|
? "" + Date.now()
|
||||||
: this.automation!.attributes.id;
|
: this.automation.attributes.id;
|
||||||
this.hass!.callApi(
|
this.hass!.callApi(
|
||||||
"POST",
|
"POST",
|
||||||
"config/automation/config/" + id,
|
"config/automation/config/" + id,
|
||||||
|
@ -26,6 +26,7 @@ import { HomeAssistant } from "../../../types";
|
|||||||
import { AutomationEntity } from "../../../data/automation";
|
import { AutomationEntity } from "../../../data/automation";
|
||||||
import format_date_time from "../../../common/datetime/format_date_time";
|
import format_date_time from "../../../common/datetime/format_date_time";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import { repeat } from "lit-html/directives/repeat";
|
||||||
|
|
||||||
@customElement("ha-automation-picker")
|
@customElement("ha-automation-picker")
|
||||||
class HaAutomationPicker extends LitElement {
|
class HaAutomationPicker extends LitElement {
|
||||||
@ -73,7 +74,9 @@ class HaAutomationPicker extends LitElement {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: this.automations.map(
|
: repeat(
|
||||||
|
this.automations,
|
||||||
|
(automation) => automation.entity_id,
|
||||||
(automation) => html`
|
(automation) => html`
|
||||||
|
|
||||||
<div class='automation'>
|
<div class='automation'>
|
||||||
|
255
src/panels/config/core/ha-config-core-form.ts
Normal file
255
src/panels/config/core/ha-config-core-form.ts
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
customElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
html,
|
||||||
|
CSSResult,
|
||||||
|
css,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-radio-group/paper-radio-group";
|
||||||
|
import "@polymer/paper-radio-button/paper-radio-button";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import "../../../components/ha-card";
|
||||||
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
|
// tslint:disable-next-line: no-duplicate-imports
|
||||||
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
|
import { UNIT_C } from "../../../common/const";
|
||||||
|
import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core";
|
||||||
|
import { createTimezoneListEl } from "../../../components/timezone-datalist";
|
||||||
|
|
||||||
|
@customElement("ha-config-core-form")
|
||||||
|
class ConfigCoreForm extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() private _working = false;
|
||||||
|
|
||||||
|
@property() private _latitude!: string;
|
||||||
|
@property() private _longitude!: string;
|
||||||
|
@property() private _elevation!: string;
|
||||||
|
@property() private _unitSystem!: ConfigUpdateValues["unit_system"];
|
||||||
|
@property() private _timeZone!: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
const isStorage = this.hass.config.config_source === "storage";
|
||||||
|
const disabled = this._working || !isStorage;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-card
|
||||||
|
.header=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.form.heading"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div class="card-content">
|
||||||
|
${!isStorage
|
||||||
|
? html`
|
||||||
|
<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.edit_requires_storage"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.latitude"
|
||||||
|
)}
|
||||||
|
name="latitude"
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._latitudeValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.longitude"
|
||||||
|
)}
|
||||||
|
name="longitude"
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._longitudeValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="flex">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.time_zone"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.time_zone"
|
||||||
|
)}
|
||||||
|
name="timeZone"
|
||||||
|
list="timezones"
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._timeZoneValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="flex">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.elevation"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.elevation"
|
||||||
|
)}
|
||||||
|
name="elevation"
|
||||||
|
type="number"
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._elevationValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
>
|
||||||
|
<span slot="suffix">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.elevation_meters"
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</paper-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="flex">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<paper-radio-group class="flex" .selected=${this._unitSystemValue}>
|
||||||
|
<paper-radio-button name="metric" .disabled=${disabled}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system_metric"
|
||||||
|
)}
|
||||||
|
<div class="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.metric_example"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</paper-radio-button>
|
||||||
|
<paper-radio-button name="imperial" .disabled=${disabled}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.unit_system_imperial"
|
||||||
|
)}
|
||||||
|
<div class="secondary">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.imperial_example"
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</paper-radio-button>
|
||||||
|
</paper-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-actions">
|
||||||
|
<mwc-button @click=${this._save} .disabled=${disabled}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.save_button"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(changedProps) {
|
||||||
|
super.firstUpdated(changedProps);
|
||||||
|
const input = this.shadowRoot!.querySelector(
|
||||||
|
"[name=timeZone]"
|
||||||
|
) as PaperInputElement;
|
||||||
|
input.inputElement.appendChild(createTimezoneListEl());
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _latitudeValue() {
|
||||||
|
return this._latitude !== undefined
|
||||||
|
? this._latitude
|
||||||
|
: this.hass.config.latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _longitudeValue() {
|
||||||
|
return this._longitude !== undefined
|
||||||
|
? this._longitude
|
||||||
|
: this.hass.config.longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _elevationValue() {
|
||||||
|
return this._elevation !== undefined
|
||||||
|
? this._elevation
|
||||||
|
: this.hass.config.elevation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _timeZoneValue() {
|
||||||
|
return this._timeZone !== undefined
|
||||||
|
? this._timeZone
|
||||||
|
: this.hass.config.time_zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _unitSystemValue() {
|
||||||
|
return this._unitSystem !== undefined
|
||||||
|
? this._unitSystem
|
||||||
|
: this.hass.config.unit_system.temperature === UNIT_C
|
||||||
|
? "metric"
|
||||||
|
: "imperial";
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleChange(ev: PolymerChangedEvent<string>) {
|
||||||
|
const target = ev.currentTarget as PaperInputElement;
|
||||||
|
this[`_${target.name}`] = target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _save() {
|
||||||
|
this._working = true;
|
||||||
|
try {
|
||||||
|
await saveCoreConfig(this.hass, {
|
||||||
|
latitude: Number(this._latitudeValue),
|
||||||
|
longitude: Number(this._longitudeValue),
|
||||||
|
elevation: Number(this._elevationValue),
|
||||||
|
unit_system: this._unitSystemValue,
|
||||||
|
time_zone: this._timeZoneValue,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
alert("FAIL");
|
||||||
|
} finally {
|
||||||
|
this._working = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 0 -8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary {
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row > * {
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-config-core-form": ConfigCoreForm;
|
||||||
|
}
|
||||||
|
}
|
94
src/panels/config/core/ha-config-name-form.ts
Normal file
94
src/panels/config/core/ha-config-name-form.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import {
|
||||||
|
LitElement,
|
||||||
|
customElement,
|
||||||
|
property,
|
||||||
|
TemplateResult,
|
||||||
|
html,
|
||||||
|
} from "lit-element";
|
||||||
|
import "@material/mwc-button/mwc-button";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-radio-group/paper-radio-group";
|
||||||
|
import "@polymer/paper-radio-button/paper-radio-button";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import "../../../components/ha-card";
|
||||||
|
import { PolymerChangedEvent } from "../../../polymer-types";
|
||||||
|
// tslint:disable-next-line: no-duplicate-imports
|
||||||
|
import { PaperInputElement } from "@polymer/paper-input/paper-input";
|
||||||
|
import { ConfigUpdateValues, saveCoreConfig } from "../../../data/core";
|
||||||
|
|
||||||
|
@customElement("ha-config-name-form")
|
||||||
|
class ConfigNameForm extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() private _working = false;
|
||||||
|
|
||||||
|
@property() private _name!: ConfigUpdateValues["location_name"];
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
const isStorage = this.hass.config.config_source === "storage";
|
||||||
|
const disabled = this._working || !isStorage;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-card>
|
||||||
|
<div class="card-content">
|
||||||
|
${!isStorage
|
||||||
|
? html`
|
||||||
|
<p>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.edit_requires_storage"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
<paper-input
|
||||||
|
class="flex"
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.location_name"
|
||||||
|
)}
|
||||||
|
name="name"
|
||||||
|
.disabled=${disabled}
|
||||||
|
.value=${this._nameValue}
|
||||||
|
@value-changed=${this._handleChange}
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
<div class="card-actions">
|
||||||
|
<mwc-button @click=${this._save} .disabled=${disabled}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.config.core.section.core.core_config.save_button"
|
||||||
|
)}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
</ha-card>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _nameValue() {
|
||||||
|
return this._name !== undefined
|
||||||
|
? this._name
|
||||||
|
: this.hass.config.location_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleChange(ev: PolymerChangedEvent<string>) {
|
||||||
|
const target = ev.currentTarget as PaperInputElement;
|
||||||
|
this[`_${target.name}`] = target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _save() {
|
||||||
|
this._working = true;
|
||||||
|
try {
|
||||||
|
await saveCoreConfig(this.hass, {
|
||||||
|
location_name: this._nameValue,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
alert("FAIL");
|
||||||
|
} finally {
|
||||||
|
this._working = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-config-name-form": ConfigNameForm;
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,9 @@ import "../ha-config-section";
|
|||||||
import isComponentLoaded from "../../../common/config/is_component_loaded";
|
import isComponentLoaded from "../../../common/config/is_component_loaded";
|
||||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||||
|
|
||||||
|
import "./ha-config-name-form";
|
||||||
|
import "./ha-config-core-form";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @appliesMixin LocalizeMixin
|
* @appliesMixin LocalizeMixin
|
||||||
*/
|
*/
|
||||||
@ -57,6 +60,9 @@ class HaConfigSectionCore extends LocalizeMixin(PolymerElement) {
|
|||||||
>[[localize('ui.panel.config.core.section.core.introduction')]]</span
|
>[[localize('ui.panel.config.core.section.core.introduction')]]</span
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<ha-config-name-form hass="[[hass]]"></ha-config-name-form>
|
||||||
|
<ha-config-core-form hass="[[hass]]"></ha-config-core-form>
|
||||||
|
|
||||||
<ha-card
|
<ha-card
|
||||||
header="[[localize('ui.panel.config.core.section.core.validation.heading')]]"
|
header="[[localize('ui.panel.config.core.section.core.validation.heading')]]"
|
||||||
>
|
>
|
||||||
|
@ -118,11 +118,14 @@ class HaConfigEntityRegistry extends LitElement {
|
|||||||
protected updated(changedProps) {
|
protected updated(changedProps) {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
if (!this._unsubEntities) {
|
if (!this._unsubEntities) {
|
||||||
this._unsubEntities = subscribeEntityRegistry(this.hass, (entities) => {
|
this._unsubEntities = subscribeEntityRegistry(
|
||||||
this._entities = entities.sort((ent1, ent2) =>
|
this.hass.connection,
|
||||||
compare(ent1.entity_id, ent2.entity_id)
|
(entities) => {
|
||||||
);
|
this._entities = entities.sort((ent1, ent2) =>
|
||||||
});
|
compare(ent1.entity_id, ent2.entity_id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ class HaConfigIntegrations extends NavigateMixin(PolymerElement) {
|
|||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
this._loadData();
|
this._loadData();
|
||||||
this._unsubAreas = subscribeAreaRegistry(this.hass, (areas) => {
|
this._unsubAreas = subscribeAreaRegistry(this.hass.connection, (areas) => {
|
||||||
this._areas = areas;
|
this._areas = areas;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import NavigateMixin from "../../../mixins/navigate-mixin";
|
|||||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||||
|
|
||||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||||
|
import { deleteScript } from "../../../data/script";
|
||||||
|
|
||||||
function ScriptEditor(mountEl, props, mergeEl) {
|
function ScriptEditor(mountEl, props, mergeEl) {
|
||||||
return render(h(Script, props), mountEl, mergeEl);
|
return render(h(Script, props), mountEl, mergeEl);
|
||||||
@ -99,7 +100,13 @@ class HaScriptEditor extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
|||||||
<ha-paper-icon-button-arrow-prev
|
<ha-paper-icon-button-arrow-prev
|
||||||
on-click="backTapped"
|
on-click="backTapped"
|
||||||
></ha-paper-icon-button-arrow-prev>
|
></ha-paper-icon-button-arrow-prev>
|
||||||
<div main-title="">Script [[computeName(script)]]</div>
|
<div main-title>Script [[computeName(script)]]</div>
|
||||||
|
<template is="dom-if" if="[[!creatingNew]]">
|
||||||
|
<paper-icon-button
|
||||||
|
icon="hass:delete"
|
||||||
|
on-click="_delete"
|
||||||
|
></paper-icon-button>
|
||||||
|
</template>
|
||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
</app-header>
|
</app-header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
@ -273,6 +280,14 @@ class HaScriptEditor extends LocalizeMixin(NavigateMixin(PolymerElement)) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _delete() {
|
||||||
|
if (!confirm("Are you sure you want to delete this script?")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await deleteScript(this.hass, computeObjectId(this.script.entity_id));
|
||||||
|
history.back();
|
||||||
|
}
|
||||||
|
|
||||||
saveScript() {
|
saveScript() {
|
||||||
var id = this.creatingNew
|
var id = this.creatingNew
|
||||||
? "" + Date.now()
|
? "" + Date.now()
|
||||||
|
@ -25,6 +25,7 @@ import { haStyle } from "../../../resources/styles";
|
|||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { triggerScript } from "../../../data/script";
|
import { triggerScript } from "../../../data/script";
|
||||||
import { showToast } from "../../../util/toast";
|
import { showToast } from "../../../util/toast";
|
||||||
|
import { repeat } from "lit-html/directives/repeat";
|
||||||
|
|
||||||
@customElement("ha-script-picker")
|
@customElement("ha-script-picker")
|
||||||
class HaScriptPicker extends LitElement {
|
class HaScriptPicker extends LitElement {
|
||||||
@ -56,7 +57,9 @@ class HaScriptPicker extends LitElement {
|
|||||||
<p>We couldn't find any scripts.</p>
|
<p>We couldn't find any scripts.</p>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: this.scripts.map(
|
: repeat(
|
||||||
|
this.scripts,
|
||||||
|
(script) => script.entity_id,
|
||||||
(script) => html`
|
(script) => html`
|
||||||
<div class="script">
|
<div class="script">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
|
@ -90,9 +90,12 @@ class ZHADeviceCard extends LitElement {
|
|||||||
this._userGivenName = this.device!.user_given_name;
|
this._userGivenName = this.device!.user_given_name;
|
||||||
}
|
}
|
||||||
if (!this._unsubAreas) {
|
if (!this._unsubAreas) {
|
||||||
this._unsubAreas = subscribeAreaRegistry(this.hass, (areas) => {
|
this._unsubAreas = subscribeAreaRegistry(
|
||||||
this._areas = areas;
|
this.hass.connection,
|
||||||
});
|
(areas) => {
|
||||||
|
this._areas = areas;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
super.update(changedProperties);
|
super.update(changedProperties);
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,10 @@ export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-actions a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
mwc-button {
|
mwc-button {
|
||||||
margin-left: -8px;
|
margin-left: -8px;
|
||||||
}
|
}
|
||||||
|
@ -352,15 +352,15 @@ export const generateLovelaceConfig = async (
|
|||||||
// so that we don't serve up stale data after changing areas.
|
// so that we don't serve up stale data after changing areas.
|
||||||
if (!subscribedRegistries) {
|
if (!subscribedRegistries) {
|
||||||
subscribedRegistries = true;
|
subscribedRegistries = true;
|
||||||
subscribeAreaRegistry(hass, () => undefined);
|
subscribeAreaRegistry(hass.connection, () => undefined);
|
||||||
subscribeDeviceRegistry(hass, () => undefined);
|
subscribeDeviceRegistry(hass.connection, () => undefined);
|
||||||
subscribeEntityRegistry(hass, () => undefined);
|
subscribeEntityRegistry(hass.connection, () => undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [areas, devices, entities] = await Promise.all([
|
const [areas, devices, entities] = await Promise.all([
|
||||||
subscribeOne(hass, subscribeAreaRegistry),
|
subscribeOne(hass.connection, subscribeAreaRegistry),
|
||||||
subscribeOne(hass, subscribeDeviceRegistry),
|
subscribeOne(hass.connection, subscribeDeviceRegistry),
|
||||||
subscribeOne(hass, subscribeEntityRegistry),
|
subscribeOne(hass.connection, subscribeEntityRegistry),
|
||||||
]);
|
]);
|
||||||
const registries = { areas, devices, entities };
|
const registries = { areas, devices, entities };
|
||||||
|
|
||||||
|
@ -310,6 +310,9 @@ class HUIRoot extends LitElement {
|
|||||||
ha-app-layout {
|
ha-app-layout {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
|
paper-menu-button {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
paper-tabs {
|
paper-tabs {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
--paper-tabs-selection-bar-color: var(--text-primary-color, #fff);
|
--paper-tabs-selection-bar-color: var(--text-primary-color, #fff);
|
||||||
|
@ -581,6 +581,21 @@
|
|||||||
"core": {
|
"core": {
|
||||||
"header": "Configuration and Server Control",
|
"header": "Configuration and Server Control",
|
||||||
"introduction": "Changing your configuration can be a tiresome process. We know. This section will try to make your life a little bit easier.",
|
"introduction": "Changing your configuration can be a tiresome process. We know. This section will try to make your life a little bit easier.",
|
||||||
|
"core_config": {
|
||||||
|
"edit_requires_storage": "Editor disabled because config stored in configuration.yaml.",
|
||||||
|
"location_name": "Name of your Home Assistant installation",
|
||||||
|
"latitude": "Latitude",
|
||||||
|
"longitude": "Longitude",
|
||||||
|
"elevation": "Elevation",
|
||||||
|
"elevation_meters": "meters",
|
||||||
|
"time_zone": "Time Zone",
|
||||||
|
"unit_system": "Unit System",
|
||||||
|
"unit_system_imperial": "Imperial",
|
||||||
|
"unit_system_metric": "Metric",
|
||||||
|
"imperial_example": "Fahrenheit, pounds",
|
||||||
|
"metric_example": "Celsius, kilograms",
|
||||||
|
"save_button": "Save"
|
||||||
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
"heading": "Configuration validation",
|
"heading": "Configuration validation",
|
||||||
"introduction": "Validate your configuration if you recently made some changes to your configuration and want to make sure that it is all valid",
|
"introduction": "Validate your configuration if you recently made some changes to your configuration and want to make sure that it is all valid",
|
||||||
@ -627,6 +642,8 @@
|
|||||||
"editor": {
|
"editor": {
|
||||||
"introduction": "Use automations to bring your home alive",
|
"introduction": "Use automations to bring your home alive",
|
||||||
"default_name": "New Automation",
|
"default_name": "New Automation",
|
||||||
|
"load_error_not_editable": "Only automations in automations.yaml are editable.",
|
||||||
|
"load_error_unknown": "Error loading automation ({err_no}).",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"unsaved_confirm": "You have unsaved changes. Are you sure you want to leave?",
|
"unsaved_confirm": "You have unsaved changes. Are you sure you want to leave?",
|
||||||
"alias": "Name",
|
"alias": "Name",
|
||||||
@ -1179,6 +1196,14 @@
|
|||||||
"password_not_match": "Passwords don't match"
|
"password_not_match": "Passwords don't match"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"core-config": {
|
||||||
|
"intro": "Hello {name}, welcome to Home Assistant. How would you like to name your home?",
|
||||||
|
"intro_location": "We would like to know where you live. This information will help with displaying information and setting up sun-based automations. This data is never shared outside of your network.",
|
||||||
|
"intro_location_detect": "We can help you fill in this information by making a one-time request to an external service.",
|
||||||
|
"location_name_default": "Home",
|
||||||
|
"button_detect": "Detect",
|
||||||
|
"finish": "Next"
|
||||||
|
},
|
||||||
"integration": {
|
"integration": {
|
||||||
"intro": "Devices and services are represented in Home Assistant as integrations. You can set them up now, or do it later from the configuration screen.",
|
"intro": "Devices and services are represented in Home Assistant as integrations. You can set them up now, or do it later from the configuration screen.",
|
||||||
"more_integrations": "More",
|
"more_integrations": "More",
|
||||||
|
@ -1118,7 +1118,7 @@
|
|||||||
"sun": {
|
"sun": {
|
||||||
"elevation": "Höhe",
|
"elevation": "Höhe",
|
||||||
"rising": "Aufgang",
|
"rising": "Aufgang",
|
||||||
"setting": "Einstellung"
|
"setting": "Untergang"
|
||||||
},
|
},
|
||||||
"updater": {
|
"updater": {
|
||||||
"title": "Update-Anweisungen"
|
"title": "Update-Anweisungen"
|
||||||
|
@ -603,6 +603,12 @@
|
|||||||
"device_unavailable": "συσκευή μη διαθέσιμη",
|
"device_unavailable": "συσκευή μη διαθέσιμη",
|
||||||
"entity_unavailable": "οντότητα μη διαθέσιμη",
|
"entity_unavailable": "οντότητα μη διαθέσιμη",
|
||||||
"no_area": "Καμία περιοχή"
|
"no_area": "Καμία περιοχή"
|
||||||
|
},
|
||||||
|
"config_flow": {
|
||||||
|
"external_step": {
|
||||||
|
"description": "Αυτό το βήμα απαιτεί να επισκεφτείτε μια εξωτερική ιστοσελίδα για να ολοκληρωθεί.",
|
||||||
|
"open_site": "Άνοιγμα ιστότοπου"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zha": {
|
"zha": {
|
||||||
@ -855,6 +861,11 @@
|
|||||||
"required_fields": "Συμπληρώστε όλα τα υποχρεωτικά πεδία",
|
"required_fields": "Συμπληρώστε όλα τα υποχρεωτικά πεδία",
|
||||||
"password_not_match": "Οι κωδικοί πρόσβασης δεν ταιριάζουν"
|
"password_not_match": "Οι κωδικοί πρόσβασης δεν ταιριάζουν"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"integration": {
|
||||||
|
"intro": "Οι συσκευές και οι υπηρεσίες εκπροσωπούνται στο Home Assistant ως ενσωματώσεις. Μπορείτε να τα ρυθμίσετε τώρα ή αργότερα από την οθόνη διαμόρφωσης.",
|
||||||
|
"more_integrations": "Περισσότερα",
|
||||||
|
"finish": "Τέλος"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lovelace": {
|
"lovelace": {
|
||||||
@ -868,6 +879,14 @@
|
|||||||
"title": "Καλωσορίσατε στην αρχική σελίδα",
|
"title": "Καλωσορίσατε στην αρχική σελίδα",
|
||||||
"no_devices": "Αυτή η σελίδα σάς επιτρέπει να ελέγχετε τις συσκευές σας, ωστόσο φαίνεται ότι δεν έχετε ακόμα ρυθμίσει συσκευές. Μεταβείτε στη σελίδα ενοποίησης για να ξεκινήσετε.",
|
"no_devices": "Αυτή η σελίδα σάς επιτρέπει να ελέγχετε τις συσκευές σας, ωστόσο φαίνεται ότι δεν έχετε ακόμα ρυθμίσει συσκευές. Μεταβείτε στη σελίδα ενοποίησης για να ξεκινήσετε.",
|
||||||
"go_to_integrations_page": "Μεταβείτε στη σελίδα ενοποίησης."
|
"go_to_integrations_page": "Μεταβείτε στη σελίδα ενοποίησης."
|
||||||
|
},
|
||||||
|
"picture-elements": {
|
||||||
|
"hold": "Αναστολή:",
|
||||||
|
"tap": "Ταπ:",
|
||||||
|
"navigate_to": "Μεταβείτε στην {location}",
|
||||||
|
"toggle": "Εναλλαγή {name}",
|
||||||
|
"call_service": "Κλήση υπηρεσίας {name}",
|
||||||
|
"more_info": "Εμφάνιση περισσότερων πληροφοριών: {name}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
@ -925,7 +944,8 @@
|
|||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"log_out": "Αποσύνδεση",
|
"log_out": "Αποσύνδεση",
|
||||||
"developer_tools": "Εργαλεία προγραμματιστή"
|
"developer_tools": "Εργαλεία προγραμματιστή",
|
||||||
|
"external_app_configuration": "Διαμόρφωση Εφαρμογής"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"loading": "Φόρτωση",
|
"loading": "Φόρτωση",
|
||||||
|
@ -355,6 +355,21 @@
|
|||||||
"introduction": "Control your Home Assistant server… from Home Assistant.",
|
"introduction": "Control your Home Assistant server… from Home Assistant.",
|
||||||
"restart": "Restart",
|
"restart": "Restart",
|
||||||
"stop": "Stop"
|
"stop": "Stop"
|
||||||
|
},
|
||||||
|
"core_config": {
|
||||||
|
"edit_requires_storage": "Editor disabled because config stored in configuration.yaml.",
|
||||||
|
"location_name": "Name of your Home Assistant installation",
|
||||||
|
"latitude": "Latitude",
|
||||||
|
"longitude": "Longitude",
|
||||||
|
"elevation": "Elevation",
|
||||||
|
"elevation_meters": "meters",
|
||||||
|
"time_zone": "Time Zone",
|
||||||
|
"unit_system": "Unit System",
|
||||||
|
"unit_system_imperial": "Imperial",
|
||||||
|
"unit_system_metric": "Metric",
|
||||||
|
"imperial_example": "Fahrenheit, pounds",
|
||||||
|
"metric_example": "Celsius, kilograms",
|
||||||
|
"save_button": "Save"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +560,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"learn_more": "Learn more about actions"
|
"learn_more": "Learn more about actions"
|
||||||
}
|
},
|
||||||
|
"load_error_not_editable": "Only automations in automations.yaml are editable.",
|
||||||
|
"load_error_unknown": "Error loading automation ({err_no})."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"script": {
|
"script": {
|
||||||
@ -866,6 +883,14 @@
|
|||||||
"intro": "Devices and services are represented in Home Assistant as integrations. You can set them up now, or do it later from the configuration screen.",
|
"intro": "Devices and services are represented in Home Assistant as integrations. You can set them up now, or do it later from the configuration screen.",
|
||||||
"more_integrations": "More",
|
"more_integrations": "More",
|
||||||
"finish": "Finish"
|
"finish": "Finish"
|
||||||
|
},
|
||||||
|
"core-config": {
|
||||||
|
"intro": "Hello {name}, welcome to Home Assistant. How would you like to name your home?",
|
||||||
|
"intro_location": "We would like to know where you live. This information will help with displaying information and setting up sun-based automations. This data is never shared outside of your network.",
|
||||||
|
"intro_location_detect": "We can help you fill in this information by making a one-time request to an external service.",
|
||||||
|
"location_name_default": "Home",
|
||||||
|
"button_detect": "Detect",
|
||||||
|
"finish": "Next"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lovelace": {
|
"lovelace": {
|
||||||
|
@ -286,9 +286,9 @@
|
|||||||
"alarm_control_panel": {
|
"alarm_control_panel": {
|
||||||
"armed": "Armado",
|
"armed": "Armado",
|
||||||
"disarmed": "Desarmar",
|
"disarmed": "Desarmar",
|
||||||
"armed_home": "Activada",
|
"armed_home": "Armada",
|
||||||
"armed_away": "Activada",
|
"armed_away": "Armada",
|
||||||
"armed_night": "Activada",
|
"armed_night": "Armada",
|
||||||
"pending": "Pendiente",
|
"pending": "Pendiente",
|
||||||
"arming": "Armando",
|
"arming": "Armando",
|
||||||
"disarming": "Desarmar",
|
"disarming": "Desarmar",
|
||||||
@ -603,6 +603,12 @@
|
|||||||
"device_unavailable": "dispositivo no disponible",
|
"device_unavailable": "dispositivo no disponible",
|
||||||
"entity_unavailable": "entidad no disponible",
|
"entity_unavailable": "entidad no disponible",
|
||||||
"no_area": "Ninguna área"
|
"no_area": "Ninguna área"
|
||||||
|
},
|
||||||
|
"config_flow": {
|
||||||
|
"external_step": {
|
||||||
|
"description": "Este paso requiere que visites una web externa para ser completado.",
|
||||||
|
"open_site": "Abrir sitio web"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zha": {
|
"zha": {
|
||||||
|
@ -484,7 +484,7 @@
|
|||||||
"label": "Valeur numérique",
|
"label": "Valeur numérique",
|
||||||
"above": "Dessus",
|
"above": "Dessus",
|
||||||
"below": "Sous",
|
"below": "Sous",
|
||||||
"value_template": "Contenu du template (optionnel)"
|
"value_template": "Contenu du modèle (optionnel)"
|
||||||
},
|
},
|
||||||
"sun": {
|
"sun": {
|
||||||
"label": "Soleil",
|
"label": "Soleil",
|
||||||
|
@ -279,7 +279,9 @@
|
|||||||
"state_badge": {
|
"state_badge": {
|
||||||
"default": {
|
"default": {
|
||||||
"unknown": "לא ידוע",
|
"unknown": "לא ידוע",
|
||||||
"unavailable": "לא זמין"
|
"unavailable": "לא זמין",
|
||||||
|
"error": "שגיאה",
|
||||||
|
"entity_not_found": "ישות לא נמצאה"
|
||||||
},
|
},
|
||||||
"alarm_control_panel": {
|
"alarm_control_panel": {
|
||||||
"armed": "מופעל",
|
"armed": "מופעל",
|
||||||
@ -579,7 +581,8 @@
|
|||||||
"cloud": {
|
"cloud": {
|
||||||
"caption": "ענן Home Assistant",
|
"caption": "ענן Home Assistant",
|
||||||
"description_login": "מחובר בתור {email} מה",
|
"description_login": "מחובר בתור {email} מה",
|
||||||
"description_not_login": "לא מחובר"
|
"description_not_login": "לא מחובר",
|
||||||
|
"description_features": "שליטה הרחק מהבית, משתלב עם Alexa ו Google Assistant."
|
||||||
},
|
},
|
||||||
"integrations": {
|
"integrations": {
|
||||||
"caption": "אינטגרציות",
|
"caption": "אינטגרציות",
|
||||||
@ -600,6 +603,12 @@
|
|||||||
"device_unavailable": "התקן אינו זמין",
|
"device_unavailable": "התקן אינו זמין",
|
||||||
"entity_unavailable": "ישות לא זמינה",
|
"entity_unavailable": "ישות לא זמינה",
|
||||||
"no_area": "ללא אזור"
|
"no_area": "ללא אזור"
|
||||||
|
},
|
||||||
|
"config_flow": {
|
||||||
|
"external_step": {
|
||||||
|
"description": "שלב זה מחייב אותך לבקר באתר אינטרנט חיצוני להשלמת הפעולה.",
|
||||||
|
"open_site": "פתח אתר"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zha": {
|
"zha": {
|
||||||
@ -607,7 +616,18 @@
|
|||||||
"description": "ניהול רשת Zigbee לאוטומציה ביתית",
|
"description": "ניהול רשת Zigbee לאוטומציה ביתית",
|
||||||
"services": {
|
"services": {
|
||||||
"reconfigure": "התקן מחדש את התקן ה ZHA. השתמש באפשרות זו אם אתה נתקל בבעיות בהתקן. אם ההתקן המדובר הוא התקן המופעל באמצעות סוללות, ודא שהוא ער ויכול לקבל פקודות בעת שימוש בשירות זה.",
|
"reconfigure": "התקן מחדש את התקן ה ZHA. השתמש באפשרות זו אם אתה נתקל בבעיות בהתקן. אם ההתקן המדובר הוא התקן המופעל באמצעות סוללות, ודא שהוא ער ויכול לקבל פקודות בעת שימוש בשירות זה.",
|
||||||
"updateDeviceName": "הגדר שם מותאם אישית עבור התקן זה במאגר ההתקנים."
|
"updateDeviceName": "הגדר שם מותאם אישית עבור התקן זה במאגר ההתקנים.",
|
||||||
|
"remove": "הסר התקן מרשת ZigBee."
|
||||||
|
},
|
||||||
|
"device_card": {
|
||||||
|
"device_name_placeholder": "שם פרטי",
|
||||||
|
"area_picker_label": "אזור",
|
||||||
|
"update_name_button": "עדכן שם"
|
||||||
|
},
|
||||||
|
"add_device_page": {
|
||||||
|
"header": "אוטומציית Zigbee - הוספת התקנים",
|
||||||
|
"spinner": "מחפש מכשירי ZHA Zigbee...",
|
||||||
|
"discovery_text": ". המכשירים שהתגלו יופיעו כאן. עקוב אחר ההוראות עבור ההתקנים שלך והצב את ההתקנים במצב תיאום."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"area_registry": {
|
"area_registry": {
|
||||||
@ -841,6 +861,11 @@
|
|||||||
"required_fields": "מלא את כל השדות הדרושים",
|
"required_fields": "מלא את כל השדות הדרושים",
|
||||||
"password_not_match": "הסיסמאות אינן תואמות"
|
"password_not_match": "הסיסמאות אינן תואמות"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"integration": {
|
||||||
|
"intro": "התקנים ושירותים מיוצגים ב- Home Assistant כאינטגרציות. באפשרותך להגדיר אותם כעת, או לעשות זאת מאוחר יותר ממסך התצורה.",
|
||||||
|
"more_integrations": "עוד",
|
||||||
|
"finish": "סיום"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lovelace": {
|
"lovelace": {
|
||||||
@ -854,6 +879,14 @@
|
|||||||
"title": "ברוך הבא הביתה",
|
"title": "ברוך הבא הביתה",
|
||||||
"no_devices": "דף זה מאפשר לך לשלוט במכשירים שלך, אך נראה שעדיין לא הוגדרו מכשירים. עבור אל דף האינטגרציות כדי להתחיל.",
|
"no_devices": "דף זה מאפשר לך לשלוט במכשירים שלך, אך נראה שעדיין לא הוגדרו מכשירים. עבור אל דף האינטגרציות כדי להתחיל.",
|
||||||
"go_to_integrations_page": "עבור אל דף האינטגרציות."
|
"go_to_integrations_page": "עבור אל דף האינטגרציות."
|
||||||
|
},
|
||||||
|
"picture-elements": {
|
||||||
|
"hold": "החזק:",
|
||||||
|
"tap": "הקש:",
|
||||||
|
"navigate_to": "נווט אל {location}",
|
||||||
|
"toggle": "החלף מצב {name}",
|
||||||
|
"call_service": "קריאה לשירות {name}",
|
||||||
|
"more_info": "הצג מידע נוסף: {name}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
@ -911,7 +944,8 @@
|
|||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"log_out": "התנתק",
|
"log_out": "התנתק",
|
||||||
"developer_tools": "כלים למפתחים"
|
"developer_tools": "כלים למפתחים",
|
||||||
|
"external_app_configuration": "הגדרות היישום"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"loading": "טוען",
|
"loading": "טוען",
|
||||||
|
@ -603,6 +603,11 @@
|
|||||||
"device_unavailable": "dispositivo non disponibile",
|
"device_unavailable": "dispositivo non disponibile",
|
||||||
"entity_unavailable": "entità non disponibile",
|
"entity_unavailable": "entità non disponibile",
|
||||||
"no_area": "Nessuna area"
|
"no_area": "Nessuna area"
|
||||||
|
},
|
||||||
|
"config_flow": {
|
||||||
|
"external_step": {
|
||||||
|
"open_site": "Apri sito Web"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zha": {
|
"zha": {
|
||||||
@ -610,7 +615,7 @@
|
|||||||
"description": "Gestione rete Zigbee Home Automation",
|
"description": "Gestione rete Zigbee Home Automation",
|
||||||
"services": {
|
"services": {
|
||||||
"reconfigure": "Riconfigurare il dispositivo ZHA (dispositivo di guarigione). Utilizzare questa opzione se si verificano problemi con il dispositivo. Se il dispositivo in questione è un dispositivo alimentato a batteria, assicurarsi che sia sveglio e che accetti i comandi quando si utilizza questo servizio.",
|
"reconfigure": "Riconfigurare il dispositivo ZHA (dispositivo di guarigione). Utilizzare questa opzione se si verificano problemi con il dispositivo. Se il dispositivo in questione è un dispositivo alimentato a batteria, assicurarsi che sia sveglio e che accetti i comandi quando si utilizza questo servizio.",
|
||||||
"updateDeviceName": "Imposta un nome personalizzato per questo dispositivo nel registro del dispositivo.",
|
"updateDeviceName": "Imposta un nome personalizzato per questo dispositivo nel registro dispositivi.",
|
||||||
"remove": "Rimuovi un dispositivo dalla rete ZigBee."
|
"remove": "Rimuovi un dispositivo dalla rete ZigBee."
|
||||||
},
|
},
|
||||||
"device_card": {
|
"device_card": {
|
||||||
@ -630,7 +635,7 @@
|
|||||||
"picker": {
|
"picker": {
|
||||||
"header": "Registro di area",
|
"header": "Registro di area",
|
||||||
"introduction": "Le aree sono utilizzate per organizzare dove sono i dispositivi. Queste informazioni saranno utilizzate in Home Assistant per aiutarti ad organizzare la tua interfaccia, permessi e integrazioni con altri sistemi.",
|
"introduction": "Le aree sono utilizzate per organizzare dove sono i dispositivi. Queste informazioni saranno utilizzate in Home Assistant per aiutarti ad organizzare la tua interfaccia, permessi e integrazioni con altri sistemi.",
|
||||||
"introduction2": "Per posizionare i dispositivi in un'area, utilizzare il collegamento seguente per accedere alla pagina delle integrazioni e quindi fare clic su un'integrazione configurata per accedere alle schede del dispositivo.",
|
"introduction2": "Per posizionare i dispositivi in un'area, utilizzare il seguente collegamento per accedere alla pagina delle integrazioni e quindi fare clic su un'integrazione configurata per accedere alle schede del dispositivo.",
|
||||||
"integrations_page": "Integrazioni",
|
"integrations_page": "Integrazioni",
|
||||||
"no_areas": "Sembra che tu non abbia ancora delle aree!",
|
"no_areas": "Sembra che tu non abbia ancora delle aree!",
|
||||||
"create_area": "CREA AREA"
|
"create_area": "CREA AREA"
|
||||||
@ -650,7 +655,7 @@
|
|||||||
"picker": {
|
"picker": {
|
||||||
"header": "Registro delle entità",
|
"header": "Registro delle entità",
|
||||||
"unavailable": "(non disponibile)",
|
"unavailable": "(non disponibile)",
|
||||||
"introduction": "Home Assistant mantiene un registro di tutte le entità che ha mai localizzato che possono essere identificate in modo univoco. A ciascuna di queste entità sarà assegnato un ID che sarà riservato solo a questa entità.",
|
"introduction": "Home Assistant mantiene un registro di tutte le entità che ha mai localizzato e possono essere identificate in modo univoco. A ciascuna di queste entità sarà assegnato un ID che sarà riservato solo a questa entità.",
|
||||||
"introduction2": "Utilizzare il registro delle entità per sovrascrivere il nome, modificare l'entity ID o rimuovere la voce da Home Assistant. Nota, la rimozione della voce del registro entità non rimuoverà l'entità. Per farlo, segui il link sottostante e rimuovilo dalla pagina delle integrazioni.",
|
"introduction2": "Utilizzare il registro delle entità per sovrascrivere il nome, modificare l'entity ID o rimuovere la voce da Home Assistant. Nota, la rimozione della voce del registro entità non rimuoverà l'entità. Per farlo, segui il link sottostante e rimuovilo dalla pagina delle integrazioni.",
|
||||||
"integrations_page": "Integrazioni"
|
"integrations_page": "Integrazioni"
|
||||||
},
|
},
|
||||||
@ -855,6 +860,10 @@
|
|||||||
"required_fields": "Compila tutti i campi richiesti",
|
"required_fields": "Compila tutti i campi richiesti",
|
||||||
"password_not_match": "Le password non corrispondono"
|
"password_not_match": "Le password non corrispondono"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"integration": {
|
||||||
|
"intro": "Dispositivi e servizi sono rappresentati in Home Assistant come integrazioni. È possibile impostarli ora, o farlo in seguito dalla schermata di configurazione.",
|
||||||
|
"finish": "finire"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lovelace": {
|
"lovelace": {
|
||||||
@ -868,6 +877,9 @@
|
|||||||
"title": "Benvenuto a casa",
|
"title": "Benvenuto a casa",
|
||||||
"no_devices": "Questa pagina ti consente di controllare i tuoi dispositivi, tuttavia sembra che tu non abbia ancora configurato uno. Vai alla pagina delle integrazioni per iniziare.",
|
"no_devices": "Questa pagina ti consente di controllare i tuoi dispositivi, tuttavia sembra che tu non abbia ancora configurato uno. Vai alla pagina delle integrazioni per iniziare.",
|
||||||
"go_to_integrations_page": "Vai alla pagina delle integrazioni."
|
"go_to_integrations_page": "Vai alla pagina delle integrazioni."
|
||||||
|
},
|
||||||
|
"picture-elements": {
|
||||||
|
"more_info": "Mostra più informazioni: {name}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
@ -926,7 +938,7 @@
|
|||||||
"sidebar": {
|
"sidebar": {
|
||||||
"log_out": "Esci",
|
"log_out": "Esci",
|
||||||
"developer_tools": "Strumenti per gli sviluppatori",
|
"developer_tools": "Strumenti per gli sviluppatori",
|
||||||
"external_app_configuration": "Configurazione dell'App"
|
"external_app_configuration": "Configurazione App"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"loading": "Caricamento",
|
"loading": "Caricamento",
|
||||||
|
@ -602,7 +602,7 @@
|
|||||||
"firmware": "Fastvare: {version}",
|
"firmware": "Fastvare: {version}",
|
||||||
"device_unavailable": "enheten er utilgjengelig",
|
"device_unavailable": "enheten er utilgjengelig",
|
||||||
"entity_unavailable": "oppføringen er utilgjengelig",
|
"entity_unavailable": "oppføringen er utilgjengelig",
|
||||||
"no_area": "Ingen område"
|
"no_area": "Intet område"
|
||||||
},
|
},
|
||||||
"config_flow": {
|
"config_flow": {
|
||||||
"external_step": {
|
"external_step": {
|
||||||
@ -622,12 +622,12 @@
|
|||||||
"device_card": {
|
"device_card": {
|
||||||
"device_name_placeholder": "Brukerdefinert navn",
|
"device_name_placeholder": "Brukerdefinert navn",
|
||||||
"area_picker_label": "Område",
|
"area_picker_label": "Område",
|
||||||
"update_name_button": "Oppdater navn"
|
"update_name_button": "Oppdatér navn"
|
||||||
},
|
},
|
||||||
"add_device_page": {
|
"add_device_page": {
|
||||||
"header": "ZigBee Home Automation - Legg til enheter",
|
"header": "ZigBee Home Automation - Legg til enheter",
|
||||||
"spinner": "Søker etter ZHA Zigbee enheter...",
|
"spinner": "Søker etter ZHA Zigbee-enheter...",
|
||||||
"discovery_text": "Oppdagede enheter vises her. Følg instruksjonene for enheten(e) og sett enheten(e) i parringsmodus."
|
"discovery_text": "Oppdagede enheter vises her. Følg instruksjonene for enheten(e) og sett enheten(e) i paringsmodus."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"area_registry": {
|
"area_registry": {
|
||||||
@ -656,7 +656,7 @@
|
|||||||
"picker": {
|
"picker": {
|
||||||
"header": "Enhetsregister",
|
"header": "Enhetsregister",
|
||||||
"unavailable": "(utilgjengelig)",
|
"unavailable": "(utilgjengelig)",
|
||||||
"introduction": "Home Assistant beholder et register over hver enhet som den noensinne har sett som kan identifiseres unikt. Hver av disse enhetene vil ha en enhets ID tilknyttet som vil bli reservert for bare denne enheten.",
|
"introduction": "Home Assistant bygger opp et register over hver enhet den har sett som kan identifiseres unikt. Hver av disse enhetene vil ha en enhets-ID tilknyttet som vil bli reservert for bare denne enheten.",
|
||||||
"introduction2": "Bruk entitetsregisteret for å overskrive navnet, endre enhets ID eller fjern oppføringen fra Home Assistant. Merk at fjerning av enhetsregisteroppføringer ikke fjerner enheten. For å gjøre det, følg linken under og fjern den fra integrasjonssiden.",
|
"introduction2": "Bruk entitetsregisteret for å overskrive navnet, endre enhets ID eller fjern oppføringen fra Home Assistant. Merk at fjerning av enhetsregisteroppføringer ikke fjerner enheten. For å gjøre det, følg linken under og fjern den fra integrasjonssiden.",
|
||||||
"integrations_page": "Integrasjonsside"
|
"integrations_page": "Integrasjonsside"
|
||||||
},
|
},
|
||||||
@ -863,7 +863,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration": {
|
"integration": {
|
||||||
"intro": "Enheter og tjenester er representert i Home Assistant som integrasjoner. Du kan sette dem opp nå, eller gjøre det senere fra konfigurasjonen skjermen.",
|
"intro": "Enheter og tjenester er representert i Home Assistant som integrasjoner. Du kan sette dem opp nå eller gjøre det senere fra konfigurasjonen.",
|
||||||
"more_integrations": "Mer",
|
"more_integrations": "Mer",
|
||||||
"finish": "Fullfør"
|
"finish": "Fullfør"
|
||||||
}
|
}
|
||||||
@ -1199,6 +1199,6 @@
|
|||||||
"groups": {
|
"groups": {
|
||||||
"system-admin": "Administratorer",
|
"system-admin": "Administratorer",
|
||||||
"system-users": "Brukere",
|
"system-users": "Brukere",
|
||||||
"system-read-only": "Lesetilgang brukere"
|
"system-read-only": "Brukere med lesetilgang"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -603,6 +603,12 @@
|
|||||||
"device_unavailable": "apparaat niet beschikbaar",
|
"device_unavailable": "apparaat niet beschikbaar",
|
||||||
"entity_unavailable": "entiteit niet beschikbaar",
|
"entity_unavailable": "entiteit niet beschikbaar",
|
||||||
"no_area": "Geen gebied"
|
"no_area": "Geen gebied"
|
||||||
|
},
|
||||||
|
"config_flow": {
|
||||||
|
"external_step": {
|
||||||
|
"description": "Deze stap vereist dat u een externe website bezoekt om dit te voltooien.",
|
||||||
|
"open_site": "Open website"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zha": {
|
"zha": {
|
||||||
|
@ -347,7 +347,7 @@
|
|||||||
"introduction": "Niektóre części Home Assistant'a można przeładować bez konieczności ponownego uruchomienia. Kliknięcie przeładuj spowoduje ponowne wczytanie konfiguracji.",
|
"introduction": "Niektóre części Home Assistant'a można przeładować bez konieczności ponownego uruchomienia. Kliknięcie przeładuj spowoduje ponowne wczytanie konfiguracji.",
|
||||||
"core": "Przeładuj rdzeń",
|
"core": "Przeładuj rdzeń",
|
||||||
"group": "Przeładuj grupy",
|
"group": "Przeładuj grupy",
|
||||||
"automation": "Przeładuj reguły automatyzacji",
|
"automation": "Przeładuj automatyzacje",
|
||||||
"script": "Przeładuj skrypty"
|
"script": "Przeładuj skrypty"
|
||||||
},
|
},
|
||||||
"server_management": {
|
"server_management": {
|
||||||
@ -368,25 +368,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"automation": {
|
"automation": {
|
||||||
"caption": "Reguły automatyzacji",
|
"caption": "Automatyzacje",
|
||||||
"description": "Twórz i edytuj reguły automatyzacji",
|
"description": "Twórz i edytuj automatyzacje",
|
||||||
"picker": {
|
"picker": {
|
||||||
"header": "Edytor automatyzacji",
|
"header": "Edytor automatyzacji",
|
||||||
"introduction": "Edytor automatyzacji pozwala tworzyć i edytować reguły automatyzacji. Kliknij poniższy link, aby przeczytać instrukcję, jak poprawnie skonfigurować reguły automatyzacji w Home Assistant.",
|
"introduction": "Edytor automatyzacji pozwala tworzyć i edytować automatyzacje Kliknij poniższy link, aby przeczytać instrukcję, jak poprawnie skonfigurować automatyzacje w Home Assistant.",
|
||||||
"pick_automation": "Wybierz regułę automatyzacji do edycji",
|
"pick_automation": "Wybierz automatyzację do edycji",
|
||||||
"no_automations": "Nie znaleziono żadnych edytowalnych reguł automatyzacji",
|
"no_automations": "Nie znaleziono żadnych edytowalnych automatyzacji",
|
||||||
"add_automation": "Dodaj regułę automatyzacji",
|
"add_automation": "Dodaj automatyzację",
|
||||||
"learn_more": "Dowiedz się więcej o regułach automatyki"
|
"learn_more": "Dowiedz się więcej o automatyzacjach"
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
"introduction": "Użyj reguł automatyzacji, aby utrzymać swój dom przy życiu",
|
"introduction": "Użyj automatyzacji, aby utrzymać swój dom przy życiu",
|
||||||
"default_name": "Nowa reguła automatyzacji",
|
"default_name": "Nowa automatyzacja",
|
||||||
"save": "Zapisz",
|
"save": "Zapisz",
|
||||||
"unsaved_confirm": "Masz niezapisane zmiany. Jesteś pewny, że chcesz wyjść?",
|
"unsaved_confirm": "Masz niezapisane zmiany. Jesteś pewny, że chcesz wyjść?",
|
||||||
"alias": "Nazwa",
|
"alias": "Nazwa",
|
||||||
"triggers": {
|
"triggers": {
|
||||||
"header": "Wyzwalacze",
|
"header": "Wyzwalacze",
|
||||||
"introduction": "Wyzwalacze uruchamiają przetwarzanie reguły automatyzacji. Możliwe jest stworzenie wielu wyzwalaczy dla tej samej reguły. Po uruchomieniu wyzwalacza Home Assistant sprawdzi ewentualne warunki i wywoła akcje.",
|
"introduction": "Wyzwalacze uruchamiają przetwarzanie automatyzacji. Możliwe jest stworzenie wielu wyzwalaczy dla tej samej automatyzacji. Po uruchomieniu wyzwalacza Home Assistant sprawdzi ewentualne warunki i wywoła akcje.",
|
||||||
"add": "Dodaj wyzwalacz",
|
"add": "Dodaj wyzwalacz",
|
||||||
"duplicate": "Duplikuj",
|
"duplicate": "Duplikuj",
|
||||||
"delete": "Usuń",
|
"delete": "Usuń",
|
||||||
@ -468,7 +468,7 @@
|
|||||||
},
|
},
|
||||||
"conditions": {
|
"conditions": {
|
||||||
"header": "Warunki",
|
"header": "Warunki",
|
||||||
"introduction": "Warunki są opcjonalną częścią reguły automatyzacji i można ich użyć, aby zapobiec działaniom po uruchomieniu. Warunki wyglądają bardzo podobnie do wyzwalaczy, ale są bardzo różne. Wyzwalacz będzie analizował zdarzenia zachodzące w systemie, a warunek będzie dotyczył tylko tego, jak wygląda teraz system. Wyzwalacz może zaobserwować, że przełącznik jest przełączany. Warunek może tylko sprawdzić, czy przełącznik jest aktualnie włączony lub wyłączony.",
|
"introduction": "Warunki są opcjonalną częścią automatyzacji i można ich użyć, aby zapobiec działaniom po uruchomieniu. Warunki wyglądają bardzo podobnie do wyzwalaczy, ale są bardzo różne. Wyzwalacz będzie analizował zdarzenia zachodzące w systemie, a warunek będzie dotyczył tylko tego, jak wygląda teraz system. Wyzwalacz może zaobserwować, że przełącznik jest przełączany. Warunek może tylko sprawdzić, czy przełącznik jest aktualnie włączony lub wyłączony.",
|
||||||
"add": "Dodaj warunek",
|
"add": "Dodaj warunek",
|
||||||
"duplicate": "Duplikuj",
|
"duplicate": "Duplikuj",
|
||||||
"delete": "Usuń",
|
"delete": "Usuń",
|
||||||
@ -514,7 +514,7 @@
|
|||||||
},
|
},
|
||||||
"actions": {
|
"actions": {
|
||||||
"header": "Akcje",
|
"header": "Akcje",
|
||||||
"introduction": "Akcje są wykonywane przez Home Assistant'a po uruchomieniu reguły automatyzacji.",
|
"introduction": "Akcje są wykonywane przez Home Assistant'a po uruchomieniu automatyzacji.",
|
||||||
"add": "Dodaj akcję",
|
"add": "Dodaj akcję",
|
||||||
"duplicate": "Duplikuj",
|
"duplicate": "Duplikuj",
|
||||||
"delete": "Usuń",
|
"delete": "Usuń",
|
||||||
|
@ -751,7 +751,7 @@
|
|||||||
},
|
},
|
||||||
"page-authorize": {
|
"page-authorize": {
|
||||||
"initializing": "Инициализация",
|
"initializing": "Инициализация",
|
||||||
"authorizing_client": "Получение доступа к Home Assistant через {clientId}.",
|
"authorizing_client": "Получение доступа к {clientId}.",
|
||||||
"logging_in_with": "Провайдер аутентификации: **{authProviderName}**.",
|
"logging_in_with": "Провайдер аутентификации: **{authProviderName}**.",
|
||||||
"pick_auth_provider": "Или войти с помощью",
|
"pick_auth_provider": "Или войти с помощью",
|
||||||
"abort_intro": "Вход прерван",
|
"abort_intro": "Вход прерван",
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
},
|
},
|
||||||
"climate": {
|
"climate": {
|
||||||
"manual": "Упутство"
|
"manual": "Упутство"
|
||||||
|
},
|
||||||
|
"timer": {
|
||||||
|
"active": "укључен",
|
||||||
|
"idle": "неактна чекању"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"state_badge": {
|
"state_badge": {
|
||||||
@ -36,6 +40,14 @@
|
|||||||
"arming": "Aktiviranje",
|
"arming": "Aktiviranje",
|
||||||
"disarming": "Deaktiviraj",
|
"disarming": "Deaktiviraj",
|
||||||
"armed_custom_bypass": "Aktiviran"
|
"armed_custom_bypass": "Aktiviran"
|
||||||
|
},
|
||||||
|
"person": {
|
||||||
|
"home": "Кући",
|
||||||
|
"not_home": "Одсутан"
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"error": "Грешка",
|
||||||
|
"entity_not_found": "Вредност није пронађена"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
@ -46,6 +58,60 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"zwave": {
|
"zwave": {
|
||||||
"caption": "Z-Wave"
|
"caption": "Z-Wave"
|
||||||
|
},
|
||||||
|
"users": {
|
||||||
|
"editor": {
|
||||||
|
"caption": "Прикажи корисника"
|
||||||
|
},
|
||||||
|
"add_user": {
|
||||||
|
"caption": "Додај корисника",
|
||||||
|
"name": "Име",
|
||||||
|
"username": "Корисничко име",
|
||||||
|
"password": "Лозинка",
|
||||||
|
"create": "Направите"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"automation": {
|
||||||
|
"picker": {
|
||||||
|
"learn_more": "Сазнајте више о аутоматизацијама"
|
||||||
|
},
|
||||||
|
"editor": {
|
||||||
|
"triggers": {
|
||||||
|
"learn_more": "Сазнајте више о окидачима"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"integrations": {
|
||||||
|
"config_flow": {
|
||||||
|
"external_step": {
|
||||||
|
"description": "Овај корак захтева да посетите екстерни веб-сајт да би био завршен.",
|
||||||
|
"open_site": "Отворите сајт"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"page-onboarding": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"password_confirm": "Потврда лозинке"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"password_not_match": "Лозинке се не подударају"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"integration": {
|
||||||
|
"finish": "Крај"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lovelace": {
|
||||||
|
"cards": {
|
||||||
|
"picture-elements": {
|
||||||
|
"hold": "Придржи:",
|
||||||
|
"tap": "Додирни",
|
||||||
|
"navigate_to": "Отиђите на ",
|
||||||
|
"toggle": "Укључи",
|
||||||
|
"more_info": "Покажи више информација:"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -67,6 +133,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"domain": {
|
"domain": {
|
||||||
"zwave": "Z-Wave"
|
"zwave": "Z-Wave",
|
||||||
|
"person": "Особа"
|
||||||
|
},
|
||||||
|
"state_attributes": {
|
||||||
|
"climate": {
|
||||||
|
"fan_mode": {
|
||||||
|
"off": "Искључен",
|
||||||
|
"on": "Укључен",
|
||||||
|
"auto": "Аутоматски"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -581,7 +581,8 @@
|
|||||||
"cloud": {
|
"cloud": {
|
||||||
"caption": "Home Assistant Cloud",
|
"caption": "Home Assistant Cloud",
|
||||||
"description_login": "ลงชื่อเข้าใช้เป็น {email}",
|
"description_login": "ลงชื่อเข้าใช้เป็น {email}",
|
||||||
"description_not_login": "ยังไม่ได้เข้าสู่ระบบ"
|
"description_not_login": "ยังไม่ได้เข้าสู่ระบบ",
|
||||||
|
"description_features": "ควบคุมการทำงานเมื่อออกจากบ้านร่วมกับ Alexa และ Google Assistant"
|
||||||
},
|
},
|
||||||
"integrations": {
|
"integrations": {
|
||||||
"caption": "การทำงานร่วมกัน",
|
"caption": "การทำงานร่วมกัน",
|
||||||
@ -602,6 +603,12 @@
|
|||||||
"device_unavailable": "อุปกรณ์นี้ไม่พร้อมใช้งาน",
|
"device_unavailable": "อุปกรณ์นี้ไม่พร้อมใช้งาน",
|
||||||
"entity_unavailable": "Entity นี้ไม่พร้อมใช้งาน",
|
"entity_unavailable": "Entity นี้ไม่พร้อมใช้งาน",
|
||||||
"no_area": "ไม่มีห้อง"
|
"no_area": "ไม่มีห้อง"
|
||||||
|
},
|
||||||
|
"config_flow": {
|
||||||
|
"external_step": {
|
||||||
|
"description": "ขั้นตอนนี้กำหนดให้คุณเยี่ยมชมเว็บไซต์ภายนอกเพื่อทำให้การดำเนินการสมบูรณ์",
|
||||||
|
"open_site": "เปิดเว็บไซต์"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zha": {
|
"zha": {
|
||||||
@ -854,6 +861,10 @@
|
|||||||
"required_fields": "กรอกข้อมูลในฟิลด์ที่จำเป็นทั้งหมด",
|
"required_fields": "กรอกข้อมูลในฟิลด์ที่จำเป็นทั้งหมด",
|
||||||
"password_not_match": "รหัสผ่านไม่ตรงกัน"
|
"password_not_match": "รหัสผ่านไม่ตรงกัน"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"integration": {
|
||||||
|
"more_integrations": "เพิ่มเติม",
|
||||||
|
"finish": "เสร็จสิ้น"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lovelace": {
|
"lovelace": {
|
||||||
@ -867,6 +878,14 @@
|
|||||||
"title": "ยินดีต้อนรับกลับบ้าน",
|
"title": "ยินดีต้อนรับกลับบ้าน",
|
||||||
"no_devices": "หน้านี้ช่วยให้คุณควบคุมอุปกรณ์ของคุณได้ แต่ยังไงก็ตามมันดูเหมือนว่าคุณยังไม่ได้ติดตั้งอุปกรณ์อะไรไว้เลย ไปยัง 'หน้าการทำงานด้วยกัน' เพื่อเริ่มติดตั้ง",
|
"no_devices": "หน้านี้ช่วยให้คุณควบคุมอุปกรณ์ของคุณได้ แต่ยังไงก็ตามมันดูเหมือนว่าคุณยังไม่ได้ติดตั้งอุปกรณ์อะไรไว้เลย ไปยัง 'หน้าการทำงานด้วยกัน' เพื่อเริ่มติดตั้ง",
|
||||||
"go_to_integrations_page": "ไปที่หน้าการรวมระบบ"
|
"go_to_integrations_page": "ไปที่หน้าการรวมระบบ"
|
||||||
|
},
|
||||||
|
"picture-elements": {
|
||||||
|
"hold": "ถือ:",
|
||||||
|
"tap": "แตะ:",
|
||||||
|
"navigate_to": "นำทางไปยัง {location}",
|
||||||
|
"toggle": "สลับ {name}",
|
||||||
|
"call_service": "เรียกบริการ {name}",
|
||||||
|
"more_info": "แสดงข้อมูลเพิ่มเติม: {name}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"editor": {
|
"editor": {
|
||||||
@ -924,7 +943,8 @@
|
|||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"log_out": "ออกจากระบบ",
|
"log_out": "ออกจากระบบ",
|
||||||
"developer_tools": "เครื่องมือสำหรับนักพัฒนา"
|
"developer_tools": "เครื่องมือสำหรับนักพัฒนา",
|
||||||
|
"external_app_configuration": "การกำหนดค่าแอพ"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"loading": "กำลังโหลด",
|
"loading": "กำลังโหลด",
|
||||||
|
@ -173,7 +173,7 @@
|
|||||||
"not_home": "离开",
|
"not_home": "离开",
|
||||||
"open": "开启",
|
"open": "开启",
|
||||||
"opening": "正在打开",
|
"opening": "正在打开",
|
||||||
"closed": "关闭",
|
"closed": "已关闭",
|
||||||
"closing": "正在关闭",
|
"closing": "正在关闭",
|
||||||
"stopped": "已停止",
|
"stopped": "已停止",
|
||||||
"locked": "已锁定",
|
"locked": "已锁定",
|
||||||
@ -372,7 +372,7 @@
|
|||||||
"description": "创建和编辑自动化",
|
"description": "创建和编辑自动化",
|
||||||
"picker": {
|
"picker": {
|
||||||
"header": "自动化编辑器",
|
"header": "自动化编辑器",
|
||||||
"introduction": "自动化编辑器方便你创建及编辑自动化。请阅读相关[说明](https:\/\/home-assistant.io\/docs\/automation\/editor\/)以确保正确配置。",
|
"introduction": "自动化编辑器方便你创建及编辑自动化。请按照下面的链接阅读说明,以确保您已正确配置Home Assistant。",
|
||||||
"pick_automation": "选择要编辑的自动化",
|
"pick_automation": "选择要编辑的自动化",
|
||||||
"no_automations": "未找到可编辑的自动化",
|
"no_automations": "未找到可编辑的自动化",
|
||||||
"add_automation": "添加自动化",
|
"add_automation": "添加自动化",
|
||||||
@ -468,7 +468,7 @@
|
|||||||
},
|
},
|
||||||
"conditions": {
|
"conditions": {
|
||||||
"header": "环境条件",
|
"header": "环境条件",
|
||||||
"introduction": "环境条件是自动化流程中的可选条件,它可用于避免触发条件满足时动作的执行。环境条件看似像触发条件实则大有不同。触发条件监测系统中事件的发生,也就是瞬时动作;而环境条件监测的是系统的状态。例如,“灯被打开”这个事件属于触发条件,“灯是开着的”这个状态就属于环境条件。\n\n[了解更多内容](https:\/\/home-assistant.io\/docs\/scripts\/conditions\/)",
|
"introduction": "环境条件是自动化流程中的可选部分,它可用于触发条件触发时拦截不符合条件的动作。环境条件看似像触发条件实则大有不同。触发条件监测系统中事件的发生,也就是瞬时动作;而环境条件监测的是系统当前的状态。触发条件可以观察到开关打开的动作。条件只能查看当前开关是开还是关。",
|
||||||
"add": "添加环境条件",
|
"add": "添加环境条件",
|
||||||
"duplicate": "复制",
|
"duplicate": "复制",
|
||||||
"delete": "删除",
|
"delete": "删除",
|
||||||
@ -606,7 +606,7 @@
|
|||||||
},
|
},
|
||||||
"config_flow": {
|
"config_flow": {
|
||||||
"external_step": {
|
"external_step": {
|
||||||
"description": "此步骤要求您访问要完成的外部网站。",
|
"description": "此步骤需要访问外部网站才能完成。",
|
||||||
"open_site": "打开网站"
|
"open_site": "打开网站"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,6 +621,7 @@
|
|||||||
},
|
},
|
||||||
"device_card": {
|
"device_card": {
|
||||||
"device_name_placeholder": "用户指定的名称",
|
"device_name_placeholder": "用户指定的名称",
|
||||||
|
"area_picker_label": "区域",
|
||||||
"update_name_button": "更新名称"
|
"update_name_button": "更新名称"
|
||||||
},
|
},
|
||||||
"add_device_page": {
|
"add_device_page": {
|
||||||
@ -862,6 +863,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"integration": {
|
"integration": {
|
||||||
|
"intro": "设备和服务在 Home Assistant 中表示为集成。您可以立即设置它们,也可以稍后在配置屏幕进行设置。",
|
||||||
"more_integrations": "更多",
|
"more_integrations": "更多",
|
||||||
"finish": "完成"
|
"finish": "完成"
|
||||||
}
|
}
|
||||||
|
@ -1052,7 +1052,7 @@
|
|||||||
},
|
},
|
||||||
"lock": {
|
"lock": {
|
||||||
"code": "密碼",
|
"code": "密碼",
|
||||||
"lock": "鎖",
|
"lock": "上鎖",
|
||||||
"unlock": "解鎖"
|
"unlock": "解鎖"
|
||||||
},
|
},
|
||||||
"vacuum": {
|
"vacuum": {
|
||||||
|
19
yarn.lock
19
yarn.lock
@ -6807,6 +6807,11 @@ glogg@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
sparkles "^1.0.0"
|
sparkles "^1.0.0"
|
||||||
|
|
||||||
|
google-timezones-json@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/google-timezones-json/-/google-timezones-json-1.0.2.tgz#6800000d7ebc2dd660611aad8c1c68196db78cab"
|
||||||
|
integrity sha512-UWXQ7BpSCW8erDespU2I4cri22xsKgwOCyhsJal0OJhi2tFpwJpsYNJt4vCiFPL1p2HzCGiS713LKpNR25n9Kg==
|
||||||
|
|
||||||
got@^5.0.0:
|
got@^5.0.0:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35"
|
resolved "https://registry.yarnpkg.com/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35"
|
||||||
@ -7242,10 +7247,10 @@ hoek@6.x.x:
|
|||||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
|
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
|
||||||
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
|
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
|
||||||
|
|
||||||
home-assistant-js-websocket@^4.1.2:
|
home-assistant-js-websocket@^4.2.1:
|
||||||
version "4.1.2"
|
version "4.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/home-assistant-js-websocket/-/home-assistant-js-websocket-4.1.2.tgz#dbcdb4b67df8d189d29bbf5603771d5bc80ef031"
|
resolved "https://registry.yarnpkg.com/home-assistant-js-websocket/-/home-assistant-js-websocket-4.2.1.tgz#8acdf2a404b4204669213d8405cca027b8b1de1c"
|
||||||
integrity sha512-/I0m6FTDEq3LkzFc4tmgHJHTj9gWA6Wn/fgaa1ghIJJY0Yqb3x6whovN5pRNFsl6bnKzOCR+nmJ2ruVTBa5mVQ==
|
integrity sha512-lF4owDhAAUY70FNvTzgg6MAEOpKbJDLsRDX3gW48muna03s3CRGQzbLmy621pJWK757CkXSW/rWbr34r3Wyi8Q==
|
||||||
|
|
||||||
homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1:
|
homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
@ -8518,9 +8523,9 @@ lit-element@^2.0.1, lit-element@^2.1.0:
|
|||||||
lit-html "^1.0.0"
|
lit-html "^1.0.0"
|
||||||
|
|
||||||
lit-html@^1.0.0:
|
lit-html@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.0.0.tgz#3dc3781a8ca68a9b5c2ff2a61e263662b9b2267b"
|
resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-1.1.0.tgz#6951fb717fb48fe34d915ae163448a04da321562"
|
||||||
integrity sha512-oeWlpLmBW3gFl7979Wol2LKITpmKTUFNn7PnFbh6YNynF61W74l6x5WhwItAwPRSATpexaX1egNnRzlN4GOtfQ==
|
integrity sha512-ZDJHpJi09yknMpjwPI8fuSl5sUG7+pF+eE5WciFtgyX7zebvgMDBgSLq4knXa7grxM00RkQ7PBd7UZQiruA78Q==
|
||||||
|
|
||||||
load-json-file@^1.0.0:
|
load-json-file@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user