Compare commits

..

8 Commits

Author SHA1 Message Date
Ludeeus
50047e2f10 Adjust gap 2021-07-30 10:21:27 +00:00
Ludeeus
2811541fba update 2021-06-02 21:22:34 +00:00
Ludeeus
57788cec44 style 2021-06-02 17:02:24 +00:00
Ludeeus
0aa314d9ae overlay 2021-06-02 16:57:41 +00:00
Ludeeus
f8d97735b8 update 2021-06-02 16:09:28 +00:00
Ludeeus
830136b874 icons 2021-06-02 15:42:31 +00:00
Ludeeus
dd01710784 addon 2021-06-02 15:31:05 +00:00
Ludeeus
f7d0736731 init 2021-06-02 15:10:18 +00:00
55 changed files with 719 additions and 2033 deletions

View File

@@ -52,7 +52,6 @@ module.exports.terserOptions = (latestBuild) => ({
module.exports.babelOptions = ({ latestBuild }) => ({
babelrc: false,
compact: false,
presets: [
!latestBuild && [
"@babel/preset-env",
@@ -80,6 +79,12 @@ module.exports.babelOptions = ({ latestBuild }) => ({
].filter(Boolean),
});
// Are already ES5, cause warnings when babelified.
module.exports.babelExclude = () => [
require.resolve("@mdi/js/mdi.js"),
require.resolve("hls.js"),
];
const outputPath = (outputRoot, latestBuild) =>
path.resolve(outputRoot, latestBuild ? "frontend_latest" : "frontend_es5");

View File

@@ -57,6 +57,7 @@ const createRollupConfig = ({
babel({
...bundle.babelOptions({ latestBuild }),
extensions,
exclude: bundle.babelExclude(),
babelHelpers: isWDS ? "inline" : "bundled",
}),
string({

View File

@@ -47,6 +47,7 @@ const createWebpackConfig = ({
rules: [
{
test: /\.m?js$|\.ts$/,
exclude: bundle.babelExclude(),
use: {
loader: "babel-loader",
options: bundle.babelOptions({ latestBuild }),

View File

@@ -50,10 +50,6 @@ import {
fetchHassioStats,
HassioStats,
} from "../../../../src/data/hassio/common";
import {
fetchHassioSnapshots,
HassioSnapshot,
} from "../../../../src/data/hassio/snapshot";
import { StoreAddon } from "../../../../src/data/supervisor/store";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
import {
@@ -65,7 +61,6 @@ import { HomeAssistant } from "../../../../src/types";
import { bytesToString } from "../../../../src/util/bytes-to-string";
import "../../components/hassio-card-content";
import "../../components/supervisor-metric";
import { showHassioAddonRestoreDialog } from "../../dialogs/addon/show-dialog-hassio-addon-restore";
import { showHassioMarkdownDialog } from "../../dialogs/markdown/show-dialog-hassio-markdown";
import { showDialogSupervisorUpdate } from "../../dialogs/update/show-dialog-update";
import { hassioStyle } from "../../resources/hassio-style";
@@ -87,8 +82,6 @@ class HassioAddonInfo extends LitElement {
@property({ attribute: false }) public supervisor!: Supervisor;
@property({ attribute: false }) public snapshots?: HassioSnapshot[];
@state() private _metrics?: HassioStats;
@state() private _error?: string;
@@ -633,11 +626,6 @@ class HassioAddonInfo extends LitElement {
${this.supervisor.localize("addon.dashboard.install")}
</ha-progress-button>
`}
${this.snapshots?.length
? html`<mwc-button @click=${this._restoreClicked}>
${this.supervisor.localize("addon.dashboard.restore")}
</mwc-button>`
: ""}
</div>
<div>
${this.addon.version
@@ -710,11 +698,6 @@ class HassioAddonInfo extends LitElement {
}
private async _loadData(): Promise<void> {
const snapshots = await fetchHassioSnapshots(this.hass);
this.snapshots = snapshots.filter((snapshot) =>
snapshot.content.addons.includes(this.addon.slug)
);
if (this.addon.state === "started") {
this._metrics = await fetchHassioStats(
this.hass,
@@ -1017,22 +1000,6 @@ class HassioAddonInfo extends LitElement {
fireEvent(this, "hass-api-called", eventdata);
}
private async _restoreClicked(): Promise<void> {
showHassioAddonRestoreDialog(this, {
supervisor: this.supervisor,
snapshots: this.snapshots || [],
addon: this.addon,
onRestore: () => {
const eventdata = {
success: true,
response: undefined,
path: "update",
};
fireEvent(this, "hass-api-called", eventdata);
},
});
}
private async _startClicked(ev: CustomEvent): Promise<void> {
const button = ev.currentTarget as any;
button.progress = true;

View File

@@ -44,9 +44,6 @@ const _computeFolders = (folders): CheckboxItem[] => {
if (folders.includes("share")) {
list.push({ slug: "share", name: "Share", checked: false });
}
if (folders.includes("media")) {
list.push({ slug: "media", name: "Media", checked: false });
}
if (folders.includes("addons/local")) {
list.push({ slug: "addons/local", name: "Local add-ons", checked: false });
}

View File

@@ -1,4 +1,4 @@
import { mdiArrowUpBoldCircle, mdiPuzzle } from "@mdi/js";
import { mdiArrowUpBoldCircle, mdiPlay, mdiPuzzle, mdiStop } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { atLeastVersion } from "../../../src/common/config/version";
@@ -17,7 +17,36 @@ class HassioAddons extends LitElement {
@property({ attribute: false }) public supervisor!: Supervisor;
@property({ type: Boolean }) public narrow!: boolean;
protected render(): TemplateResult {
return html`<ha-card
.header=${this.supervisor.localize("dashboard.addons")}
>
<div class="addons" ?narrow=${this.narrow}>
${this.supervisor.supervisor.addons.map(
(addon) => html`<div
class="addon"
@click=${this._addonTapped}
.addon=${addon}
>
<div class="icon">
<div class="overlay">
<ha-svg-icon
.title=${addon.state}
.path=${addon.state === "started" ? mdiPlay : mdiStop}
>
</ha-svg-icon>
</div>
${addon.icon && atLeastVersion(this.hass.config.version, 0, 105)
? html`<img src="/api/hassio/addons/${addon.slug}/icon" />`
: html`<ha-svg-icon .path=${mdiPuzzle}></ha-svg-icon>`}
</div>
<div class="name">${addon.name}</div>
</div>`
)}
</div>
</ha-card>`;
return html`
<div class="content">
<h1>${this.supervisor.localize("dashboard.addons")}</h1>
@@ -88,9 +117,42 @@ class HassioAddons extends LitElement {
haStyle,
hassioStyle,
css`
ha-card {
.addons {
display: grid;
grid-template-columns: repeat(4, auto);
padding-bottom: 16px;
}
.addons[narrow] {
grid-template-columns: repeat(2, auto);
}
.addon {
text-align: center;
max-width: 100px;
padding: 0 8px;
cursor: pointer;
}
.icon > *:not(.overlay) {
position: relative;
max-height: 60px;
max-width: 60px;
margin: auto;
--mdc-icon-size: 60px;
display: flex;
}
.icon {
margin-bottom: 4px;
}
.overlay {
position: absolute;
z-index: 2;
--mdc-icon-size: 24px;
color: var(--secondary-text-color);
background-color: var(--secondary-background-color);
opacity: 0.6;
border-radius: 100%;
margin-left: 12px;
border: 1px var(--secondary-text-color) solid;
}
`,
];
}

View File

@@ -5,6 +5,7 @@ import "../../../src/layouts/hass-tabs-subpage";
import { haStyle } from "../../../src/resources/styles";
import { HomeAssistant, Route } from "../../../src/types";
import { supervisorTabs } from "../hassio-tabs";
import { hassioStyle } from "../resources/hassio-style";
import "./hassio-addons";
import "./hassio-update";
@@ -32,14 +33,17 @@ class HassioDashboard extends LitElement {
<span slot="header">
${this.supervisor.localize("panel.dashboard")}
</span>
<div class="content">
<hassio-update
.hass=${this.hass}
.supervisor=${this.supervisor}
.narrow=${this.narrow}
></hassio-update>
<hassio-addons
.hass=${this.hass}
.supervisor=${this.supervisor}
.narrow=${this.narrow}
></hassio-addons>
</div>
</hass-tabs-subpage>
@@ -49,9 +53,18 @@ class HassioDashboard extends LitElement {
static get styles(): CSSResultGroup {
return [
haStyle,
hassioStyle,
css`
.content {
margin: 0 auto;
display: grid;
max-width: 1400px;
justify-content: center;
grid-template-columns: repeat(2, auto);
gap: 16px;
}
.content > * {
display: block;
min-width: 400px;
}
`,
];

View File

@@ -1,5 +1,5 @@
import "@material/mwc-button";
import { mdiHomeAssistant } from "@mdi/js";
import { mdiHomeAssistant, mdiPuzzle } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
@@ -42,11 +42,15 @@ export class HassioUpdate extends LitElement {
@property({ attribute: false }) public supervisor!: Supervisor;
@property({ type: Boolean }) public narrow!: boolean;
private _pendingUpdates = memoizeOne(
(supervisor: Supervisor): number =>
Object.keys(supervisor).filter(
(value) => supervisor[value].update_available
).length
).length +
supervisor.supervisor.addons.filter((addon) => addon.update_available)
.length
);
protected render(): TemplateResult {
@@ -60,15 +64,38 @@ export class HassioUpdate extends LitElement {
}
return html`
<div class="content">
<h1>
${this.supervisor.localize(
"common.update_available",
"count",
updatesAvailable
<ha-card
.header="${this.supervisor.localize(
"common.update_available",
"count",
updatesAvailable + 1
)}
🎉"
>
${this._renderUpdateRow({
type: "os",
heading: "Home Assistant Operating system",
icon: mdiHomeAssistant,
version: "5",
version_latest: "6",
})}
${this.supervisor.addon.addons
.filter((addon) => addon.update_available)
.map((addon) =>
this._renderUpdateRow({
type: "addon",
heading: addon.name,
version: addon.version_latest,
version_latest: addon.version,
image: addon.icon
? `/api/hassio/addons/${addon.slug}/icon`
: undefined,
icon: mdiPuzzle,
})
)}
🎉
</h1>
</ha-card>
<div class="content">
<h1></h1>
<div class="card-group">
${this._renderUpdateCard(
"Home Assistant Core",
@@ -100,6 +127,37 @@ export class HassioUpdate extends LitElement {
`;
}
private _renderUpdateRow(options: {
type: "supervisor" | "os" | "core" | "addon";
heading: string;
version: string;
version_latest: string;
icon?: string;
image?: string;
release_notes?: string;
slug?: string;
}): TemplateResult {
return html`<div class="update-row">
<paper-icon-item>
<div class="icon" slot="item-icon">
${options.image && atLeastVersion(this.hass.config.version, 0, 104)
? html`<img src="${options.image}" />`
: options.icon
? html`<ha-svg-icon .path=${options.icon}></ha-svg-icon>`
: ""}
</div>
<paper-item-body two-line>
${options.heading}
<div secondary>Version ${options.version_latest} is available</div>
</paper-item-body>
</paper-icon-item>
<div class="update-row-actions" ?narrow=${false}>
<mwc-button>Releaese notes</mwc-button>
<mwc-button>Update</mwc-button>
</div>
</div>`;
}
private _renderUpdateCard(
name: string,
key: string,
@@ -231,31 +289,21 @@ export class HassioUpdate extends LitElement {
haStyle,
hassioStyle,
css`
.icon {
--mdc-icon-size: 48px;
float: right;
margin: 0 0 2px 10px;
color: var(--primary-text-color);
.update-row,
paper-icon-item {
display: flex;
align-items: center;
}
.update-heading {
font-size: var(--paper-font-subhead_-_font-size);
font-weight: 500;
margin-bottom: 0.5em;
color: var(--primary-text-color);
.update-row {
padding: 8px;
justify-content: space-between;
}
.card-content {
height: calc(100% - 47px);
box-sizing: border-box;
}
.card-actions {
text-align: right;
}
a {
text-decoration: none;
}
ha-settings-row {
padding: 0;
--paper-item-body-two-line-min-height: 32px;
.icon > * {
max-height: 32px;
max-width: 32px;
margin-right: 16px;
--mdc-icon-size: 32px;
}
`,
];

View File

@@ -1,190 +0,0 @@
import "@material/mwc-button/mwc-button";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import relativeTime from "../../../../src/common/datetime/relative_time";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/common/search/search-input";
import { compare } from "../../../../src/common/string/compare";
import { nextRender } from "../../../../src/common/util/render-status";
import "../../../../src/components/ha-circular-progress";
import { createCloseHeading } from "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-expansion-panel";
import "../../../../src/components/ha-settings-row";
import { extractApiErrorMessage } from "../../../../src/data/hassio/common";
import {
fetchHassioSnapshotInfo,
HassioPartialSnapshotCreateParams,
HassioSnapshotDetail,
supervisorRestorePartialSnapshot,
} from "../../../../src/data/hassio/snapshot";
import {
showAlertDialog,
showPromptDialog,
} from "../../../../src/dialogs/generic/show-dialog-box";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { HassioAddonRestoreDialogParams } from "./show-dialog-hassio-addon-restore";
@customElement("dialog-hassio-addon-restore")
class HassioAddonRestoreDialog extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@state() private _dialogParams?: HassioAddonRestoreDialogParams;
@state() private _snapshots?: HassioSnapshotDetail[];
@state() private _restoring = false;
public showDialog(params: HassioAddonRestoreDialogParams) {
this._dialogParams = params;
this._restoring = false;
Promise.all(
params.snapshots.map((snapshot) =>
fetchHassioSnapshotInfo(this.hass, snapshot.slug)
)
).then((data) => {
this._snapshots = data.sort((a, b) => compare(b.date, a.date));
});
}
public closeDialog() {
this._dialogParams = undefined;
this._snapshots = undefined;
this._restoring = false;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
if (!this._dialogParams || (!this._snapshots && !this._restoring)) {
return html``;
}
const snapshotCount = this._snapshots?.length || 0;
return html`
<ha-dialog
open
hideActions
@closed=${this.closeDialog}
.heading=${createCloseHeading(
this.hass,
this._dialogParams.supervisor.localize("dialog.addon_restore.title", {
name: this._dialogParams.addon.name,
})
)}
>
${this._restoring
? html`<div class="restore">
<ha-circular-progress size="large" active></ha-circular-progress>
<span
>${this._dialogParams.supervisor.localize(
"dialog.addon_restore.restore_in_progress"
)}
</span>
</div>`
: html`${this._dialogParams.supervisor.localize(
"dialog.addon_restore.description",
{
name: this._dialogParams.addon.name,
count: snapshotCount,
}
)}
${this._snapshots?.map(
(snapshot) =>
html`<ha-settings-row three-lines>
<span slot="heading">
${snapshot.name || snapshot.slug}
</span>
<span slot="description">
<div>
${this._dialogParams!.supervisor.localize(
"dialog.addon_restore.version",
{
version:
snapshot.addons.find(
(addon) =>
addon.slug === this._dialogParams?.addon.slug
)?.version ||
this._dialogParams!.supervisor.localize(
"dialog.addon_restore.no_version"
),
}
)}
</div>
${relativeTime(new Date(snapshot.date), this.hass.localize)}
</span>
<mwc-button
.snapshot=${snapshot}
@click=${this._restoreClicked}
>
${this._dialogParams!.supervisor.localize(
"dialog.addon_restore.restore"
)}
</mwc-button>
</ha-settings-row>`
)}`}
</ha-dialog>
`;
}
private async _restoreClicked(ev: CustomEvent) {
let password: string | null = null;
const snapshot: HassioSnapshotDetail = (ev.currentTarget as any).snapshot;
if (snapshot.protected) {
password = await showPromptDialog(this, {
text: this._dialogParams?.supervisor.localize(
"dialog.addon_restore.protected"
),
inputLabel: this._dialogParams?.supervisor.localize(
"dialog.addon_restore.password"
),
inputType: "password",
});
await nextRender();
if (!password) {
return;
}
}
this._restoring = true;
const data: HassioPartialSnapshotCreateParams = {
addons: [this._dialogParams!.addon.slug],
};
if (password) {
data.password = password;
}
try {
await supervisorRestorePartialSnapshot(this.hass, snapshot.slug, data);
} catch (err) {
await showAlertDialog(this, {
text: extractApiErrorMessage(err),
});
await nextRender();
return;
}
this._dialogParams?.onRestore();
this.closeDialog();
}
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
css`
.restore {
display: flex;
flex-direction: column;
align-items: center;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"dialog-hassio-addon-restore": HassioAddonRestoreDialog;
}
}

View File

@@ -1,22 +0,0 @@
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { HassioAddonDetails } from "../../../../src/data/hassio/addon";
import { HassioSnapshot } from "../../../../src/data/hassio/snapshot";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
export interface HassioAddonRestoreDialogParams {
supervisor: Supervisor;
snapshots: HassioSnapshot[];
addon: HassioAddonDetails;
onRestore: () => void;
}
export const showHassioAddonRestoreDialog = (
element: HTMLElement,
dialogParams: HassioAddonRestoreDialogParams
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-hassio-addon-restore",
dialogImport: () => import("./dialog-hassio-addon-restore"),
dialogParams,
});
};

View File

@@ -1,194 +0,0 @@
import { mdiClose } from "@mdi/js";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../src/common/dom/fire_event";
import "../../../../src/common/search/search-input";
import { compare } from "../../../../src/common/string/compare";
import "../../../../src/components/ha-dialog";
import "../../../../src/components/ha-expansion-panel";
import { HassioHardwareInfo } from "../../../../src/data/hassio/hardware";
import { dump } from "../../../../src/resources/js-yaml-dump";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { HassioHardwareDialogParams } from "./show-dialog-hassio-hardware";
const _filterDevices = memoizeOne(
(showAdvanced: boolean, hardware: HassioHardwareInfo, filter: string) =>
hardware.devices
.filter(
(device) =>
(showAdvanced ||
["tty", "gpio", "input"].includes(device.subsystem)) &&
(device.by_id?.toLowerCase().includes(filter) ||
device.name.toLowerCase().includes(filter) ||
device.dev_path.toLocaleLowerCase().includes(filter) ||
JSON.stringify(device.attributes)
.toLocaleLowerCase()
.includes(filter))
)
.sort((a, b) => compare(a.name, b.name))
);
@customElement("dialog-hassio-hardware")
class HassioHardwareDialog extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@state() private _dialogParams?: HassioHardwareDialogParams;
@state() private _filter?: string;
public showDialog(params: HassioHardwareDialogParams) {
this._dialogParams = params;
}
public closeDialog() {
this._dialogParams = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
protected render(): TemplateResult {
if (!this._dialogParams) {
return html``;
}
const devices = _filterDevices(
this.hass.userData?.showAdvanced || false,
this._dialogParams.hardware,
(this._filter || "").toLowerCase()
);
return html`
<ha-dialog
open
scrimClickAction
hideActions
@closed=${this.closeDialog}
.heading=${true}
>
<div class="header" slot="heading">
<h2>
${this._dialogParams.supervisor.localize("dialog.hardware.title")}
</h2>
<mwc-icon-button dialogAction="close">
<ha-svg-icon .path=${mdiClose}></ha-svg-icon>
</mwc-icon-button>
<search-input
autofocus
no-label-float
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
.label=${this._dialogParams.supervisor.localize(
"dialog.hardware.search"
)}
>
</search-input>
</div>
${devices.map(
(device) =>
html`<ha-expansion-panel
.header=${device.name}
.secondary=${device.by_id || undefined}
outlined
>
<div class="device-property">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.subsystem"
)}:
</span>
<span>${device.subsystem}</span>
</div>
<div class="device-property">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.device_path"
)}:
</span>
<code>${device.dev_path}</code>
</div>
${device.by_id
? html` <div class="device-property">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.id"
)}:
</span>
<code>${device.by_id}</code>
</div>`
: ""}
<div class="attributes">
<span>
${this._dialogParams!.supervisor.localize(
"dialog.hardware.attributes"
)}:
</span>
<pre>${dump(device.attributes, { indent: 2 })}</pre>
</div>
</ha-expansion-panel>`
)}
</ha-dialog>
`;
}
private _handleSearchChange(ev: CustomEvent) {
this._filter = ev.detail.value;
}
static get styles(): CSSResultGroup {
return [
haStyle,
haStyleDialog,
css`
mwc-icon-button {
position: absolute;
right: 16px;
top: 10px;
text-decoration: none;
color: var(--primary-text-color);
}
h2 {
margin: 18px 42px 0 18px;
color: var(--primary-text-color);
}
ha-expansion-panel {
margin: 4px 0;
}
pre,
code {
background-color: var(--markdown-code-background-color, none);
border-radius: 3px;
}
pre {
padding: 16px;
overflow: auto;
line-height: 1.45;
font-family: var(--code-font-family, monospace);
}
code {
font-size: 85%;
padding: 0.2em 0.4em;
}
search-input {
margin: 0 16px;
display: block;
}
.device-property {
display: flex;
justify-content: space-between;
}
.attributes {
margin-top: 12px;
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"dialog-hassio-hardware": HassioHardwareDialog;
}
}

View File

@@ -1,19 +0,0 @@
import { fireEvent } from "../../../../src/common/dom/fire_event";
import { HassioHardwareInfo } from "../../../../src/data/hassio/hardware";
import { Supervisor } from "../../../../src/data/supervisor/supervisor";
export interface HassioHardwareDialogParams {
supervisor: Supervisor;
hardware: HassioHardwareInfo;
}
export const showHassioHardwareDialog = (
element: HTMLElement,
dialogParams: HassioHardwareDialogParams
): void => {
fireEvent(element, "show-dialog", {
dialogTag: "dialog-hassio-hardware",
dialogImport: () => import("./dialog-hassio-hardware"),
dialogParams,
});
};

View File

@@ -22,7 +22,6 @@ import {
import { HassDialog } from "../../../../src/dialogs/make-dialog-manager";
import { haStyle, haStyleDialog } from "../../../../src/resources/styles";
import { HomeAssistant } from "../../../../src/types";
import { fileDownload } from "../../../../src/util/file_download";
import "../../components/supervisor-snapshot-content";
import type { SupervisorSnapshotContent } from "../../components/supervisor-snapshot-content";
import { HassioSnapshotDialogParams } from "./show-dialog-hassio-snapshot";
@@ -289,11 +288,12 @@ class HassioSnapshotDialog
}
}
fileDownload(
this,
signedPath.path,
`home_assistant_snapshot_${slugify(this._computeName)}.tar`
);
const a = document.createElement("a");
a.href = signedPath.path;
a.download = `home_assistant_snapshot_${slugify(this._computeName)}.tar`;
this.shadowRoot!.appendChild(a);
a.click();
this.shadowRoot!.removeChild(a);
}
private get _computeName() {

View File

@@ -97,23 +97,16 @@ class HassioIngressView extends LitElement {
title: requestedAddon,
});
await nextRender();
navigate("/hassio/store", { replace: true });
history.back();
return;
}
if (!addonInfo.version) {
await showAlertDialog(this, {
text: this.supervisor.localize("my.error_addon_not_installed"),
title: addonInfo.name,
});
await nextRender();
navigate(`/hassio/addon/${addonInfo.slug}/info`, { replace: true });
} else if (!addonInfo.ingress) {
if (!addonInfo.ingress) {
await showAlertDialog(this, {
text: this.supervisor.localize("my.error_addon_no_ingress"),
title: addonInfo.name,
});
await nextRender();
navigate(`/hassio/addon/${addonInfo.slug}/info`, { replace: true });
history.back();
} else {
navigate(`/hassio/ingress/${addonInfo.slug}`, { replace: true });
}

View File

@@ -2,6 +2,7 @@ import "@material/mwc-button";
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import "@material/mwc-list/mwc-list-item";
import { mdiDotsVertical } from "@mdi/js";
import { dump } from "js-yaml";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
@@ -40,8 +41,8 @@ import {
roundWithOneDecimal,
} from "../../../src/util/calculate";
import "../components/supervisor-metric";
import { showHassioMarkdownDialog } from "../dialogs/markdown/show-dialog-hassio-markdown";
import { showNetworkDialog } from "../dialogs/network/show-dialog-network";
import { showHassioHardwareDialog } from "../dialogs/hardware/show-dialog-hassio-hardware";
import { hassioStyle } from "../resources/hassio-style";
@customElement("hassio-host-info")
@@ -228,19 +229,20 @@ class HassioHostInfo extends LitElement {
}
private async _showHardware(): Promise<void> {
let hardware;
try {
hardware = await fetchHassioHardwareInfo(this.hass);
const content = await fetchHassioHardwareInfo(this.hass);
showHassioMarkdownDialog(this, {
title: this.supervisor.localize("system.host.hardware"),
content: `<pre>${dump(content, { indent: 2 })}</pre>`,
});
} catch (err) {
await showAlertDialog(this, {
showAlertDialog(this, {
title: this.supervisor.localize(
"system.host.failed_to_get_hardware_list"
),
text: extractApiErrorMessage(err),
});
return;
}
showHassioHardwareDialog(this, { supervisor: this.supervisor, hardware });
}
private async _hostReboot(ev: CustomEvent): Promise<void> {

View File

@@ -1,4 +1,5 @@
module.exports = {
"*.ts": () => "tsc -p tsconfig.json",
"*.{js,ts}": "eslint --fix",
"!(/translations)*.{js,ts,json,css,md,html}": "prettier --write",
};

View File

@@ -108,7 +108,7 @@
"fecha": "^4.2.0",
"fuse.js": "^6.0.0",
"google-timezones-json": "^1.0.2",
"hls.js": "^1.0.5",
"hls.js": "^1.0.4",
"home-assistant-js-websocket": "^5.10.0",
"idb-keyval": "^5.0.5",
"intl-messageformat": "^9.6.16",

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name="home-assistant-frontend",
version="20210603.0",
version="20210601.1",
description="The Home Assistant frontend",
url="https://github.com/home-assistant/home-assistant-polymer",
author="The Home Assistant Authors",

View File

@@ -1,16 +1,9 @@
import "@material/mwc-icon-button/mwc-icon-button";
import { mdiClose, mdiMagnify } from "@mdi/js";
import "@polymer/paper-input/paper-input";
import type { PaperInputElement } from "@polymer/paper-input/paper-input";
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property, query } from "lit/decorators";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import "../../components/ha-svg-icon";
import { fireEvent } from "../dom/fire_event";
@@ -34,11 +27,18 @@ class SearchInput extends LitElement {
this.shadowRoot!.querySelector("paper-input")!.focus();
}
@query("paper-input", true) private _input!: PaperInputElement;
protected render(): TemplateResult {
return html`
<style>
.no-underline:not(.focused) {
--paper-input-container-underline: {
display: none;
height: 0;
}
}
</style>
<paper-input
class=${classMap({ "no-underline": this.noUnderline })}
.autofocus=${this.autofocus}
.label=${this.label || "Search"}
.value=${this.filter}
@@ -62,17 +62,6 @@ class SearchInput extends LitElement {
`;
}
protected updated(changedProps: PropertyValues) {
if (
changedProps.has("noUnderline") &&
(this.noUnderline || changedProps.get("noUnderline") !== undefined)
) {
(this._input.inputElement!.parentElement!.shadowRoot!.querySelector(
"div.unfocused-line"
) as HTMLElement).style.display = this.noUnderline ? "none" : "block";
}
}
private async _filterChanged(value: string) {
fireEvent(this, "value-changed", { value: String(value) });
}

View File

@@ -14,17 +14,12 @@ class HaExpansionPanel extends LitElement {
@property() header?: string;
@property() secondary?: string;
@query(".container") private _container!: HTMLDivElement;
protected render(): TemplateResult {
return html`
<div class="summary" @click=${this._toggleContainer}>
<slot class="header" name="header">
${this.header}
<slot class="secondary" name="secondary">${this.secondary}</slot>
</slot>
<slot name="header">${this.header}</slot>
<ha-svg-icon
.path=${mdiChevronDown}
class="summary-icon ${classMap({ expanded: this.expanded })}"
@@ -111,16 +106,6 @@ class HaExpansionPanel extends LitElement {
.container.expanded {
height: auto;
}
.header {
display: block;
}
.secondary {
display: block;
color: var(--secondary-text-color);
font-size: 12px;
}
`;
}
}

View File

@@ -7,14 +7,14 @@ import { afterNextRender } from "../common/util/render-status";
import { FrontendLocaleData } from "../data/translation";
import { getValueInPercentage, normalize } from "../util/calculate";
// Workaround for https://github.com/home-assistant/frontend/issues/6467
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
const getAngle = (value: number, min: number, max: number) => {
const percentage = getValueInPercentage(normalize(value, min, max), min, max);
return (percentage * 180) / 100;
};
// Workaround for https://github.com/home-assistant/frontend/issues/6467
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
@customElement("ha-gauge")
export class Gauge extends LitElement {
@property({ type: Number }) public min = 0;

View File

@@ -13,11 +13,6 @@ import { nextRender } from "../common/util/render-status";
import { getExternalConfig } from "../external_app/external_config";
import type { HomeAssistant } from "../types";
type HlsLite = Omit<
HlsType,
"subtitleTrackController" | "audioTrackController" | "emeController"
>;
@customElement("ha-hls-player")
class HaHLSPlayer extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -44,7 +39,7 @@ class HaHLSPlayer extends LitElement {
@state() private _attached = false;
private _hlsPolyfillInstance?: HlsLite;
private _hlsPolyfillInstance?: HlsType;
private _useExoPlayer = false;
@@ -108,8 +103,7 @@ class HaHLSPlayer extends LitElement {
const useExoPlayerPromise = this._getUseExoPlayer();
const masterPlaylistPromise = fetch(this.url);
const Hls: typeof HlsType = (await import("hls.js/dist/hls.light.min.js"))
.default;
const Hls = (await import("hls.js")).default;
let hlsSupported = Hls.isSupported();
if (!hlsSupported) {
@@ -188,7 +182,7 @@ class HaHLSPlayer extends LitElement {
url: string
) {
const hls = new Hls({
backBufferLength: 60,
liveBackBufferLength: 60,
fragLoadingTimeOut: 30000,
manifestLoadingTimeOut: 30000,
levelLoadingTimeOut: 30000,

View File

@@ -14,17 +14,12 @@ interface HassioHardwareAudioList {
};
}
interface HardwareDevice {
attributes: Record<string, string>;
by_id: null | string;
dev_path: string;
name: string;
subsystem: string;
sysfs: string;
}
export interface HassioHardwareInfo {
devices: HardwareDevice[];
serial: string[];
input: string[];
disk: string[];
gpio: string[];
audio: Record<string, unknown>;
}
export const fetchHassioHardwareAudio = async (

View File

@@ -39,7 +39,7 @@ export interface HassioSnapshotDetail extends HassioSnapshot {
}
export interface HassioFullSnapshotCreateParams {
name?: string;
name: string;
password?: string;
}
export interface HassioPartialSnapshotCreateParams
@@ -194,26 +194,3 @@ export const uploadSnapshot = async (
}
return resp.json();
};
export const supervisorRestorePartialSnapshot = async (
hass: HomeAssistant,
slug: string,
data: HassioPartialSnapshotCreateParams
) => {
if (atLeastVersion(hass.config.version, 2021, 2, 4)) {
await hass.callWS({
type: "supervisor/api",
endpoint: `/snapshots/${slug}/restore/partial`,
method: "post",
timeout: null,
data,
});
return;
}
await hass.callApi<HassioResponse<void>>(
"POST",
`hassio/snapshots/${slug}/restore/partial`,
data
);
};

View File

@@ -23,6 +23,11 @@ class MoreInfoPerson extends LitElement {
}
return html`
<ha-attributes
.hass=${this.hass}
.stateObj=${this.stateObj}
extra-filters="id,user_id,editable"
></ha-attributes>
${this.stateObj.attributes.latitude && this.stateObj.attributes.longitude
? html`
<ha-map
@@ -46,11 +51,6 @@ class MoreInfoPerson extends LitElement {
</div>
`
: ""}
<ha-attributes
.hass=${this.hass}
.stateObj=${this.stateObj}
extra-filters="id,user_id,editable"
></ha-attributes>
`;
}

View File

@@ -17,6 +17,11 @@ class MoreInfoTimer extends LitElement {
}
return html`
<ha-attributes
.hass=${this.hass}
.stateObj=${this.stateObj}
extra-filters="remaining"
></ha-attributes>
<div class="actions">
${this.stateObj.state === "idle" || this.stateObj.state === "paused"
? html`
@@ -52,11 +57,6 @@ class MoreInfoTimer extends LitElement {
`
: ""}
</div>
<ha-attributes
.hass=${this.hass}
.stateObj=${this.stateObj}
extra-filters="remaining"
></ha-attributes>
`;
}

View File

@@ -48,9 +48,6 @@
window.providersPromise = fetch("/auth/providers", {
credentials: "same-origin",
});
if (!window.globalThis) {
window.globalThis = window;
}
</script>
<script>

View File

@@ -71,9 +71,6 @@
import("<%= latestAppJS %>");
window.customPanelJS = "<%= latestCustomPanelJS %>";
window.latestJS = true;
if (!window.globalThis) {
window.globalThis = window;
}
</script>
<script>
{% for extra_module in extra_modules -%}

View File

@@ -80,9 +80,6 @@
window.stepsPromise = fetch("/api/onboarding", {
credentials: "same-origin",
});
if (!window.globalThis) {
window.globalThis = window;
}
</script>
<script>

View File

@@ -9,12 +9,7 @@ import {
} from "../../../../../data/zha";
import "../../../../../layouts/hass-tabs-subpage";
import type { HomeAssistant, Route } from "../../../../../types";
import {
Network,
Edge,
Node,
EdgeOptions,
} from "vis-network/peer/esm/vis-network";
import { Network, Edge, Node, EdgeOptions } from "vis-network/peer";
import "../../../../../common/search/search-input";
import "../../../../../components/device/ha-device-picker";
import "../../../../../components/ha-button-menu";
@@ -26,7 +21,6 @@ import "../../../../../components/ha-checkbox";
import type { HaCheckbox } from "../../../../../components/ha-checkbox";
import { zhaTabs } from "./zha-config-dashboard";
import { customElement, property, query, state } from "lit/decorators";
import "../../../../../components/ha-formfield";
@customElement("zha-network-visualization-page")
export class ZHANetworkVisualizationPage extends LitElement {
@@ -34,7 +28,7 @@ export class ZHANetworkVisualizationPage extends LitElement {
@property({ attribute: false }) public route!: Route;
@property({ type: Boolean, reflect: true }) public narrow!: boolean;
@property({ type: Boolean }) public narrow!: boolean;
@property({ type: Boolean }) public isWide!: boolean;
@@ -73,6 +67,8 @@ export class ZHANetworkVisualizationPage extends LitElement {
{},
{
autoResize: true,
height: window.innerHeight + "px",
width: window.innerWidth + "px",
layout: {
improvedLayout: true,
},
@@ -139,35 +135,17 @@ export class ZHANetworkVisualizationPage extends LitElement {
"ui.panel.config.zha.visualization.header"
)}
>
${this.narrow
? html`
<div slot="header">
<search-input
no-label-float
no-underline
class="header"
@value-changed=${this._handleSearchChange}
.filter=${this._filter}
.label=${this.hass.localize(
"ui.panel.config.zha.visualization.highlight_label"
)}
>
</search-input>
</div>
`
: ""}
<div class="header">
${!this.narrow
? html`<search-input
no-label-float
no-underline
@value-changed=${this._handleSearchChange}
.filter=${this._filter}
.label=${this.hass.localize(
"ui.panel.config.zha.visualization.highlight_label"
)}
></search-input>`
: ""}
<div class="table-header">
<search-input
no-label-float
no-underline
@value-changed=${this._handleSearchChange}
.filter=${this._filter}
.label=${this.hass.localize(
"ui.panel.config.zha.visualization.highlight_label"
)}
>
</search-input>
<ha-device-picker
.hass=${this.hass}
.value=${this.zoomedDeviceId}
@@ -177,24 +155,16 @@ export class ZHANetworkVisualizationPage extends LitElement {
.deviceFilter=${(device) => this._filterDevices(device)}
@value-changed=${this._onZoomToDevice}
></ha-device-picker>
<div class="controls">
<ha-formfield
.label=${this.hass!.localize(
"ui.panel.config.zha.visualization.auto_zoom"
)}
>
<ha-checkbox
@change=${this._handleCheckboxChange}
.checked=${this._autoZoom}
>
</ha-checkbox>
</ha-formfield>
<mwc-button @click=${this._refreshTopology}>
${this.hass!.localize(
"ui.panel.config.zha.visualization.refresh_topology"
)}
</mwc-button>
</div>
<ha-checkbox
@change=${this._handleCheckboxChange}
.checked=${this._autoZoom}
></ha-checkbox
>${this.hass!.localize("ui.panel.config.zha.visualization.auto_zoom")}
<mwc-button @click=${this._refreshTopology}
>${this.hass!.localize(
"ui.panel.config.zha.visualization.refresh_topology"
)}</mwc-button
>
</div>
<div id="visualization"></div>
</hass-tabs-subpage>
@@ -382,23 +352,30 @@ export class ZHANetworkVisualizationPage extends LitElement {
return [
css`
.header {
border-bottom: 1px solid var(--divider-color);
padding: 0 8px;
font-family: var(--paper-font-display1_-_font-family);
-webkit-font-smoothing: var(
--paper-font-display1_-_-webkit-font-smoothing
);
font-size: var(--paper-font-display1_-_font-size);
font-weight: var(--paper-font-display1_-_font-weight);
letter-spacing: var(--paper-font-display1_-_letter-spacing);
line-height: var(--paper-font-display1_-_line-height);
opacity: var(--dark-primary-opacity);
}
.table-header {
border-bottom: 1px solid --divider-color;
padding: 0 16px;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: row;
height: var(--header-height);
box-sizing: border-box;
}
.header > * {
padding: 0 8px;
}
:host([narrow]) .header {
:host([narrow]) .table-header {
flex-direction: column;
align-items: stretch;
height: var(--header-height) * 2;
height: var(--header-height) * 3;
}
.search-toolbar {
@@ -409,34 +386,34 @@ export class ZHANetworkVisualizationPage extends LitElement {
}
search-input {
position: relative;
top: 2px;
flex: 1;
}
:host(:not([narrow])) search-input {
margin: 5px;
}
search-input.header {
display: block;
position: relative;
top: -2px;
color: var(--secondary-text-color);
left: -8px;
}
ha-device-picker {
flex: 1;
position: relative;
top: -4px;
}
.controls {
display: flex;
align-items: center;
justify-content: space-between;
:host(:not([narrow])) ha-device-picker {
margin: 5px;
}
#visualization {
height: calc(100% - var(--header-height));
width: 100%;
mwc-button {
font-weight: 500;
color: var(--primary-color);
}
:host([narrow]) #visualization {
height: calc(100% - (var(--header-height) * 2));
:host(:not([narrow])) mwc-button {
margin: 5px;
}
`,
];

View File

@@ -24,7 +24,6 @@ import {
import "../../../../../layouts/hass-tabs-subpage";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant, Route } from "../../../../../types";
import { fileDownload } from "../../../../../util/file_download";
import "../../../ha-config-section";
import { showZWaveJSAddNodeDialog } from "./show-dialog-zwave_js-add-node";
import { showZWaveJSRemoveNodeDialog } from "./show-dialog-zwave_js-remove-node";
@@ -313,7 +312,12 @@ class ZWaveJSConfigDashboard extends LitElement {
return;
}
fileDownload(this, signedPath.path, `zwave_js_dump.jsonl`);
const a = document.createElement("a");
a.href = signedPath.path;
a.download = `zwave_js_dump.jsonl`;
this.shadowRoot!.appendChild(a);
a.click();
this.shadowRoot!.removeChild(a);
}
static get styles(): CSSResultGroup {

View File

@@ -36,9 +36,7 @@ export class HaPickThemeRow extends LitElement {
const hasThemes =
this.hass.themes.themes && Object.keys(this.hass.themes.themes).length;
const curTheme =
this.hass.selectedTheme?.theme || this.hass.themes.darkMode
? this.hass.themes.default_dark_theme || this.hass.themes.default_theme
: this.hass.themes.default_theme;
this.hass.selectedTheme?.theme || this.hass.themes.default_theme;
const themeSettings = this.hass.selectedTheme;

View File

@@ -1,10 +1,10 @@
// For localize
import "core-js";
import "regenerator-runtime/runtime";
import "lit/polyfill-support";
import "@formatjs/intl-getcanonicallocales/polyfill";
import "lit/polyfill-support";
import "core-js";
// To use comlink under ES5
import "proxy-polyfill";
import "regenerator-runtime/runtime";
import "unfetch/polyfill";
// Source: https://github.com/jserz/js_piece/blob/master/DOM/ParentNode/append()/append().md
@@ -32,16 +32,3 @@ import "unfetch/polyfill";
});
});
})([Element.prototype, Document.prototype, DocumentFragment.prototype]);
// Source: https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNames
if (Element.prototype.getAttributeNames === undefined) {
Element.prototype.getAttributeNames = function () {
const attributes = this.attributes;
const length = attributes.length;
const result = new Array(length);
for (let i = 0; i < length; i++) {
result[i] = attributes[i].name;
}
return result;
};
}

View File

@@ -2,7 +2,6 @@
const isSafari14 = /^((?!chrome|android).)*version\/14\.0\s.*safari/i.test(
navigator.userAgent
);
if (isSafari14) {
const origAttachShadow = window.Element.prototype.attachShadow;
window.Element.prototype.attachShadow = function (init) {

View File

@@ -1155,7 +1155,7 @@
"section": {
"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",
"check_config": "Check configuration",
"valid": "Configuration valid!",
"invalid": "Configuration invalid"
@@ -3630,7 +3630,6 @@
"restart": "restart",
"start": "start",
"stop": "stop",
"restore": "restore",
"install": "install",
"uninstall": "uninstall",
"rebuild": "rebuild",
@@ -3814,8 +3813,6 @@
"faq_link": "[%key:ui::panel::my::faq_link%]",
"error": "[%key:ui::panel::my::error%]",
"error_addon_not_found": "Add-on not found",
"error_addon_not_started": "The requested add-on are not running. Please start it first",
"error_addon_not_installed": "The requested add-on is not installed. Please install it first",
"error_addon_no_ingress": "The requested add-on does not support ingress"
},
"system": {
@@ -3981,24 +3978,6 @@
"create_snapshot": "Create a snapshot of {name} before updating",
"updating": "Updating {name} to version {version}",
"snapshotting": "Creating snapshot of {name}"
},
"addon_restore": {
"title": "Restore {name}",
"description": "You have {count, plural,\n one {one snapshot}\n other {{count} snapshots}\n} that includes restore points for {name}",
"version": "Version {version}",
"no_version": "No version",
"restore": "Restore",
"enter_password": "[%key:supervisor::snapshot::enter_password%]",
"protected": "The snapshot is password protected, please provide the password for it.",
"restore_in_progress": "Restore in progress"
},
"hardware": {
"title": "Hardware",
"search": "Search hardware",
"subsystem": "Subsystem",
"id": "ID",
"attributes": "Attributes",
"device_path": "Device path"
}
}
}

View File

@@ -1,14 +0,0 @@
export const fileDownload = (
element: HTMLElement,
href: string,
filename: string
): void => {
const a = document.createElement("a");
a.target = "_blank";
a.href = href;
a.download = filename;
element.shadowRoot!.appendChild(a);
a.dispatchEvent(new MouseEvent("click"));
element.shadowRoot!.removeChild(a);
};

View File

View File

@@ -351,9 +351,6 @@
"create_blocked_not_running": "Създаването на снапшот в момента не е възможно, тъй като системата е в състояние {state}.",
"create_snapshot": "Създаване на снапшот",
"created": "Създаден",
"delete_selected": "Изтриване на избраните снапшоти",
"delete_snapshot_confirm": "Изтрий",
"delete_snapshot_title": "Изтриване на снапшот",
"description": "Снапшотите ви позволяват лесно да архивирате и възстановявате всички данни от вашия екземпляр на Home Assistant.",
"enter_password": "Моля, въведете парола.",
"folder": {
@@ -372,7 +369,6 @@
"password_protected": "защитен с парола",
"password_protection": "Защита с парола",
"security": "Сигурност",
"selected": "{number} избрани",
"type": "Тип",
"upload_snapshot": "Качване на снапшот"
},
@@ -498,7 +494,7 @@
"heating": "{name} отопление",
"high": "високо",
"low": "ниско",
"on_off": "Вкл. / Изкл.",
"on_off": "Вкл. / Изкл",
"operation": "Режим",
"preset_mode": "Предварително зададени настройки",
"swing_mode": "Режим на люлеене",
@@ -878,7 +874,6 @@
"config_entry_system_options": {
"enable_new_entities_description": "Ако е изключено, новооткритите обекти за {integration} няма да бъдат автоматично добавяни в Home Assistant",
"enable_new_entities_label": "Активирай новодобавените обекти.",
"restart_home_assistant": "Трябва да рестартирате Home Assistant, за да влязат в сила промените.",
"title": "Системни опции за {integration}",
"update": "Актуализация"
},
@@ -2098,7 +2093,7 @@
"confirm_delete_ignore_title": "Да се спре ли игнорирането на {name}?",
"confirm_ignore": "Наистина ли не искате да настроите тази интеграция? Можете да отмените това, като кликнете върху „Показване на игнорирани интеграции“ в менюто горе вдясно.",
"hide_ignored": "Скриване на игнорираните интеграции",
"ignore": "Игнориране",
"ignore": "Игнорирайте",
"ignored": "Игнорирана",
"show_ignored": "Показване на игнорираните интеграции",
"stop_ignore": "Спрете да игнорирате"

View File

@@ -284,7 +284,7 @@
"refresh": "Actualitza",
"release_notes": "Notes de la versió",
"reload": "Torna a carregar",
"reset_defaults": "Restableix els valors per defecte",
"reset_defaults": "Restableix als valors per defecte",
"reset_options": "Opcions de reinici",
"restart": "Reinicia",
"restart_name": "Reinicia {name}",
@@ -368,8 +368,6 @@
"error": "S'ha produït un error desconegut",
"error_addon_no_ingress": "El complement sol·licitat no admet ingress",
"error_addon_not_found": "No s'ha trobat el complement",
"error_addon_not_installed": "El complement sol·licitat no està instal·lat. Instal·la'l primer",
"error_addon_not_started": "El complement sol·licitat no s'està executant. Inicia'l primer",
"faq_link": "Preguntes freqüents de My Home Assistant",
"not_supported": "La instància de Home Assistant no admet aquesta redirecció. Consulta {link} per veure les redireccions compatibles i en quina versió es van introduir."
},
@@ -1393,7 +1391,7 @@
"type_select": "Tipus de repetició",
"type": {
"count": {
"label": "Comptador"
"label": "Compta"
},
"until": {
"conditions": "Condicions de \"Fins que\"",
@@ -2721,7 +2719,7 @@
"validation": {
"check_config": "Comprova la configuració",
"heading": "Validació de la configuració",
"introduction": "Valida la configuració si recentment n'has fet algun canvi i vols assegurar-te de que sigui vàlida.",
"introduction": "Valida la configuració si recentment has fet algun canvi a la configuració i vols assegurar-te de que sigui vàlida.",
"invalid": "Configuració invàlida",
"valid": "Configuració vàlida!"
}
@@ -3716,7 +3714,7 @@
},
"page-authorize": {
"abort_intro": "S'ha avortat l'inici de sessió",
"authorizing_client": "Estàs a punt de concedir al client {clientId} l'accés a la teva instància de Home Assistant.",
"authorizing_client": "Esteu a punt de permetre l'accés a la vostra instància de Home Assistant al client {clientId}.",
"form": {
"error": "Error: {error}",
"next": "Següent",
@@ -3810,7 +3808,7 @@
"working": "Si us plau, espereu"
},
"initializing": "S'està inicialitzant",
"logging_in_to_with": "Iniciant sessió a **{locationName}** amb **{authProviderName}**.",
"logging_in_to_with": "S'escriuen els registes amb **{authProviderName}** a **{locationName}**.",
"logging_in_with": "Iniciant sessió amb **{authProviderName}**.",
"pick_auth_provider": "O bé inicieu sessió amb"
},

View File

@@ -368,8 +368,6 @@
"error": "Nastala neznámá chyba",
"error_addon_no_ingress": "Požadovaný doplněk nepodporuje ingress",
"error_addon_not_found": "Doplněk nebyl nalezen",
"error_addon_not_installed": "Požadovaný doplněk není nainstalován. Nejprve jej prosím nainstalujte",
"error_addon_not_started": "Požadovaný doplněk není spuštěn. Nejprve jej prosím spusťte",
"faq_link": "Časté dotazy týkající se My Home Assistant",
"not_supported": "Toto přesměrování není vaší instancí Home Assistant podporováno. Zkontrolujte {link} pro podporovaná přesměrování a verzi, ve které byla zavedena."
},
@@ -931,11 +929,8 @@
},
"dialogs": {
"config_entry_system_options": {
"enable_new_entities_description": "Pokud se mají automaticky přidat nově objevená zařízení integrace {integration}.",
"enable_new_entities_description": "Pokud je zakázáno, nově objevené entity pro {integration} nebudou automaticky přidány do Home Assistant.",
"enable_new_entities_label": "Povolit nově přidané entity.",
"enable_polling_description": "Má-li Home Assistant automaticky zjišťovat aktualizace entit integrace {integration}.",
"enable_polling_label": "Povolit dotazování na aktualizace.",
"restart_home_assistant": "Aby se změny projevily, je třeba restartovat Home Assistant.",
"title": "Upravit nastavení pro {integration}",
"update": "Aktualizovat"
},
@@ -1169,7 +1164,7 @@
},
"types": {
"navigation": "Navigovat",
"reload": "Nově načíst",
"reload": "Znovu načíst",
"server_control": "Server"
}
},
@@ -2078,8 +2073,7 @@
"scripts": "Skripty",
"unknown_error": "Neznámá chyba",
"unnamed_device": "Nepojmenované zařízení",
"update": "Aktualizovat",
"update_device_error": "Aktualizace zařízení se nezdařila"
"update": "Aktualizovat"
},
"entities": {
"caption": "Entity",
@@ -2212,7 +2206,6 @@
"depends_on_cloud": "Závisí na cloudu",
"device_unavailable": "Zařízení není dostupné",
"devices": "{count} {count, plural,\n one {zařízení}\n other {zařízení}\n}",
"disable_error": "Povolení nebo zakázání integrace se nezdařilo",
"disable_restart_confirm": "Restartujte Home Assistant pro dokončení odstranění této integrace",
"disable": {
"disable_confirm": "Opravdu chcete zakázat tuto položku konfigurace? Její zařízení a entity budou zakázány.",
@@ -2224,7 +2217,6 @@
},
"disabled_cause": "Zakázáno {cause}"
},
"disabled_polling": "Automatické dotazování na aktualizovaná data je zakázáno",
"documentation": "Dokumentace",
"enable_restart_confirm": "Restartujte Home Assistant pro dokončení přidání této integrace",
"entities": "{count} {count, plural,\n one {entita}\n other {entit}\n}",
@@ -2721,7 +2713,7 @@
"validation": {
"check_config": "Zkontrolujte konfiguraci",
"heading": "Ověření konfigurace",
"introduction": "Pokud jste nedávno provedli nějaké změny v konfiguraci a chcete se ujistit, že jsou všechny platné, proveďte ověření konfigurace.",
"introduction": "Pokud jste nedávno provedli změny konfigurace a chcete se ujistit, že je vše v pořádku, můžete zde konfiguraci ověřit",
"invalid": "Konfigurace není v pořádku!",
"valid": "Konfigurace je v pořádku!"
}
@@ -2936,7 +2928,6 @@
"follow_device_instructions": "Podle pokynů dodaných se zařízením aktivujte párování na zařízení.",
"inclusion_failed": "Uzel nelze přidat. Další informace najdete v protokolech.",
"inclusion_finished": "Uzel byl přidán.",
"interview_failed": "Komunikace se zařízením se nezdařila. V logách mohou být k dispozici další informace.",
"introduction": "Tento průvodce vás provede přidáním uzlu do vaší sítě Z-Wave.",
"secure_inclusion_warning": "Zabezpečená zařízení vyžadují větší šířku pásma; příliš mnoho zabezpečených zařízení může zpomalit vaši síť Z-Wave. Bezpečné začlenění doporučujeme používat pouze u zařízení, která to vyžadují, jako jsou zámky nebo otvírače garážových vrat.",
"start_inclusion": "Zahájit začlenění",
@@ -3101,7 +3092,7 @@
"heal_node": "Uzdravit uzel",
"node_info": "Informace o uzlu",
"print_node": "Otisk uzlu",
"refresh_entity": "Nově načíst Entitu",
"refresh_entity": "Znovu načíst Entitu",
"refresh_node": "Obnovit uzel",
"remove_failed_node": "Odebrat selhaný uzel",
"remove_node": "Odebrat uzel",
@@ -3166,7 +3157,6 @@
"copy_id": "Zkopírovat ID do schránky",
"current_entities": "Současné entity",
"description1": "Nastavte stav zařízení v Home Assistant.",
"description2": "Pokud entita patří k zařízení, neprobíhá s tímto zařízením žádná skutečná komunikace.",
"entity": "Entita",
"filter_attributes": "Filtrovat atributy",
"filter_entities": "Filtrovat entity",

View File

@@ -368,8 +368,6 @@
"error": "Ein unbekannter Fehler ist aufgetreten.",
"error_addon_no_ingress": "Das angeforderte Add-on unterstützt keinen Ingress",
"error_addon_not_found": "Add-on nicht gefunden",
"error_addon_not_installed": "Das angeforderte Add-on ist nicht installiert. Bitte installiere es zuerst",
"error_addon_not_started": "Das angeforderte Add-on läuft nicht. Bitte starte es zuerst",
"faq_link": "Häufig gestellten Fragen zu Home Assistant",
"not_supported": "Diese Weiterleitung wird von deiner Home Assistant-Instanz nicht unterstützt. Überprüfe den {link} auf die unterstützten Weiterleitungen und die Version, in der sie eingeführt wurden."
},
@@ -387,13 +385,8 @@
"create_blocked_not_running": "Das Erstellen eines Snapshots ist derzeit nicht möglich, da sich das System im Zustand {state} befindet.",
"create_snapshot": "Datensicherung erstellen",
"created": "Erstellt",
"delete_selected": "Ausgewählten Snapshot löschen",
"delete_snapshot_confirm": "löschen",
"delete_snapshot_text": "Möchtest du {number} {number, plural,\n one {den Snapshot}\n other {die Snapshots}\n} löschen?",
"delete_snapshot_title": "Snapshot löschen",
"description": "Datensicherungen ermöglichen dir das leichte Speichern und Wiederherstellen von allen Daten aus Home Assistant.",
"enter_password": "Bitte Passwort eingeben.",
"failed_to_delete": "Löschen fehlgeschlagen",
"folder": {
"addons/local": "Lokale Add-ons",
"homeassistant": "Home Assistant-Konfiguration",
@@ -410,8 +403,6 @@
"password_protected": "Passwort geschützt",
"password_protection": "Passwortschutz",
"security": "Sicherheit",
"select_type": "Wähle aus, was wiederhergestellt werden soll",
"selected": "{number} ausgewählt",
"type": "Typ",
"upload_snapshot": "Datensicherung hochladen"
},
@@ -729,9 +720,6 @@
"no_match": "Keine übereinstimmende Bereiche gefunden",
"show_areas": "Bereiche anzeigen"
},
"attributes": {
"expansion_header": "Attribute"
},
"blueprint-picker": {
"add_user": "Benutzer hinzufügen",
"remove_user": "Benutzer entfernen",
@@ -933,9 +921,6 @@
"config_entry_system_options": {
"enable_new_entities_description": "Wenn deaktiviert werden neu erkannte Entitäten für {integration} nicht automatisch zu Home Assistant hinzugefügt.",
"enable_new_entities_label": "Neu hinzugefügte Entitäten aktivieren.",
"enable_polling_description": "Ob Home Assistant automatisch {integration} Entitäten nach Updates abfragen soll.",
"enable_polling_label": "Aktiviere Polling für Updates.",
"restart_home_assistant": "Du musst Home Assistant neu starten, damit deine Änderungen wirksam werden.",
"title": "Einstellungen für {integration}",
"update": "Aktualisieren"
},
@@ -1734,7 +1719,6 @@
"title": "Alexa"
},
"connected": "Verbunden",
"connecting": "Verbinde...",
"connection_status": "Cloud-Verbindungsstatus",
"fetching_subscription": "Abo wird abgerufen ...",
"google": {
@@ -2078,8 +2062,7 @@
"scripts": "Skripte",
"unknown_error": "Unbekannter Fehler",
"unnamed_device": "Unbenanntes Gerät",
"update": "Aktualisieren",
"update_device_error": "Aktualisieren des Geräts fehlgeschlagen"
"update": "Aktualisieren"
},
"entities": {
"caption": "Entitäten",
@@ -2212,7 +2195,6 @@
"depends_on_cloud": "Abhängig von der Cloud",
"device_unavailable": "Gerät nicht verfügbar",
"devices": "{count} {count, plural,\n one {Gerät}\n other {Geräte}\n}",
"disable_error": "Aktivieren oder Deaktivieren der Integration fehlgeschlagen",
"disable_restart_confirm": "Home Assistant neu starten, um das Deaktivieren dieser Integration abzuschließen",
"disable": {
"disable_confirm": "Möchtest du diesen Konfigurationseintrag wirklich deaktivieren? Die Geräte und Entitäten werden deaktiviert.",
@@ -2224,7 +2206,6 @@
},
"disabled_cause": "Deaktiviert durch {cause}."
},
"disabled_polling": "Automatisches Abfragen nach aktualisierten Daten deaktiviert",
"documentation": "Dokumentation",
"enable_restart_confirm": "Home Assistant neu starten, um das Aktivieren dieser Integration abzuschließen",
"entities": "{count} {count, plural,\none {Entität}\nother {Entitäten}\n}",
@@ -2978,7 +2959,6 @@
},
"logs": {
"log_level": "Protokollstufe",
"log_level_changed": "Log Level geändert auf: {level}",
"subscribed_to_logs": "Abonniert Z-Wave JS-Protokollnachrichten ...",
"title": "Z-Wave JS Protokolle"
},

View File

@@ -368,8 +368,6 @@
"error": "An unknown error occurred",
"error_addon_no_ingress": "The requested add-on does not support ingress",
"error_addon_not_found": "Add-on not found",
"error_addon_not_installed": "The requested add-on is not installed. Please install it first",
"error_addon_not_started": "The requested add-on are not running. Please start it first",
"faq_link": "My Home Assistant FAQ",
"not_supported": "This redirect is not supported by your Home Assistant instance. Check the {link} for the supported redirects and the version they where introduced."
},
@@ -2721,7 +2719,7 @@
"validation": {
"check_config": "Check configuration",
"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",
"invalid": "Configuration invalid",
"valid": "Configuration valid!"
}

View File

@@ -367,8 +367,6 @@
"my": {
"error": "Ha ocurrido un error desconocido",
"error_addon_not_found": "Complemento no encontrado",
"error_addon_not_installed": "El complemento solicitado no está instalado. Por favor instálelo primero",
"error_addon_not_started": "El complemento solicitado no se están ejecutando. Por favor inícielo antes.",
"faq_link": "Mis preguntas frecuentes de Home Assistant",
"not_supported": "Esta redirección no está soportada por su instancia de Home Assistant. Consulte las redirecciones soportadas y la versión en la que fueron introducidas en {link}."
},
@@ -2033,8 +2031,7 @@
"scripts": "Scripts",
"unknown_error": "Error desconocido",
"unnamed_device": "Dispositivo sin nombre",
"update": "Actualizar",
"update_device_error": "Error al actualizar el dispositivo"
"update": "Actualizar"
},
"entities": {
"caption": "Entidades",
@@ -2166,7 +2163,6 @@
"depends_on_cloud": "Depende de la nube",
"device_unavailable": "Dispositivo no disponible",
"devices": "{count} {count, plural,\n one {dispositivo}\n other {dispositivos}\n}",
"disable_error": "Ha fallado la habilitación o deshabilitación de la integración",
"disable_restart_confirm": "Reinicie Home Assistant para terminar de deshabilitar esta integración",
"disable": {
"disable_confirm": "¿Está seguro de que desea deshabilitar esta entrada de configuración? Sus dispositivos y entidades serán deshabilitados.",

View File

@@ -368,8 +368,6 @@
"error": "Se ha producido un error desconocido",
"error_addon_no_ingress": "El complemento solicitado no admite la entrada",
"error_addon_not_found": "Complemento no encontrado",
"error_addon_not_installed": "El complemento solicitado no está instalado. Por favor instálalo primero",
"error_addon_not_started": "El complemento solicitado no se está ejecutando. Por favor, inícialo primero",
"faq_link": "Preguntas frecuentes sobre mi Home Assistant",
"not_supported": "Esta redirección no es compatible con tu instancia de Home Assistant. Consulta el {link} para conocer las redirecciones admitidas y la versión en la que se introdujeron."
},
@@ -2078,8 +2076,7 @@
"scripts": "Scripts",
"unknown_error": "Error desconocido",
"unnamed_device": "Dispositivo sin nombre",
"update": "Actualizar",
"update_device_error": "Error al actualizar el dispositivo"
"update": "Actualizar"
},
"entities": {
"caption": "Entidades",
@@ -2212,7 +2209,6 @@
"depends_on_cloud": "Depende de la nube",
"device_unavailable": "Dispositivo no disponible",
"devices": "{count} {count, plural,\n one {dispositivo}\n other {dispositivos}\n}",
"disable_error": "Error al habilitar o deshabilitar la integración",
"disable_restart_confirm": "Reinicia Home Assistant para terminar de deshabilitar esta integración",
"disable": {
"disable_confirm": "¿Estás seguro de que deseas deshabilitar esta entrada de configuración? Sus dispositivos y entidades estarán deshabilitados.",
@@ -2721,7 +2717,7 @@
"validation": {
"check_config": "Verificar configuración",
"heading": "Validación de la configuración",
"introduction": "Valida tu configuración si has realizado cambios recientemente en ella y quieres asegurarte de que son correctos",
"introduction": "Valida tu configuración si has realizado cambios recientemente y quieres asegurarte de que son correctos",
"invalid": "Configuración no válida",
"valid": "¡Configuración valida!"
}

View File

@@ -368,8 +368,6 @@
"error": "Viga",
"error_addon_no_ingress": "Valitud lisandmoodul ei toeta ingressi",
"error_addon_not_found": "Lisandmoodulit ei leitud",
"error_addon_not_installed": "Soovitud lisandmoodul pole pigaldatud. Alustamiseks paigalda see",
"error_addon_not_started": "Soovitud lisandmoodul ei tööta. Alustamiseks käivita see",
"faq_link": "KKK viide",
"not_supported": "pole toetatud"
},
@@ -931,7 +929,7 @@
},
"dialogs": {
"config_entry_system_options": {
"enable_new_entities_description": "Kas lisada äsja avastatud sidumise {integration} olemeid automaatselt Home Assistant'i.",
"enable_new_entities_description": "Kas lisada äsja avastatud sidumise {integration} olemed automaatselt Home Assistant'i.",
"enable_new_entities_label": "Luba äsja lisatud olemid.",
"enable_polling_description": "Kas Home Assistant peaks automaatselt küsitlema {integration} üksusi uuenduste saamiseks.",
"enable_polling_label": "Luba värskenduste jaoks küsitlus.",
@@ -2078,8 +2076,7 @@
"scripts": "Skriptid",
"unknown_error": "Tundmatu viga",
"unnamed_device": "Nimetu seade",
"update": "Uuenda",
"update_device_error": "Seadme värskendamine nurjus"
"update": "Uuenda"
},
"entities": {
"caption": "Olemite register",
@@ -2212,7 +2209,6 @@
"depends_on_cloud": "Sõltub pilveteenusest",
"device_unavailable": "Seade pole saadaval",
"devices": "{count} {count, plural,\n one {seade}\n other {seadet}\n}",
"disable_error": "Sidumise lubamine või keelamine nurjus",
"disable_restart_confirm": "Taaskäivita Home Assistant, et lõpetada selle sidumise keelamine",
"disable": {
"disable_confirm": "Kas soovid selle seadistuskirje kindlasti keelata? Selle seadmed ja üksused keelatakse.",
@@ -2721,7 +2717,7 @@
"validation": {
"check_config": "Kontrolli seadeid",
"heading": "Seadete kontrollimine",
"introduction": "Kontrolli oma seadeid kui oled neis hiljuti muutusi teinud ja tahad veenduda, et kõik on korrektne.",
"introduction": "Kontrolli oma seadeid kui oled neis hiljuti muutusi teinud ja tahad veenduda, et kõik on korrektne",
"invalid": "Konfiguratsioon on vigane",
"valid": "Konfiguratsioon on korrektne!"
}

File diff suppressed because it is too large Load Diff

View File

@@ -368,8 +368,6 @@
"error": "Si è verificato un errore sconosciuto",
"error_addon_no_ingress": "Il componente aggiuntivo richiesto non supporta l'ingresso",
"error_addon_not_found": "Componente aggiuntivo non trovato",
"error_addon_not_installed": "Il componente aggiuntivo richiesto non è installato. Si prega di installarlo prima di proseguire",
"error_addon_not_started": "Il componente aggiuntivo non è in esecuzione. Si prega di avviarlo prima di proseguire",
"faq_link": "My Home Assistant FAQ",
"not_supported": "Questo reindirizzamento non è supportato dall'istanza di Home Assistant. Controlla il {link} per i reindirizzamenti supportati e la versione in cui sono stati introdotti."
},
@@ -413,7 +411,7 @@
"select_type": "Seleziona cosa ripristinare",
"selected": "{number} selezionato/i",
"type": "Tipo di istantanea",
"upload_snapshot": "Aggiungi istantanea"
"upload_snapshot": "Invia istantanea"
},
"store": {
"missing_addons": "Componenti aggiuntivi mancanti? Abilita la modalità avanzata nella pagina del tuo profilo utente",
@@ -2078,8 +2076,7 @@
"scripts": "Script",
"unknown_error": "Errore sconosciuto",
"unnamed_device": "Dispositivo senza nome",
"update": "Aggiorna",
"update_device_error": "Aggiornamento del dispositivo non riuscito"
"update": "Aggiorna"
},
"entities": {
"caption": "Entità",
@@ -2212,7 +2209,6 @@
"depends_on_cloud": "Dipende dal cloud",
"device_unavailable": "Dispositivo non disponibile",
"devices": "{count} {count, plural, \none {dispositivo}\nother {dispositivi}\n}",
"disable_error": "Abilitazione o disabilitazione dell'integrazione non riuscita",
"disable_restart_confirm": "Riavvia Home Assistant per terminare la disabilitazione di questa integrazione",
"disable": {
"disable_confirm": "Sei sicuro di voler disabilitare questa voce di configurazione? I suoi dispositivi ed entità saranno disabilitati.",

View File

@@ -368,8 +368,6 @@
"error": "알 수 없는 오류가 발생했습니다",
"error_addon_no_ingress": "해당 애드온은 인그레스를 지원하지 않습니다.",
"error_addon_not_found": "애드온을 찾을 수 없습니다",
"error_addon_not_installed": "해당 애드온은 설치되어있지 않습니다. 애드온을 설치해주세요.",
"error_addon_not_started": "해당 애드온은 실행중이지 않습니다. 애드온을 실행해주세요.",
"faq_link": "내 Home Assistant 자주 묻는 질문",
"not_supported": "이 리디렉션은 Home Assistant 인스턴스에서 지원되지 않습니다. {link}에서 지원되는 리디렉션과 리디렉션이 도입된 버전을 확인해주세요."
},
@@ -389,7 +387,7 @@
"created": "생성됨",
"delete_selected": "선택한 스냅샷 삭제",
"delete_snapshot_confirm": "삭제",
"delete_snapshot_text": "{number} {number, plural,\n one{개의 스냅샷}\n other{개의 스냅샷}\n} 삭제하시겠습니까?",
"delete_snapshot_text": "{number} {number, plural,\n one{개의 스냅샷}\n other{개의 스냅샷}\n} 삭제하시겠습니까?",
"delete_snapshot_title": "스냅샷 삭제",
"description": "스냅숏을 사용하면 Home Assistant 인스턴스의 모든 데이터를 쉽게 백업하고 복원할 수 있습니다.",
"enter_password": "비밀번호를 입력해주세요.",
@@ -2078,8 +2076,7 @@
"scripts": "스크립트",
"unknown_error": "알 수 없는 오류",
"unnamed_device": "이름이 없는 기기",
"update": "업데이트",
"update_device_error": "장치 업데이트 실패"
"update": "업데이트"
},
"entities": {
"caption": "구성요소",
@@ -2212,7 +2209,6 @@
"depends_on_cloud": "클라우드 서비스",
"device_unavailable": "기기 사용불가",
"devices": "{count} {count, plural,\none{개의 기기}\nother{개의 기기}\n}",
"disable_error": "통합구성요소 활성화 혹은 비활성화 실패",
"disable_restart_confirm": "이 통합 구성요소를 비활성화하려면 Home Assistant를 다시 시작해주세요",
"disable": {
"disable_confirm": "이 구성 항목을 비활성화하시겠습니까? 해당 기기 및 구성요소가 비활성화됩니다.",

View File

@@ -368,8 +368,6 @@
"error": "En ukjent feil har oppstått",
"error_addon_no_ingress": "Det etterspurte tillegget støtter ikke inngang",
"error_addon_not_found": "Tillegget ble ikke funnet",
"error_addon_not_installed": "Det forespurte tillegget er ikke installert. Vennligst installer den først",
"error_addon_not_started": "Det valgte tillegget kjører ikke. Vennligst start den først",
"faq_link": "Vanlige spørsmål om Min Home Assistant",
"not_supported": "Denne viderekoblingen støttes ikke av Home Assistant-forekomsten. Se på {link} for viderekoblinger som støttes, og hvilken versjon de ble introdusert."
},
@@ -931,11 +929,8 @@
},
"dialogs": {
"config_entry_system_options": {
"enable_new_entities_description": "Hvis nylig oppdagede enheter for {integration} skal legges til automatisk.",
"enable_new_entities_description": "Hvis den er deaktivert, blir ikke nyoppdagede entiteter for {integration} automatisk lagt til i Home Assistant.",
"enable_new_entities_label": "Aktiver entiteter som nylig er lagt til.",
"enable_polling_description": "Hvis Home Assistant automatisk skal avstemme {integration} enheter for oppdateringer.",
"enable_polling_label": "Aktiver avstemning for oppdateringer.",
"restart_home_assistant": "Du må starte Home Assistant på nytt for at endringene skal tre i kraft.",
"title": "Systemalternativer for {integration}",
"update": "Oppdater"
},
@@ -2078,8 +2073,7 @@
"scripts": "Skript",
"unknown_error": "Ukjent feil",
"unnamed_device": "Enhet uten navn",
"update": "Oppdater",
"update_device_error": "Oppdatering av enheten mislyktes"
"update": "Oppdater"
},
"entities": {
"caption": "Entiteter",
@@ -2212,7 +2206,6 @@
"depends_on_cloud": "Avhenger av skyen",
"device_unavailable": "Enheten er utilgjengelig",
"devices": "{count} {count, plural,\n one {enhet}\n other {enheter}\n}",
"disable_error": "Aktivering eller deaktivering av integrasjonen mislyktes",
"disable_restart_confirm": "Start Home Assistant på nytt for å fullføre deaktiveringen av denne integreringen",
"disable": {
"disable_confirm": "Er du sikker på at du vil deaktivere denne config-oppføringen? Enhetene og enhetene deaktiveres.",
@@ -2224,7 +2217,6 @@
},
"disabled_cause": "Deaktivert av {cause}"
},
"disabled_polling": "Automatisk avstemning for oppdaterte data deaktivert",
"documentation": "Dokumentasjon",
"enable_restart_confirm": "Start Home Assistant på nytt for å fullføre aktiveringen av denne integreringen",
"entities": "{count} {count, plural,\n one {entitet}\n other {entiteter}\n}",
@@ -2721,7 +2713,7 @@
"validation": {
"check_config": "Sjekk konfigurasjonen",
"heading": "Validering av konfigurasjon",
"introduction": "Bekreft konfigurasjonen hvis du nylig har gjort noen endringer i konfigurasjonen og vil være sikker på at den er gyldig.",
"introduction": "Valider konfigurasjonen hvis du nylig har gjort endringer i konfigurasjonen og vil forsikre deg om at den er gyldig",
"invalid": "Ugyldig konfigurasjon",
"valid": "Gyldig konfigurasjon"
}

View File

@@ -368,8 +368,6 @@
"error": "Er is een onbekende fout opgetreden",
"error_addon_no_ingress": "De gevraagde add-on ondersteunt geen ingress",
"error_addon_not_found": "Invoegtoepassing niet gevonden",
"error_addon_not_installed": "De gevraagde add-on is niet geïnstalleerd. Gelieve deze eerst te installeren",
"error_addon_not_started": "De gevraagde add-on is niet actief. Start deze a.u.b. eerst",
"faq_link": "My Home Assistant FAQ",
"not_supported": "Deze redirect wordt niet ondersteund door uw Home Assistant instantie. Controleer de {link} voor de ondersteunde redirects en de versie waarin ze zijn geïntroduceerd."
},
@@ -2078,8 +2076,7 @@
"scripts": "Scripts",
"unknown_error": "Onbekende fout",
"unnamed_device": "Naamloos apparaat",
"update": "Bijwerken",
"update_device_error": "Updaten van het apparaat mislukt"
"update": "Bijwerken"
},
"entities": {
"caption": "Entiteiten",

View File

@@ -368,8 +368,6 @@
"error": "Wystąpił nieznany błąd",
"error_addon_no_ingress": "Żądany dodatek nie obsługuje osadzania",
"error_addon_not_found": "Nie znaleziono dodatku",
"error_addon_not_installed": "Żądany dodatek nie jest zainstalowany. Najpierw go zainstaluj.",
"error_addon_not_started": "Żądany dodatek nie jest uruchomiony. Proszę najpierw go uruchomić.",
"faq_link": "Mój Home Assistant - często zadawane pytania",
"not_supported": "To przekierowanie nie jest obsługiwane przez Twoją instancję Home Assistanta. Sprawdź {link} aby znaleźć obsługiwane przekierowania i wersję, w której zostały wprowadzone."
},
@@ -931,11 +929,8 @@
},
"dialogs": {
"config_entry_system_options": {
"enable_new_entities_description": "Jeśli nowo odkryte urządzenia dla integracji {integration} powinny zostać dodane automatycznie.",
"enable_new_entities_description": "Jeśli wyłączone, nowo wykryte encje integracji {integration} nie będą automatycznie dodawane do Home Assistanta.",
"enable_new_entities_label": "Włącz dodawanie nowych encji.",
"enable_polling_description": "Czy Home Assistant powinien automatycznie odpytywać encje {integration} w poszukiwaniu aktualizacji.",
"enable_polling_label": "Włącz odpytywanie o aktualizacje.",
"restart_home_assistant": "Aby zmiany zostały wprowadzone, musisz ponownie uruchomić Home Assistanta.",
"title": "Opcje systemowe dla {integration}",
"update": "Aktualizuj"
},
@@ -2078,8 +2073,7 @@
"scripts": "Skrypty",
"unknown_error": "Nieznany błąd",
"unnamed_device": "Nienazwane urządzenie",
"update": "Aktualizuj",
"update_device_error": "Aktualizacja urządzenia nie powiodła się"
"update": "Aktualizuj"
},
"entities": {
"caption": "Rejestr encji",
@@ -2212,7 +2206,6 @@
"depends_on_cloud": "Zależny od chmury",
"device_unavailable": "Urządzenie niedostępne",
"devices": "{count} {count, plural,\n one {urządzenie}\n few {urządzenia}\n many {urządzeń}\n other {urządzeń}\n}",
"disable_error": "Nie udało się włączyć lub wyłączyć integracji",
"disable_restart_confirm": "Zrestartuj Home Assistanta, aby zakończyć wyłączanie tej integracji",
"disable": {
"disable_confirm": "Czy na pewno chcesz wyłączyć ten wpis w konfiguracji? Jego urządzenia i instancje zostaną wyłączone.",
@@ -2224,7 +2217,6 @@
},
"disabled_cause": "Wyłączone przez {cause}."
},
"disabled_polling": "Automatyczne odpytywanie o zaktualizowane dane jest wyłączone",
"documentation": "Dokumentacja",
"enable_restart_confirm": "Uruchom ponownie Home Assistanta, aby dokończyć uruchamianie tej integracji",
"entities": "{count} {count, plural,\n one {encja}\n few {encje}\n many {encji}\n other {encji}\n}",

View File

@@ -368,8 +368,6 @@
"error": "Произошла неизвестная ошибка",
"error_addon_no_ingress": "Дополнение не поддерживает ingress.",
"error_addon_not_found": "Дополнение не найдено.",
"error_addon_not_installed": "Запрошенное дополнение не установлено. Сначала нужно установить его.",
"error_addon_not_started": "Запрашиваемое дополнение не запущено. Сначала нужно запустить его.",
"faq_link": "часто задаваемыми вопросами по My Home Assistant",
"not_supported": "Это перенаправление не поддерживается Вашим Home Assistant. Ознакомьтесь с {link}, чтобы узнать поддерживаемые перенаправления и версии, в которых они были добавлены."
},
@@ -396,24 +394,24 @@
"failed_to_delete": "Не удалось удалить",
"folder": {
"addons/local": "Локальные дополнения",
"homeassistant": "Home Assistant configuration",
"homeassistant": "Home Assistant",
"media": "Media",
"share": "Share",
"ssl": "SSL"
},
"folders": "Папки",
"full_snapshot": "Все файлы",
"full_snapshot": "Полный",
"name": "Название",
"no_snapshots": "Не найдено ни одного снимка",
"partial_snapshot": "Выбрать из списка",
"partial_snapshot": "Выборочный",
"password": "Пароль",
"password_protected": "защищено паролем",
"password_protection": "Защита паролем",
"security": "Безопасность",
"select_type": "Выберите что нужно восстановить из этого снимка файловой системы",
"select_type": "Выберите что нужно восстановить",
"selected": "Выбрано: {number}",
"type": "Выберите что должен включать в себя снимок файловой системы",
"upload_snapshot": "Загрузить снимок на сервер"
"type": "Тип снимка",
"upload_snapshot": "Загрузить снимок"
},
"store": {
"missing_addons": "Пропали дополнения? Активируйте расширенный режим на странице Вашего профиля пользователя",
@@ -2078,8 +2076,7 @@
"scripts": "Скрипты",
"unknown_error": "Неизвестная ошибка.",
"unnamed_device": "Устройство без названия",
"update": "Обновить",
"update_device_error": "Не удалось обновить устройство"
"update": "Обновить"
},
"entities": {
"caption": "Объекты",
@@ -2212,7 +2209,6 @@
"depends_on_cloud": "Зависит от облачных сервисов",
"device_unavailable": "Устройство недоступно",
"devices": "{count} {count, plural,\n one {устройство}\n few {устройства}\n many {устройств}\n other {устройств}\n}",
"disable_error": "Не удалось активировать или деактивировать интеграцию",
"disable_restart_confirm": "Перезапустите Home Assistant, чтобы завершить деактивацию этой интеграции.",
"disable": {
"disable_confirm": "Вы уверены, что хотите деактивировать эту запись конфигурации? Её дочерние устройства и объекты будут также деактивированы.",
@@ -2721,7 +2717,7 @@
"validation": {
"check_config": "Начать проверку",
"heading": "Проверка конфигурации",
"introduction": "Выполните проверку конфигурации, если в неё были внесены изменения и Вы хотите убедиться в её работоспособности.",
"introduction": "Проверьте файлы конфигурации, если Вы внесли в них изменения.",
"invalid": "Ошибка в конфигурации",
"valid": "Конфигурация выполнена верно"
}

View File

@@ -368,8 +368,6 @@
"error": "发生未知错误",
"error_addon_no_ingress": "请求的加载项不支持 ingress",
"error_addon_not_found": "未找到加载项",
"error_addon_not_installed": "请求的加载项尚未安装,请先安装",
"error_addon_not_started": "请求的加载项未运行,请先运行",
"faq_link": "我的 Home Assistant 常见问题",
"not_supported": "您的 Home Assistant 不支持此重定向。请查阅{link}以获取受支持的重定向及其引入的版本。"
},
@@ -1808,7 +1806,7 @@
}
},
"alexa": {
"banner": "无法通过此 UI 修改要开放的实体,因为您在 configuration.yaml 中配置了实体过滤器。",
"banner": "由于您在 configuration.yaml 中配置了实体过滤器,无法通过此 UI 修改要开放的实体。",
"dont_expose_entity": "使实体不可发现",
"expose": "向Alexa发送你的位置",
"expose_entity": "使实体可发现",
@@ -2078,8 +2076,7 @@
"scripts": "脚本",
"unknown_error": "未知错误",
"unnamed_device": "未命名设备",
"update": "更新",
"update_device_error": "更新设备失败"
"update": "更新"
},
"entities": {
"caption": "实体注册表",
@@ -2212,7 +2209,6 @@
"depends_on_cloud": "依赖云端服务",
"device_unavailable": "设备不可用",
"devices": "{count} {count, plural,\n one {个设备}\n other {个设备}\n}",
"disable_error": "启用/禁用集成失败",
"disable_restart_confirm": "重启 Home Assistant 以完成此集成的禁用",
"disable": {
"disable_confirm": "您确定要禁用此配置条目吗?其设备和实体也将被禁用。",
@@ -2721,7 +2717,7 @@
"validation": {
"check_config": "检查配置",
"heading": "配置检查",
"introduction": "此处可以帮助您检验最新修改的配置文件有效性",
"introduction": "此处可以帮助您检验最新修改的配置文件有效性",
"invalid": "配置无效",
"valid": "配置有效!"
}

View File

@@ -368,8 +368,6 @@
"error": "發生未知錯誤",
"error_addon_no_ingress": "所要求的附加元件不支援 ingress",
"error_addon_not_found": "找不到附加元件",
"error_addon_not_installed": "所要求的附加元件未安裝,請先進行安裝。",
"error_addon_not_started": "所要求的附加元件未執行,請先進行啟動。",
"faq_link": "Home Assistant 常見問答集",
"not_supported": "Home Assistant 不支援此重新導向。點選 {link} 獲取支援之重新導向與版本。"
},
@@ -2078,8 +2076,7 @@
"scripts": "腳本",
"unknown_error": "未知錯誤",
"unnamed_device": "未命名的裝置",
"update": "更新",
"update_device_error": "更新裝置失敗"
"update": "更新"
},
"entities": {
"caption": "實體",
@@ -2212,7 +2209,6 @@
"depends_on_cloud": "跟隨雲服務",
"device_unavailable": "裝置不可用",
"devices": "{count} {count, plural,\n one {個裝置}\n other {個裝置}\n}",
"disable_error": "開啟或關閉整合失敗",
"disable_restart_confirm": "重啟 Home Assistant 以完成整合關閉",
"disable": {
"disable_confirm": "確定要關閉此設定實體?其裝置與實體將會關閉。",
@@ -2721,7 +2717,7 @@
"validation": {
"check_config": "檢查設定內容",
"heading": "設定驗證",
"introduction": "如果您對設定進行了部分更改、並且想確保設定有無錯誤,可以選擇驗證設定內容。",
"introduction": "如果您對設定進行了一些更改、並且想確保設定有無錯誤,可以選擇驗證設定內容。",
"invalid": "設定無效",
"valid": "設定檔內容檢查正確"
}

View File

@@ -4041,9 +4041,9 @@ async-each@^1.0.0, async-each@^1.0.1:
integrity sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==
async-limiter@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
async-settle@^1.0.0:
version "1.0.0"
@@ -7462,10 +7462,10 @@ he@1.2.0, he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
hls.js@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.0.5.tgz#3879bcf5ebcd6cdc188279cf9c15a74ac773630c"
integrity sha512-G7euEVuzM2AMZ69OzpQikO0HDJTMReX8OMUJmGhgwcjyh2OSsL2mGiqbL+6aK6wmUJelUfIh+FLyH73udZVYKQ==
hls.js@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.0.4.tgz#1b191f0f49c992e5c22d4a648ac73630d13d3c2e"
integrity sha512-sTea9L0ORE9u5dThUjEhDP4t9YzakEYRyMHEYQctaLZf2X9ihjmUbqKneExQWHXZz2cYQs5ihaKUe8QnrQDp7Q==
hmac-drbg@^1.0.1:
version "1.0.1"
@@ -13503,9 +13503,9 @@ write@1.0.3:
mkdirp "^0.5.1"
ws@^6.2.1:
version "6.2.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e"
integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
dependencies:
async-limiter "~1.0.0"