mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-13 11:19:25 +00:00
Compare commits
8 Commits
restore-ad
...
dash
Author | SHA1 | Date | |
---|---|---|---|
![]() |
50047e2f10 | ||
![]() |
2811541fba | ||
![]() |
57788cec44 | ||
![]() |
0aa314d9ae | ||
![]() |
f8d97735b8 | ||
![]() |
830136b874 | ||
![]() |
dd01710784 | ||
![]() |
f7d0736731 |
@@ -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");
|
||||
|
||||
|
@@ -57,6 +57,7 @@ const createRollupConfig = ({
|
||||
babel({
|
||||
...bundle.babelOptions({ latestBuild }),
|
||||
extensions,
|
||||
exclude: bundle.babelExclude(),
|
||||
babelHelpers: isWDS ? "inline" : "bundled",
|
||||
}),
|
||||
string({
|
||||
|
@@ -47,6 +47,7 @@ const createWebpackConfig = ({
|
||||
rules: [
|
||||
{
|
||||
test: /\.m?js$|\.ts$/,
|
||||
exclude: bundle.babelExclude(),
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: bundle.babelOptions({ latestBuild }),
|
||||
|
@@ -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;
|
||||
|
@@ -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 });
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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,
|
||||
});
|
||||
};
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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,
|
||||
});
|
||||
};
|
@@ -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() {
|
||||
|
@@ -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 });
|
||||
}
|
||||
|
@@ -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> {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
module.exports = {
|
||||
"*.ts": () => "tsc -p tsconfig.json",
|
||||
"*.{js,ts}": "eslint --fix",
|
||||
"!(/translations)*.{js,ts,json,css,md,html}": "prettier --write",
|
||||
};
|
||||
|
@@ -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",
|
||||
|
2
setup.py
2
setup.py
@@ -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",
|
||||
|
@@ -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) });
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
@@ -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 (
|
||||
|
@@ -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
|
||||
);
|
||||
};
|
||||
|
@@ -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>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -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>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -48,9 +48,6 @@
|
||||
window.providersPromise = fetch("/auth/providers", {
|
||||
credentials: "same-origin",
|
||||
});
|
||||
if (!window.globalThis) {
|
||||
window.globalThis = window;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
@@ -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 -%}
|
||||
|
@@ -80,9 +80,6 @@
|
||||
window.stepsPromise = fetch("/api/onboarding", {
|
||||
credentials: "same-origin",
|
||||
});
|
||||
if (!window.globalThis) {
|
||||
window.globalThis = window;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
@@ -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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
};
|
@@ -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": "Спрете да игнорирате"
|
||||
|
@@ -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"
|
||||
},
|
||||
|
@@ -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",
|
||||
|
@@ -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"
|
||||
},
|
||||
|
@@ -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!"
|
||||
}
|
||||
|
@@ -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.",
|
||||
|
@@ -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!"
|
||||
}
|
||||
|
@@ -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
@@ -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.",
|
||||
|
@@ -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": "이 구성 항목을 비활성화하시겠습니까? 해당 기기 및 구성요소가 비활성화됩니다.",
|
||||
|
@@ -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"
|
||||
}
|
||||
|
@@ -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",
|
||||
|
@@ -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}",
|
||||
|
@@ -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": "Конфигурация выполнена верно"
|
||||
}
|
||||
|
@@ -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": "配置有效!"
|
||||
}
|
||||
|
@@ -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": "設定檔內容檢查正確"
|
||||
}
|
||||
|
20
yarn.lock
20
yarn.lock
@@ -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"
|
||||
|
||||
|
Reference in New Issue
Block a user