From 959134df02da754b43fa895f9e94f613b3d3db2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Fri, 28 May 2021 14:37:16 +0200 Subject: [PATCH 01/13] Better secrets support in add-on configuration (#9275) --- .../addon-view/config/hassio-addon-config.ts | 20 ++++++++++++++++++- src/components/ha-yaml-editor.ts | 11 +++++++--- src/data/hassio/addon.ts | 4 +++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/hassio/src/addon-view/config/hassio-addon-config.ts b/hassio/src/addon-view/config/hassio-addon-config.ts index 52c3d73930..273bca178b 100644 --- a/hassio/src/addon-view/config/hassio-addon-config.ts +++ b/hassio/src/addon-view/config/hassio-addon-config.ts @@ -3,6 +3,7 @@ import { ActionDetail } from "@material/mwc-list"; import "@material/mwc-list/mwc-list-item"; import { mdiDotsVertical } from "@mdi/js"; import "@polymer/iron-autogrow-textarea/iron-autogrow-textarea"; +import { DEFAULT_SCHEMA, Type } from "js-yaml"; import { css, CSSResultGroup, @@ -11,7 +12,7 @@ import { PropertyValues, TemplateResult, } from "lit"; -import { customElement, property, state, query } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../src/common/dom/fire_event"; import "../../../../src/components/buttons/ha-progress-button"; @@ -27,6 +28,7 @@ import { HassioAddonDetails, HassioAddonSetOptionParams, setHassioAddonOption, + validateHassioAddonOption, } from "../../../../src/data/hassio/addon"; import { extractApiErrorMessage } from "../../../../src/data/hassio/common"; import { Supervisor } from "../../../../src/data/supervisor/supervisor"; @@ -38,6 +40,13 @@ import { hassioStyle } from "../../resources/hassio-style"; const SUPPORTED_UI_TYPES = ["string", "select", "boolean", "integer", "float"]; +const ADDON_YAML_SCHEMA = DEFAULT_SCHEMA.extend([ + new Type("!secret", { + kind: "scalar", + construct: (data) => `!secret ${data}`, + }), +]); + @customElement("hassio-addon-config") class HassioAddonConfig extends LitElement { @property({ attribute: false }) public addon!: HassioAddonDetails; @@ -125,6 +134,7 @@ class HassioAddonConfig extends LitElement { >` : html` `} ${this._error ? html`
${this._error}
` : ""} ${!this._yamlMode || @@ -269,6 +279,14 @@ class HassioAddonConfig extends LitElement { this._error = undefined; try { + const validation = await validateHassioAddonOption( + this.hass, + this.addon.slug, + this._editor?.value + ); + if (!validation.valid) { + throw Error(validation.message); + } await setHassioAddonOption(this.hass, this.addon.slug, { options: this._yamlMode ? this._editor?.value : this._options, }); diff --git a/src/components/ha-yaml-editor.ts b/src/components/ha-yaml-editor.ts index 8d79034c3e..8ff961aa10 100644 --- a/src/components/ha-yaml-editor.ts +++ b/src/components/ha-yaml-editor.ts @@ -1,4 +1,4 @@ -import { dump, load } from "js-yaml"; +import { DEFAULT_SCHEMA, dump, load, Schema } from "js-yaml"; import { html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; @@ -20,6 +20,8 @@ const isEmpty = (obj: Record): boolean => { export class HaYamlEditor extends LitElement { @property() public value?: any; + @property({ attribute: false }) public yamlSchema: Schema = DEFAULT_SCHEMA; + @property() public defaultValue?: any; @property() public isValid = true; @@ -30,7 +32,10 @@ export class HaYamlEditor extends LitElement { public setValue(value): void { try { - this._yaml = value && !isEmpty(value) ? dump(value) : ""; + this._yaml = + value && !isEmpty(value) + ? dump(value, { schema: this.yamlSchema }) + : ""; } catch (err) { // eslint-disable-next-line no-console console.error(err, value); @@ -67,7 +72,7 @@ export class HaYamlEditor extends LitElement { if (this._yaml) { try { - parsed = load(this._yaml); + parsed = load(this._yaml, { schema: this.yamlSchema }); } catch (err) { // Invalid YAML isValid = false; diff --git a/src/data/hassio/addon.ts b/src/data/hassio/addon.ts index 902bd88816..c2e43ac046 100644 --- a/src/data/hassio/addon.ts +++ b/src/data/hassio/addon.ts @@ -212,13 +212,15 @@ export const setHassioAddonOption = async ( export const validateHassioAddonOption = async ( hass: HomeAssistant, - slug: string + slug: string, + data?: any ): Promise<{ message: string; valid: boolean }> => { if (atLeastVersion(hass.config.version, 2021, 2, 4)) { return hass.callWS({ type: "supervisor/api", endpoint: `/addons/${slug}/options/validate`, method: "post", + data, }); } From 2d5ae78521c4e3f8a8af410aef347b2eebe4d032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Fri, 28 May 2021 15:49:40 +0200 Subject: [PATCH 02/13] Add selection to snapshot table for mass deletion (#9284) Co-authored-by: Bram Kragten --- hassio/src/snapshots/hassio-snapshots.ts | 138 ++++++++++++++++++++++- src/data/hassio/snapshot.ts | 15 +++ src/translations/en.json | 6 + 3 files changed, 154 insertions(+), 5 deletions(-) diff --git a/hassio/src/snapshots/hassio-snapshots.ts b/hassio/src/snapshots/hassio-snapshots.ts index a13f37c9d2..56c527b667 100644 --- a/hassio/src/snapshots/hassio-snapshots.ts +++ b/hassio/src/snapshots/hassio-snapshots.ts @@ -1,15 +1,17 @@ import "@material/mwc-button"; import { ActionDetail } from "@material/mwc-list"; import "@material/mwc-list/mwc-list-item"; -import { mdiDotsVertical, mdiPlus } from "@mdi/js"; +import { mdiDelete, mdiDotsVertical, mdiPlus } from "@mdi/js"; import { + css, CSSResultGroup, html, LitElement, PropertyValues, TemplateResult, } from "lit"; -import { customElement, property, state } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; +import { classMap } from "lit/directives/class-map"; import memoizeOne from "memoize-one"; import { atLeastVersion } from "../../../src/common/config/version"; import relativeTime from "../../../src/common/datetime/relative_time"; @@ -17,18 +19,25 @@ import { HASSDomEvent } from "../../../src/common/dom/fire_event"; import { DataTableColumnContainer, RowClickedEvent, + SelectionChangedEvent, } from "../../../src/components/data-table/ha-data-table"; import "../../../src/components/ha-button-menu"; import "../../../src/components/ha-fab"; +import { extractApiErrorMessage } from "../../../src/data/hassio/common"; import { fetchHassioSnapshots, friendlyFolderName, HassioSnapshot, reloadHassioSnapshots, + removeSnapshot, } from "../../../src/data/hassio/snapshot"; import { Supervisor } from "../../../src/data/supervisor/supervisor"; -import { showAlertDialog } from "../../../src/dialogs/generic/show-dialog-box"; +import { + showAlertDialog, + showConfirmationDialog, +} from "../../../src/dialogs/generic/show-dialog-box"; import "../../../src/layouts/hass-tabs-subpage-data-table"; +import type { HaTabsSubpageDataTable } from "../../../src/layouts/hass-tabs-subpage-data-table"; import { haStyle } from "../../../src/resources/styles"; import { HomeAssistant, Route } from "../../../src/types"; import { showHassioCreateSnapshotDialog } from "../dialogs/snapshot/show-dialog-hassio-create-snapshot"; @@ -49,10 +58,15 @@ export class HassioSnapshots extends LitElement { @property({ type: Boolean }) public isWide!: boolean; - private _firstUpdatedCalled = false; + @state() private _selectedSnapshots: string[] = []; @state() private _snapshots?: HassioSnapshot[] = []; + @query("hass-tabs-subpage-data-table", true) + private _dataTable!: HaTabsSubpageDataTable; + + private _firstUpdatedCalled = false; + public connectedCallback(): void { super.connectedCallback(); if (this.hass && this._firstUpdatedCalled) { @@ -153,7 +167,9 @@ export class HassioSnapshots extends LitElement { .data=${this._snapshotData(this._snapshots || [])} id="slug" @row-click=${this._handleRowClicked} + @selection-changed=${this._handleSelectionChanged} clickable + selectable hasFab main-page supervisor @@ -176,6 +192,45 @@ export class HassioSnapshots extends LitElement { : ""} + ${this._selectedSnapshots.length + ? html`
+

+ ${this.supervisor.localize("snapshot.selected", { + number: this._selectedSnapshots.length, + })} +

+
+ ${!this.narrow + ? html` + + ${this.supervisor.localize("snapshot.delete_selected")} + + ` + : html` + + + + + ${this.supervisor.localize("snapshot.delete_selected")} + + `} +
+
` + : ""} + + ): void { + this._selectedSnapshots = ev.detail.value; + } + private _showUploadSnapshotDialog() { showSnapshotUploadDialog(this, { showSnapshot: (slug: string) => @@ -216,6 +277,35 @@ export class HassioSnapshots extends LitElement { this._snapshots = await fetchHassioSnapshots(this.hass); } + private async _deleteSelected() { + const confirm = await showConfirmationDialog(this, { + title: this.supervisor.localize("snapshot.delete_snapshot_title"), + text: this.supervisor.localize("snapshot.delete_snapshot_text", { + number: this._selectedSnapshots.length, + }), + confirmText: this.supervisor.localize("snapshot.delete_snapshot_confirm"), + }); + + if (!confirm) { + return; + } + + try { + await Promise.all( + this._selectedSnapshots.map((slug) => removeSnapshot(this.hass, slug)) + ); + } catch (err) { + showAlertDialog(this, { + title: this.supervisor.localize("snapshot.failed_to_delete"), + text: extractApiErrorMessage(err), + }); + return; + } + await reloadHassioSnapshots(this.hass); + this._snapshots = await fetchHassioSnapshots(this.hass); + this._dataTable.clearSelection(); + } + private _handleRowClicked(ev: HASSDomEvent) { const slug = ev.detail.id; showHassioSnapshotDialog(this, { @@ -244,7 +334,45 @@ export class HassioSnapshots extends LitElement { } static get styles(): CSSResultGroup { - return [haStyle, hassioStyle]; + return [ + haStyle, + hassioStyle, + css` + .table-header { + display: flex; + justify-content: space-between; + align-items: center; + height: 58px; + border-bottom: 1px solid rgba(var(--rgb-primary-text-color), 0.12); + } + .header-toolbar { + display: flex; + justify-content: space-between; + align-items: center; + color: var(--secondary-text-color); + position: relative; + top: -4px; + } + .selected-txt { + font-weight: bold; + padding-left: 16px; + color: var(--primary-text-color); + } + .table-header .selected-txt { + margin-top: 20px; + } + .header-toolbar .selected-txt { + font-size: 16px; + } + .header-toolbar .header-btns { + margin-right: -12px; + } + .header-btns > mwc-button, + .header-btns > mwc-icon-button { + margin: 8px; + } + `, + ]; } } diff --git a/src/data/hassio/snapshot.ts b/src/data/hassio/snapshot.ts index ba34776228..b2f1c36c25 100644 --- a/src/data/hassio/snapshot.ts +++ b/src/data/hassio/snapshot.ts @@ -130,6 +130,21 @@ export const createHassioFullSnapshot = async ( ); }; +export const removeSnapshot = async (hass: HomeAssistant, slug: string) => { + if (atLeastVersion(hass.config.version, 2021, 2, 4)) { + await hass.callWS({ + type: "supervisor/api", + endpoint: `/snapshots/${slug}/remove`, + method: "post", + }); + return; + } + await hass.callApi>( + "POST", + `hassio/snapshots/${slug}/remove` + ); +}; + export const createHassioPartialSnapshot = async ( hass: HomeAssistant, data: HassioPartialSnapshotCreateParams diff --git a/src/translations/en.json b/src/translations/en.json index 6a700c664a..584e25f33e 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3896,6 +3896,12 @@ "available_snapshots": "Available Snapshots", "no_snapshots": "You don't have any snapshots yet.", "create_blocked_not_running": "Creating a snapshot is not possible right now because the system is in {state} state.", + "delete_selected": "Delete selected snapshots", + "delete_snapshot_title": "Delete snapshot", + "delete_snapshot_text": "Do you want to delete {number} {number, plural,\n one {snapshot}\n other {snapshots}\n}?", + "delete_snapshot_confirm": "delete", + "selected": "{number} selected", + "failed_to_delete": "Failed to delete", "could_not_create": "Could not create snapshot", "upload_snapshot": "Upload snapshot", "create_snapshot": "Create snapshot", From 0419c1a41f37ad7a0e28c62d56a0546768a58d33 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 29 May 2021 04:54:28 +0200 Subject: [PATCH 03/13] Fix icon loading (#9289) --- src/data/iconsets.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/data/iconsets.ts b/src/data/iconsets.ts index debfcea7e2..5675184a3d 100644 --- a/src/data/iconsets.ts +++ b/src/data/iconsets.ts @@ -36,18 +36,16 @@ export const getIcon = (iconName: string) => .then((icon) => resolve_(icon)) .catch((e) => reject_(e)); } - }) - ) - .catch((e) => { - // Firefox in private mode doesn't support IDB - // Safari sometime doesn't open the DB so we time out - for (const [, , reject_] of toRead) { - reject_(e); - } - }) - .finally(() => { toRead = []; - }); + }) + ).catch((e) => { + // Firefox in private mode doesn't support IDB + // Safari sometime doesn't open the DB so we time out + for (const [, , reject_] of toRead) { + reject_(e); + } + toRead = []; + }); }); export const findIconChunk = (icon: string): string => { From 4f60a92b9259a29e864c1c51a51465b10450ecca Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sat, 29 May 2021 05:02:28 +0200 Subject: [PATCH 04/13] Fix default themes (#9290) * Fix default themes * Simplify pick theme row --- .../registries/dialog-hassio-registries.ts | 3 -- .../dialog-hassio-repositories.ts | 3 -- .../device/ha-device-action-picker.ts | 1 - .../device/ha-device-condition-picker.ts | 1 - .../device/ha-device-trigger-picker.ts | 1 - .../media-player/ha-media-player-browse.ts | 1 - .../types/ha-automation-trigger-tag.ts | 2 +- .../helpers/forms/ha-input_number-form.ts | 3 -- .../helpers/forms/ha-input_select-form.ts | 3 -- .../helpers/forms/ha-input_text-form.ts | 3 -- .../hui-header-footer-editor.ts | 1 - src/panels/profile/ha-pick-theme-row.ts | 36 ++++--------------- src/state/themes-mixin.ts | 9 +++-- 13 files changed, 11 insertions(+), 56 deletions(-) diff --git a/hassio/src/dialogs/registries/dialog-hassio-registries.ts b/hassio/src/dialogs/registries/dialog-hassio-registries.ts index 6cd738119a..043ca71de5 100644 --- a/hassio/src/dialogs/registries/dialog-hassio-registries.ts +++ b/hassio/src/dialogs/registries/dialog-hassio-registries.ts @@ -244,9 +244,6 @@ class HassioRegistriesDialog extends LitElement { mwc-list-item span[slot="secondary"] { color: var(--secondary-text-color); } - ha-paper-dropdown-menu { - display: block; - } `, ]; } diff --git a/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts b/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts index cbc1e6e40d..8130e0d781 100644 --- a/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts +++ b/hassio/src/dialogs/repositories/dialog-hassio-repositories.ts @@ -150,9 +150,6 @@ class HassioRepositoriesDialog extends LitElement { mwc-button { margin-left: 8px; } - ha-paper-dropdown-menu { - display: block; - } ha-circular-progress { display: block; margin: 32px; diff --git a/src/components/device/ha-device-action-picker.ts b/src/components/device/ha-device-action-picker.ts index ce053d45cf..3dbeae27a6 100644 --- a/src/components/device/ha-device-action-picker.ts +++ b/src/components/device/ha-device-action-picker.ts @@ -4,7 +4,6 @@ import { fetchDeviceActions, localizeDeviceAutomationAction, } from "../../data/device_automation"; -import "../ha-paper-dropdown-menu"; import { HaDeviceAutomationPicker } from "./ha-device-automation-picker"; @customElement("ha-device-action-picker") diff --git a/src/components/device/ha-device-condition-picker.ts b/src/components/device/ha-device-condition-picker.ts index 977a4ee05f..f6ca89d012 100644 --- a/src/components/device/ha-device-condition-picker.ts +++ b/src/components/device/ha-device-condition-picker.ts @@ -4,7 +4,6 @@ import { fetchDeviceConditions, localizeDeviceAutomationCondition, } from "../../data/device_automation"; -import "../ha-paper-dropdown-menu"; import { HaDeviceAutomationPicker } from "./ha-device-automation-picker"; @customElement("ha-device-condition-picker") diff --git a/src/components/device/ha-device-trigger-picker.ts b/src/components/device/ha-device-trigger-picker.ts index 142955b24a..c5755f9ecd 100644 --- a/src/components/device/ha-device-trigger-picker.ts +++ b/src/components/device/ha-device-trigger-picker.ts @@ -4,7 +4,6 @@ import { fetchDeviceTriggers, localizeDeviceAutomationTrigger, } from "../../data/device_automation"; -import "../ha-paper-dropdown-menu"; import { HaDeviceAutomationPicker } from "./ha-device-automation-picker"; @customElement("ha-device-trigger-picker") diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts index db5b8af6b3..481b0a5d2a 100644 --- a/src/components/media-player/ha-media-player-browse.ts +++ b/src/components/media-player/ha-media-player-browse.ts @@ -45,7 +45,6 @@ import "../ha-button-menu"; import "../ha-card"; import "../ha-circular-progress"; import "../ha-fab"; -import "../ha-paper-dropdown-menu"; import "../ha-svg-icon"; declare global { diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts index 5accba1a25..454b3bdb80 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-tag.ts @@ -6,7 +6,7 @@ import { TagTrigger } from "../../../../../data/automation"; import { fetchTags, Tag } from "../../../../../data/tag"; import { HomeAssistant } from "../../../../../types"; import { TriggerElement } from "../ha-automation-trigger-row"; - +import "../../../../../components/ha-paper-dropdown-menu"; @customElement("ha-automation-trigger-tag") export class HaTagTrigger extends LitElement implements TriggerElement { @property({ attribute: false }) public hass!: HomeAssistant; diff --git a/src/panels/config/helpers/forms/ha-input_number-form.ts b/src/panels/config/helpers/forms/ha-input_number-form.ts index ec3288ebab..4f3a32bbd8 100644 --- a/src/panels/config/helpers/forms/ha-input_number-form.ts +++ b/src/panels/config/helpers/forms/ha-input_number-form.ts @@ -193,9 +193,6 @@ class HaInputNumberForm extends LitElement { .form { color: var(--primary-text-color); } - ha-paper-dropdown-menu { - display: block; - } `, ]; } diff --git a/src/panels/config/helpers/forms/ha-input_select-form.ts b/src/panels/config/helpers/forms/ha-input_select-form.ts index fbb15f7f6e..0267c9e6d2 100644 --- a/src/panels/config/helpers/forms/ha-input_select-form.ts +++ b/src/panels/config/helpers/forms/ha-input_select-form.ts @@ -196,9 +196,6 @@ class HaInputSelectForm extends LitElement { mwc-button { margin-left: 8px; } - ha-paper-dropdown-menu { - display: block; - } `, ]; } diff --git a/src/panels/config/helpers/forms/ha-input_text-form.ts b/src/panels/config/helpers/forms/ha-input_text-form.ts index 4de30e62d2..f48c562791 100644 --- a/src/panels/config/helpers/forms/ha-input_text-form.ts +++ b/src/panels/config/helpers/forms/ha-input_text-form.ts @@ -179,9 +179,6 @@ class HaInputTextForm extends LitElement { .row { padding: 16px 0; } - ha-paper-dropdown-menu { - display: block; - } `, ]; } diff --git a/src/panels/lovelace/editor/header-footer-editor/hui-header-footer-editor.ts b/src/panels/lovelace/editor/header-footer-editor/hui-header-footer-editor.ts index 044f7502ae..5ee72ba281 100644 --- a/src/panels/lovelace/editor/header-footer-editor/hui-header-footer-editor.ts +++ b/src/panels/lovelace/editor/header-footer-editor/hui-header-footer-editor.ts @@ -5,7 +5,6 @@ import "@polymer/paper-listbox/paper-listbox"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; import { fireEvent } from "../../../../common/dom/fire_event"; -import "../../../../components/ha-paper-dropdown-menu"; import "../../../../components/ha-svg-icon"; import type { LovelaceConfig } from "../../../../data/lovelace"; import type { HomeAssistant } from "../../../../types"; diff --git a/src/panels/profile/ha-pick-theme-row.ts b/src/panels/profile/ha-pick-theme-row.ts index 7043281d87..bb2ac4a86d 100644 --- a/src/panels/profile/ha-pick-theme-row.ts +++ b/src/panels/profile/ha-pick-theme-row.ts @@ -17,7 +17,6 @@ import "../../components/ha-paper-dropdown-menu"; import "../../components/ha-radio"; import type { HaRadio } from "../../components/ha-radio"; import "../../components/ha-settings-row"; -import { Theme } from "../../data/ws-themes"; import { DEFAULT_PRIMARY_COLOR, DEFAULT_ACCENT_COLOR, @@ -33,10 +32,6 @@ export class HaPickThemeRow extends LitElement { @state() _themeNames: string[] = []; - @state() _selectedThemeIndex = 0; - - @state() _selectedTheme?: Theme; - protected render(): TemplateResult { const hasThemes = this.hass.themes.themes && Object.keys(this.hass.themes.themes).length; @@ -72,7 +67,8 @@ export class HaPickThemeRow extends LitElement { > ${this._themeNames.map( @@ -81,8 +77,7 @@ export class HaPickThemeRow extends LitElement { - ${curTheme === "default" || - (this._selectedTheme && this._supportsModeSelection(this._selectedTheme)) + ${curTheme === "default" || this._supportsModeSelection(curTheme) ? html`
0 - ) { - this._selectedThemeIndex = this._themeNames.indexOf( - this.hass.selectedTheme.theme - ); - this._selectedTheme = this.hass.themes.themes[ - this.hass.selectedTheme.theme - ]; - } else if (!this.hass.selectedTheme) { - this._selectedThemeIndex = 0; - } - } } private _handleColorChange(ev: CustomEvent) { @@ -199,8 +175,8 @@ export class HaPickThemeRow extends LitElement { }); } - private _supportsModeSelection(theme: Theme): boolean { - return theme.modes?.light !== undefined && theme.modes?.dark !== undefined; + private _supportsModeSelection(themeName: string): boolean { + return "modes" in this.hass.themes.themes[themeName]; } private _handleDarkMode(ev: CustomEvent) { diff --git a/src/state/themes-mixin.ts b/src/state/themes-mixin.ts index efce598882..2fc88a831a 100644 --- a/src/state/themes-mixin.ts +++ b/src/state/themes-mixin.ts @@ -74,16 +74,15 @@ export default >(superClass: T) => const themeName = themeSettings?.theme || (darkPreferred && this.hass.themes.default_dark_theme - ? this.hass.themes.default_dark_theme! + ? this.hass.themes.default_dark_theme : this.hass.themes.default_theme); let darkMode = themeSettings?.dark === undefined ? darkPreferred : themeSettings?.dark; - const selectedTheme = - themeSettings?.theme !== undefined - ? this.hass.themes.themes[themeSettings.theme] - : undefined; + const selectedTheme = themeName + ? this.hass.themes.themes[themeName] + : undefined; if (selectedTheme && darkMode && !selectedTheme.modes) { darkMode = false; From 63fcb649d202476a8253b3c3b67240387df6437d Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 29 May 2021 03:21:09 +0000 Subject: [PATCH 05/13] Translation update --- translations/frontend/bg.json | 15 ++++++++++++++- translations/frontend/ca.json | 6 ++++++ translations/frontend/da.json | 2 +- translations/frontend/en.json | 6 ++++++ translations/frontend/es.json | 6 ++++++ translations/frontend/nl.json | 8 +++++++- translations/frontend/ru.json | 8 +++++++- translations/frontend/zh-Hant.json | 6 ++++++ 8 files changed, 53 insertions(+), 4 deletions(-) diff --git a/translations/frontend/bg.json b/translations/frontend/bg.json index dbc8595145..203efdef19 100644 --- a/translations/frontend/bg.json +++ b/translations/frontend/bg.json @@ -530,8 +530,11 @@ }, "light": { "brightness": "Яркост", + "cold_white_value": "Студено бяла яркост", + "color_brightness": "Яркост на цвета", "color_temperature": "Цветова температура", "effect": "Ефект", + "warm_white_value": "Топло бяла яркост", "white_value": "Стойност на бялото" }, "lock": { @@ -679,6 +682,9 @@ "no_match": "Не са намерени съответстващи области", "show_areas": "Показване на области" }, + "attributes": { + "expansion_header": "Атрибути" + }, "blueprint-picker": { "add_user": "Добавяне на потребител", "remove_user": "Премахване на потребител", @@ -1052,6 +1058,7 @@ "person": "Презареждане на хората", "reload": "Презареждане на {domain}", "rest": "Презареждане на REST обекти и услуги за нотификация", + "rpi_gpio": "Raspberry Pi GPIO обекти", "scene": "Презареждане на сцените", "script": "Презареждане на скриптовете", "telegram": "Презареждане на Telegram услугите за нотификация", @@ -2215,6 +2222,8 @@ }, "network_status": { "details": { + "driverfailed": "Неуспешно свързване с Z-Wave контролера", + "driverready": "Инициализиране на Z-Wave контролера", "ready": "Готов за свързване", "started": "Свързан към MQTT", "starting": "Свързване към MQTT" @@ -2613,6 +2622,7 @@ "header": "Z-Wave конфигурация на устройството", "introduction": "Управление и настройване на специфични конфигурационни параметри на подбраното устройството (възел, node)", "parameter_is_read_only": "Този параметър е само за четене.", + "set_param_error": "Възникна грешка.", "zwave_js_device_database": "Z-Wave JS база данни с устройства" }, "node_status": { @@ -3483,12 +3493,15 @@ "reset": "Нулиране" }, "time_format": { + "description": "Изберете как да се форматира времето.", + "dropdown_label": "Формат на времето", "formats": { "12": "12 часа (AM/PM)", "24": "24 часа", "language": "Авто (езикова настройка)", "system": "Системна настройка" - } + }, + "header": "Формат на времето" }, "vibrate": { "description": "Разрешаване или забраняване на вибрациите на това устройство при управление на устройства.", diff --git a/translations/frontend/ca.json b/translations/frontend/ca.json index 9ca6e802d6..afe04d60bc 100644 --- a/translations/frontend/ca.json +++ b/translations/frontend/ca.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "Ara mateix no és possible crear una instantània perquè el sistema es troba en estat {state}.", "create_snapshot": "Crea instantània", "created": "Creada", + "delete_selected": "Suprimeix les instantànies seleccionades", + "delete_snapshot_confirm": "suprimeix", + "delete_snapshot_text": "Vols suprimir {number} {number, plural,\n one {instantània}\n other {instantànies}\n}?", + "delete_snapshot_title": "Suprimeix instantània", "description": "Les instantànies et permeten fer una còpia de seguretat i recuperar les dades de la teva instància de Home Assistant.", "enter_password": "Introdueix una contrasenya.", + "failed_to_delete": "No s'ha pogut suprimir", "folder": { "addons/local": "Complements locals", "homeassistant": "Configuració de Home Assistant", @@ -404,6 +409,7 @@ "password_protection": "Protecció amb contrasenya", "security": "Seguretat", "select_type": "Selecciona què vols restaurar", + "selected": "{number} seleccionada/es", "type": "Tipus d'instantània", "upload_snapshot": "Puja instantània" }, diff --git a/translations/frontend/da.json b/translations/frontend/da.json index 768c77d9ff..2498e9f36e 100644 --- a/translations/frontend/da.json +++ b/translations/frontend/da.json @@ -3786,7 +3786,7 @@ "working": "Vent venligst" }, "initializing": "Initialiserer", - "logging_in_to_with": "Logger ind på ** {locationName} ** med ** {authProviderName} **.", + "logging_in_to_with": "Logger ind på **{locationName}** med **{authProviderName}**.", "logging_in_with": "Log ind med **{authProviderName}**.", "pick_auth_provider": "Eller log ind med" }, diff --git a/translations/frontend/en.json b/translations/frontend/en.json index 7f87c48dce..a2cade9a79 100644 --- a/translations/frontend/en.json +++ b/translations/frontend/en.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "Creating a snapshot is not possible right now because the system is in {state} state.", "create_snapshot": "Create snapshot", "created": "Created", + "delete_selected": "Delete selected snapshots", + "delete_snapshot_confirm": "delete", + "delete_snapshot_text": "Do you want to delete {number} {number, plural,\n one {snapshot}\n other {snapshots}\n}?", + "delete_snapshot_title": "Delete snapshot", "description": "Snapshots allow you to easily backup and restore all data of your Home Assistant instance.", "enter_password": "Please enter a password.", + "failed_to_delete": "Failed to delete", "folder": { "addons/local": "Local add-ons", "homeassistant": "Home Assistant configuration", @@ -404,6 +409,7 @@ "password_protection": "Password protection", "security": "Security", "select_type": "Select what to restore", + "selected": "{number} selected", "type": "Snapshot type", "upload_snapshot": "Upload snapshot" }, diff --git a/translations/frontend/es.json b/translations/frontend/es.json index fd19086d4f..a42530ef1f 100644 --- a/translations/frontend/es.json +++ b/translations/frontend/es.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "No es posible crear una instantánea en este momento porque el sistema está en el estado {state}.", "create_snapshot": "Crear instantánea", "created": "Creada", + "delete_selected": "Eliminar instantáneas seleccionadas", + "delete_snapshot_confirm": "Eliminar", + "delete_snapshot_text": "¿Deseas eliminar {number} {number, plural,\n one {instantánea}\n other {instantáneas}\n}?", + "delete_snapshot_title": "Eliminar instantánea", "description": "Las instantáneas te permiten realizar copias de seguridad y restaurar fácilmente todos los datos de tu instancia de Home Assistant.", "enter_password": "Por favor, introduce una contraseña.", + "failed_to_delete": "No se pudo eliminar", "folder": { "addons/local": "Complementos locales", "homeassistant": "Configuración de Home Assistant", @@ -404,6 +409,7 @@ "password_protection": "Protección con contraseña", "security": "Seguridad", "select_type": "Selecciona qué restaurar", + "selected": "{number} {number, plural,\n one {seleccionada}\n other {seleccionadas}\n}", "type": "Tipo de instantánea", "upload_snapshot": "Subir instantánea" }, diff --git a/translations/frontend/nl.json b/translations/frontend/nl.json index ef4ac76756..3721aa6c18 100644 --- a/translations/frontend/nl.json +++ b/translations/frontend/nl.json @@ -292,7 +292,7 @@ "save": "Opslaan", "show_more": "Toon meer informatie hierover", "update": "Update", - "update_available": "Er {count, plural, one {staat een update} other {{count} staan updates}} klaar", + "update_available": "{count, plural, one {Een update staat} other {{count} updates staan}} klaar", "version": "Versie", "yes": "Ja" }, @@ -385,8 +385,13 @@ "create_blocked_not_running": "Het maken van een snapshot is nu niet mogelijk omdat het systeem in {state} staat.", "create_snapshot": "Maak snapshot", "created": "Gemaakt", + "delete_selected": "Verwijder geselecteerde snapshots", + "delete_snapshot_confirm": "verwijder", + "delete_snapshot_text": "Wilt je {number} {number, plural,\n one {snapshot}\n other {snapshots}\n} verwijderen?", + "delete_snapshot_title": "Verwijder snapshot", "description": "Met snapshots kunt u gemakkelijk een back-up maken van alle gegevens van uw Home Assistant en ze herstellen.", "enter_password": "Voer een wachtwoord in.", + "failed_to_delete": "Verwijderen mislukt", "folder": { "addons/local": "Lokale invoegtoepassingen", "homeassistant": "Home Assistant configuratie", @@ -404,6 +409,7 @@ "password_protection": "Wachtwoord bescherming", "security": "Beveiliging", "select_type": "Selecteer wat u wilt herstellen", + "selected": "{number} geselecteerd", "type": "Snapshot type", "upload_snapshot": "Upload snapshot" }, diff --git a/translations/frontend/ru.json b/translations/frontend/ru.json index c657d7b224..fd7dcbf674 100644 --- a/translations/frontend/ru.json +++ b/translations/frontend/ru.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "Создание снимка сейчас невозможно, потому что система находится в состоянии {state}.", "create_snapshot": "Создать снимок", "created": "Создан", + "delete_selected": "Удалить выбранные снимки", + "delete_snapshot_confirm": "удалить", + "delete_snapshot_text": "Вы уверены, что хотите удалить {number} {number, plural,\n one {снимок}\n few {снимка}\n many {снимков}\n other {снимков}\n}?", + "delete_snapshot_title": "Удалить снимок", "description": "Снимок файловой системы (snapshot) позволяет легко создавать и восстанавливать резервную копию всех данных Вашего Home Assistant.", "enter_password": "Пожалуйста, введите пароль.", + "failed_to_delete": "Не удалось удалить", "folder": { "addons/local": "Локальные дополнения", "homeassistant": "Home Assistant", @@ -403,7 +408,8 @@ "password_protected": "защищено паролем", "password_protection": "Защита паролем", "security": "Безопасность", - "select_type": "Выберите, что нужно восстановить", + "select_type": "Выберите что нужно восстановить", + "selected": "Выбрано: {number}", "type": "Тип снимка", "upload_snapshot": "Загрузить снимок" }, diff --git a/translations/frontend/zh-Hant.json b/translations/frontend/zh-Hant.json index b5e293dac7..d6f2f605db 100644 --- a/translations/frontend/zh-Hant.json +++ b/translations/frontend/zh-Hant.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "由於系統為 {state} 狀態,無法製作系統備份。", "create_snapshot": "製作系統備份", "created": "建立", + "delete_selected": "刪除已選擇系統備份", + "delete_snapshot_confirm": "刪除", + "delete_snapshot_text": "是否要刪除 {number} {number, plural,\n one {個系統備份}\n other {個系統備份}\n}?", + "delete_snapshot_title": "刪除系統備份", "description": "系統備份可供您快速的備份與還原 Home Assistant 所有資料。", "enter_password": "請輸入密碼。", + "failed_to_delete": "刪除失敗", "folder": { "addons/local": "本地附加元件", "homeassistant": "Home Assistant 設定", @@ -404,6 +409,7 @@ "password_protection": "密碼保護", "security": "加密", "select_type": "選擇所要回復內容", + "selected": "已選擇 {number} 個", "type": "系統備份類型", "upload_snapshot": "上傳系統備份" }, From 03bbf6a5820a9f50c9a2aa24605007b0211c0f9c Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sun, 30 May 2021 03:38:49 +0000 Subject: [PATCH 06/13] Translation update --- translations/frontend/et.json | 6 +++ translations/frontend/fy.json | 60 ++++++++++++++++++++++++++++++ translations/frontend/it.json | 20 ++++++++-- translations/frontend/nl.json | 2 +- translations/frontend/pl.json | 6 +++ translations/frontend/zh-Hans.json | 30 ++++++++++----- 6 files changed, 110 insertions(+), 14 deletions(-) diff --git a/translations/frontend/et.json b/translations/frontend/et.json index 878a37dc10..29c4b37799 100644 --- a/translations/frontend/et.json +++ b/translations/frontend/et.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "Hetktõmmise loomine pole praegu võimalik kuna süsteem on olekus {state}.", "create_snapshot": "Loo hetktõmmis", "created": "Loodud", + "delete_selected": "Kustuta valitud hetktõmmised", + "delete_snapshot_confirm": "kustuta", + "delete_snapshot_text": "Kas kustutada {number} {number, plural,\n one {hetktõmmis}\n other {hetktõmmist}\n}?", + "delete_snapshot_title": "Kustuta hetktõmmis", "description": "Hetktõmmised võimaldavad hõlpsalt varundada ja taastada kõik Home Assistanti andmed.", "enter_password": "Sisesta salasõna.", + "failed_to_delete": "Kustutamine nurjus", "folder": { "addons/local": "Kohalikud lisandmoodulid", "homeassistant": "Home Assistanti sätted", @@ -404,6 +409,7 @@ "password_protection": "Salasõnaga kaitstud", "security": "Turvalisus", "select_type": "Vali mida taastada", + "selected": "{number} valitud", "type": "Hetktõmmise tüüp", "upload_snapshot": "Hetktõmmise üleslaadimine" }, diff --git a/translations/frontend/fy.json b/translations/frontend/fy.json index cbc2b50536..f179ab6ac8 100644 --- a/translations/frontend/fy.json +++ b/translations/frontend/fy.json @@ -58,6 +58,17 @@ }, "my": { "error_addon_not_found": "Add-on net fûn" + }, + "snapshot": { + "created": "Makke", + "delete_snapshot_confirm": "ferwiderje", + "failed_to_delete": "Ferwiderje is mislearre", + "selected": "{number} selekteare" + }, + "system": { + "supervisor": { + "search": "Sykje" + } } }, "ui": { @@ -110,6 +121,9 @@ "name": "Namme" } }, + "data-table": { + "clear": "Opklearje" + }, "device-picker": { "device": "Apparaat", "toggle": "Skeakelje" @@ -119,6 +133,14 @@ "generic": { "cancel": "Annulearje" }, + "quick-bar": { + "commands": { + "types": { + "navigation": "Navigearje", + "server_control": "Server" + } + } + }, "zha_device_info": { "zha_device_card": { "device_name_placeholder": "Feroarje apparaatnamme" @@ -142,6 +164,12 @@ "type": { "choose": { "add_option": "Opsje tafoegje" + }, + "device_id": { + "extra_fields": { + "mode": "Wize", + "value": "Wearde" + } } } }, @@ -199,6 +227,9 @@ } }, "cloud": { + "account": { + "connecting": "Ferbine ..." + }, "alexa": { "title": "Alexa" }, @@ -221,6 +252,21 @@ "info": { "description": "Ynformaasje oer dyn Home Assistant ynstallaasje" }, + "integrations": { + "config_entry": { + "configure": "Ynstelle" + }, + "disable": { + "show": "Toan" + } + }, + "logs": { + "level": { + "critical": "KRITYSK", + "info": "YNFO", + "warning": "WARSKÔGING" + } + }, "lovelace": { "description": "Konfigurearje dyn Lovelace-dashboards", "resources": { @@ -241,6 +287,8 @@ "name": "Namme" }, "picker": { + "duplicate": "Duplisearje", + "duplicate_scene": "Duplisearje sêne", "headers": { "name": "Namme" } @@ -338,6 +386,13 @@ } } }, + "page-onboarding": { + "analytics": { + "finish": "Folgjende" + }, + "finish": "Ein", + "next": "Folgjende" + }, "profile": { "advanced_mode": { "link_promo": "Lear mear" @@ -349,6 +404,11 @@ "mfa_setup": { "close": "Slute" }, + "number_format": { + "formats": { + "none": "Gjin" + } + }, "themes": { "dark_mode": { "dark": "Tsjuster", diff --git a/translations/frontend/it.json b/translations/frontend/it.json index d0fcb13914..e72b301dd8 100644 --- a/translations/frontend/it.json +++ b/translations/frontend/it.json @@ -314,7 +314,7 @@ "addon_new_version": "Nuova versione disponibile", "addon_running": "Il componente aggiuntivo è in esecuzione", "addon_stopped": "Il componente aggiuntivo viene arrestato", - "addons": "Componenti aggiuntivi", + "addons": "Componenti aggiuntivi installati", "no_addons": "Non hai ancora installato alcun componente aggiuntivo. Vai al negozio di componenti aggiuntivi per iniziare!" }, "dialog": { @@ -385,8 +385,13 @@ "create_blocked_not_running": "La creazione di un'istantanea non è al momento possibile perché il sistema è nello stato {state}.", "create_snapshot": "Crea istantanea", "created": "Creato", + "delete_selected": "Elimina le istantanee selezionate", + "delete_snapshot_confirm": "Elimina", + "delete_snapshot_text": "Vuoi eliminare {number} {number, plural,\n one {istantanea}\n other {istantanee}\n}?", + "delete_snapshot_title": "Elimina istantanea", "description": "Le istantanee ti consentono di eseguire facilmente il backup e il ripristino di tutti i dati dell'istanza di Home Assistant.", "enter_password": "Immettere una password.", + "failed_to_delete": "Impossibile eliminare", "folder": { "addons/local": "Componenti aggiuntivi locali", "homeassistant": "Configurazione di Home Assistant", @@ -396,14 +401,16 @@ }, "folders": "Cartelle", "full_snapshot": "Istantanea completa", - "name": "Nome", + "name": "Nome dell'istantanea", "no_snapshots": "Non hai ancora nessuna istantanea.", "partial_snapshot": "Istantanea parziale", - "password": "Password", + "password": "Password dell'istantanea", "password_protected": "protetto da password", "password_protection": "Protezione con password", "security": "Sicurezza", - "type": "Tipo", + "select_type": "Seleziona cosa ripristinare", + "selected": "{number} selezionato/i", + "type": "Tipo di istantanea", "upload_snapshot": "Invia istantanea" }, "store": { @@ -720,6 +727,9 @@ "no_match": "Non sono state trovate aree corrispondenti", "show_areas": "Mostra le aree" }, + "attributes": { + "expansion_header": "Attributi" + }, "blueprint-picker": { "add_user": "Aggiungi utente", "remove_user": "Rimuovi utente", @@ -1719,6 +1729,7 @@ "title": "Alexa" }, "connected": "Connesso", + "connecting": "In collegamento...", "connection_status": "Stato della connessione cloud", "fetching_subscription": "Recupero iscrizione in corso...", "google": { @@ -2959,6 +2970,7 @@ }, "logs": { "log_level": "Livello di registro", + "log_level_changed": "Livello di registro modificato in: {level}", "subscribed_to_logs": "Sottoscrizione al registro dei messaggi di Z-Wave JS ...", "title": "Registri Z-Wave JS" }, diff --git a/translations/frontend/nl.json b/translations/frontend/nl.json index 3721aa6c18..c44e937cba 100644 --- a/translations/frontend/nl.json +++ b/translations/frontend/nl.json @@ -387,7 +387,7 @@ "created": "Gemaakt", "delete_selected": "Verwijder geselecteerde snapshots", "delete_snapshot_confirm": "verwijder", - "delete_snapshot_text": "Wilt je {number} {number, plural,\n one {snapshot}\n other {snapshots}\n} verwijderen?", + "delete_snapshot_text": "Wilt u {number} {number, plural,\n one {snapshot}\n other {snapshots}\n} verwijderen?", "delete_snapshot_title": "Verwijder snapshot", "description": "Met snapshots kunt u gemakkelijk een back-up maken van alle gegevens van uw Home Assistant en ze herstellen.", "enter_password": "Voer een wachtwoord in.", diff --git a/translations/frontend/pl.json b/translations/frontend/pl.json index 9a208016a5..c2c22c3b6e 100644 --- a/translations/frontend/pl.json +++ b/translations/frontend/pl.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "Tworzenie snapshota nie jest teraz możliwe, ponieważ system jest w {state}.", "create_snapshot": "Utwórz snapshot", "created": "Utworzony", + "delete_selected": "Usuń wybrane snapshoty", + "delete_snapshot_confirm": "usuń", + "delete_snapshot_text": "Czy chcesz usunąć {number} {number, plural,\n one {snapshota}\n few {snapshoty}\n many {snapshotów}\n other {snapshoty}\n}?", + "delete_snapshot_title": "Usuń snapshota", "description": "Snapshoty umożliwiają łatwe tworzenie kopii zapasowych i przywracanie wszystkich danych instancji Home Assistant.", "enter_password": "Proszę wprowadzić hasło", + "failed_to_delete": "Nie udało się usunąć", "folder": { "addons/local": "Folder Local add-ons", "homeassistant": "Folder konfiguracji Home Assistant", @@ -404,6 +409,7 @@ "password_protection": "Ochrona hasłem", "security": "Bezpieczeństwo", "select_type": "Wybierz, co przywrócić", + "selected": "wybrano {number}", "type": "Typ snapshota", "upload_snapshot": "Prześlij snapshota" }, diff --git a/translations/frontend/zh-Hans.json b/translations/frontend/zh-Hans.json index 204b0f2bdf..eac6f6b64e 100644 --- a/translations/frontend/zh-Hans.json +++ b/translations/frontend/zh-Hans.json @@ -385,8 +385,13 @@ "create_blocked_not_running": "现在无法创建快照,因为系统处于{state}状态。", "create_snapshot": "创建快照", "created": "创建于", + "delete_selected": "删除选定的快照", + "delete_snapshot_confirm": "删除", + "delete_snapshot_text": "您是否要删除{number}个快照?", + "delete_snapshot_title": "删除快照", "description": "“快照”使您可以轻松地备份和还原 Home Assistant 实例的所有数据。", "enter_password": "请输入密码。", + "failed_to_delete": "删除失败", "folder": { "addons/local": "本地加载项", "homeassistant": "Home Assistant 配置", @@ -403,6 +408,8 @@ "password_protected": "密码保护", "password_protection": "密码保护", "security": "安全性", + "select_type": "选择要还原的内容", + "selected": "选择了 {number} 项", "type": "类型", "upload_snapshot": "上传快照" }, @@ -573,8 +580,8 @@ }, "lock": { "code": "密码", - "lock": "锁定", - "unlock": "解锁" + "lock": "上锁", + "unlock": "开锁" }, "media_player": { "browse_media": "浏览媒体", @@ -720,6 +727,9 @@ "no_match": "未找到相关区域", "show_areas": "显示区域" }, + "attributes": { + "expansion_header": "属性" + }, "blueprint-picker": { "add_user": "添加用户", "remove_user": "删除用户", @@ -788,13 +798,13 @@ "was_closed": "已关闭", "was_connected": "已连接", "was_disconnected": "已断开", - "was_locked": "已锁定", + "was_locked": "已上锁", "was_low": "较低", "was_normal": "正常", "was_opened": "已打开", "was_plugged_in": "已插入", "was_safe": "[%key_id:6884522%]", - "was_unlocked": "已解锁", + "was_unlocked": "已打开", "was_unplugged": "已拔出", "was_unsafe": "[%key_id:6884523%]" }, @@ -1119,7 +1129,7 @@ "command_line": "命令行实体", "core": "位置和自定义", "filesize": "文件大小实体", - "filter": "filter 实体", + "filter": "筛选实体", "generic": "通用 IP 摄像机实体", "generic_thermostat": "通用恒温器实体", "group": "分组、分组实体及其通知服务", @@ -1719,6 +1729,7 @@ "title": "Alexa" }, "connected": "已连接", + "connecting": "正在连接...", "connection_status": "云连接状态", "fetching_subscription": "正在获取订阅...", "google": { @@ -1792,7 +1803,7 @@ } }, "alexa": { - "banner": "由于已在configuration.yaml中配置了实体过滤器,因此无法编辑通过此UI公开哪些实体。", + "banner": "您在configuration.yaml中配置了实体过滤器,因此无法用此UI修改被公开的实体名单。", "dont_expose_entity": "使实体不可发现", "expose": "向Alexa发送你的位置", "expose_entity": "使实体可发现", @@ -2041,7 +2052,7 @@ "filter": { "filter": "筛选", "hidden_devices": "{number} 个隐藏设备", - "show_all": "显示全部", + "show_all": "全部显示", "show_disabled": "显示已禁用的设备" }, "search": "搜索设备" @@ -2081,7 +2092,7 @@ "filter": { "filter": "筛选", "hidden_entities": "{number} 个隐藏{number, plural,\n one {实体}\n other {实体}\n}", - "show_all": "显示全部", + "show_all": "全部显示", "show_disabled": "显示已禁用的实体", "show_readonly": "显示只读实体", "show_unavailable": "显示不可用的实体" @@ -2661,7 +2672,7 @@ "command_line": "命令行实体", "core": "位置和自定义", "filesize": "文件大小实体", - "filter": "filter 实体", + "filter": "筛选实体", "generic": "通用 IP 摄像机实体", "generic_thermostat": "通用恒温器实体", "group": "分组、分组实体及其通知服务", @@ -2959,6 +2970,7 @@ }, "logs": { "log_level": "日志级别", + "log_level_changed": "日志级别更改为: {level}", "subscribed_to_logs": "已订阅 Z-Wave JS 日志消息...", "title": "Z-Wave JS 日志" }, From 10a77b627808c1b5bfa9e5bbac76309a35c537da Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sun, 30 May 2021 16:02:03 +0200 Subject: [PATCH 07/13] Update translations --- translations/frontend/nl.json | 2 +- translations/frontend/pt-BR.json | 30 ++++++++++++++++++++++-------- translations/frontend/sl.json | 4 ++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/translations/frontend/nl.json b/translations/frontend/nl.json index c44e937cba..7a6c1683d5 100644 --- a/translations/frontend/nl.json +++ b/translations/frontend/nl.json @@ -4027,7 +4027,7 @@ "12": "12 uur (AM/PM)", "24": "24 uur", "language": "Automatisch (taalinstelling gebruiken)", - "system": "Systeemlokalen gebruiken" + "system": "Gebruik systeemlandinstelling" }, "header": "Tijdformaat" }, diff --git a/translations/frontend/pt-BR.json b/translations/frontend/pt-BR.json index 87168ecd09..90742292f6 100644 --- a/translations/frontend/pt-BR.json +++ b/translations/frontend/pt-BR.json @@ -121,9 +121,16 @@ }, "snapshot": { "created": "Criado", + "delete_selected": "Excluir snapshots selecionados", + "delete_snapshot_confirm": "Excluir", + "delete_snapshot_text": "Deseja excluir {number} {number, plural,\n one {snapshot}\n other {snapshots}\n}?", + "delete_snapshot_title": "Excluir snapshot", + "failed_to_delete": "Falha ao excluir", "folder": { "homeassistant": "Configuração do Home Assistant" - } + }, + "select_type": "Selecione o que restaurar", + "selected": "{number} selecionado" }, "system": { "supervisor": { @@ -338,6 +345,9 @@ "no_match": "Não foram encontradas áreas com esta configuração", "show_areas": "Mostrar áreas" }, + "attributes": { + "expansion_header": "Atributos" + }, "blueprint-picker": { "add_user": "Adicionar Usuário", "remove_user": "Remover usuário" @@ -1117,6 +1127,7 @@ "title": "Alexa" }, "connected": "Conectado", + "connecting": "Conectando ...", "connection_status": "Status de conexão com a Cloud", "fetching_subscription": "Buscando assinatura…", "google": { @@ -1152,7 +1163,8 @@ "link_learn_how_it_works": "Aprenda como funciona", "not_connected": "Não Conectado", "remote_enabled": { - "caption": "Conectar automaticamente" + "caption": "Conectar automaticamente", + "description": "Ative esta opção para garantir que a instância do Home Assistant esteja sempre acessível remotamente." }, "title": "Controle Remoto" }, @@ -1806,8 +1818,8 @@ "add_scene": "Adicionar cena", "delete_confirm": "Tem certeza de que deseja excluir esta cena?", "delete_scene": "Excluir cena", - "duplicate": "Duplicado", - "duplicate_scene": "Cena duplicada", + "duplicate": "Duplicar", + "duplicate_scene": "Duplicar cena", "edit_scene": "Editar cena", "header": "Editor de cena", "headers": { @@ -2107,7 +2119,9 @@ }, "zwave_js": { "logs": { - "log_level": "Nível de Log" + "log_level": "Nível de Log", + "subscribed_to_logs": "Inscrito em mensagens de log JS do Z-Wave ...", + "title": "Logs Z-Wave JS" }, "navigation": { "logs": "Logs" @@ -3006,9 +3020,9 @@ "description": "Escolha como os horários são formatados.", "dropdown_label": "Formato de hora", "formats": { - "12": "Horas", - "24": "Horas", - "language": "Auto (usar configuração de idioma)", + "12": "12 horas (AM/PM)", + "24": "24 horas", + "language": "Automático (usar configuração de idioma)", "system": "Use a localidade do sistema" }, "header": "Formato de hora" diff --git a/translations/frontend/sl.json b/translations/frontend/sl.json index d25cdd2eb0..ed306ac1d9 100644 --- a/translations/frontend/sl.json +++ b/translations/frontend/sl.json @@ -1490,7 +1490,7 @@ "picker": { "filter": { "filter": "Filter", - "hidden_devices": "{number} {number, plural,\n one {skrita naprava}\n two {skriti napravi}\n few {skrite naprave}\n many {skritih naprav}\n}", + "hidden_devices": "{number} {number, plural,\n one {skrita naprava}\n two {skriti napravi}\n few {skrite naprave}\n other {skritih naprav}\n}", "show_all": "Prikaži vse", "show_disabled": "Prikaži onemogočene naprave" }, @@ -1530,7 +1530,7 @@ }, "filter": { "filter": "Filter", - "hidden_entities": "{number} {number, plural,\n one {skrita entiteta}\n two {skriti entiteti}\n few {skrite entitete}\n many {skritih entitet}\n}", + "hidden_entities": "{number} {number, plural,\n one {skrita entiteta}\n two {skriti entiteti}\n few {skrite entitete}\n other {skritih entitet}\n}", "show_all": "Pokaži vse", "show_disabled": "Pokaži onemogočene entitete", "show_readonly": "Prikaži entitete \"samo za branje\"", From 528af0157dba0923a88eae7d06a4ab63c836edde Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Sun, 30 May 2021 16:06:22 +0200 Subject: [PATCH 08/13] Move entity attribution out of attribute expansion panel (#9296) --- src/components/ha-attributes.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/ha-attributes.ts b/src/components/ha-attributes.ts index 5c75269a0b..8168043eb8 100644 --- a/src/components/ha-attributes.ts +++ b/src/components/ha-attributes.ts @@ -54,17 +54,17 @@ class HaAttributes extends LitElement {
` )} - ${this.stateObj.attributes.attribution - ? html` -
- ${this.stateObj.attributes.attribution} -
- ` - : ""} ` : ""} + ${this.stateObj.attributes.attribution + ? html` +
+ ${this.stateObj.attributes.attribution} +
+ ` + : ""} `; } @@ -91,6 +91,7 @@ class HaAttributes extends LitElement { .attribution { color: var(--secondary-text-color); text-align: center; + margin-top: 16px; } pre { font-family: inherit; From 92c8bd80b5a5e44b857286a157f91791326d61a9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Sun, 30 May 2021 17:02:03 +0200 Subject: [PATCH 09/13] Catch translation errors (#9299) --- src/common/translations/localize.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/common/translations/localize.ts b/src/common/translations/localize.ts index ee9522e141..1c13650812 100644 --- a/src/common/translations/localize.ts +++ b/src/common/translations/localize.ts @@ -86,11 +86,15 @@ export const computeLocalize = async ( | undefined; if (!translatedMessage) { - translatedMessage = new IntlMessageFormat( - translatedValue, - language, - formats - ); + try { + translatedMessage = new IntlMessageFormat( + translatedValue, + language, + formats + ); + } catch (err) { + return "Translation error: " + err.message; + } cache._localizationCache[messageKey] = translatedMessage; } From 93b3b8f9850495d06927758503b2e943183915ac Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 31 May 2021 05:08:46 +0200 Subject: [PATCH 10/13] Fix editor structs (#9286) --- src/common/structs/is-custom-type.ts | 6 + src/common/structs/is-entity-id.ts | 7 +- src/common/structs/is-icon.ts | 7 +- .../config-elements/hui-button-card-editor.ts | 3 +- .../hui-entities-card-editor.ts | 118 ++++++++++- .../config-elements/hui-entity-card-editor.ts | 2 +- .../hui-generic-entity-row-editor.ts | 7 +- .../config-elements/hui-glance-card-editor.ts | 7 +- .../hui-graph-footer-editor.ts | 6 +- .../hui-history-graph-card-editor.ts | 20 +- .../config-elements/hui-light-card-editor.ts | 3 +- .../config-elements/hui-map-card-editor.ts | 7 +- .../hui-picture-card-editor.ts | 3 +- .../hui-picture-entity-card-editor.ts | 3 +- .../hui-picture-glance-card-editor.ts | 8 +- .../hui-weather-forecast-card-editor.ts | 7 +- .../lovelace/editor/structs/action-struct.ts | 67 +++++++ .../editor/structs/entities-struct.ts | 18 ++ src/panels/lovelace/editor/types.ts | 185 ------------------ src/panels/lovelace/header-footer/structs.ts | 29 +++ src/panels/lovelace/header-footer/types.ts | 28 --- 21 files changed, 261 insertions(+), 280 deletions(-) create mode 100644 src/common/structs/is-custom-type.ts create mode 100644 src/panels/lovelace/editor/structs/action-struct.ts create mode 100644 src/panels/lovelace/editor/structs/entities-struct.ts create mode 100644 src/panels/lovelace/header-footer/structs.ts diff --git a/src/common/structs/is-custom-type.ts b/src/common/structs/is-custom-type.ts new file mode 100644 index 0000000000..9b90eb517f --- /dev/null +++ b/src/common/structs/is-custom-type.ts @@ -0,0 +1,6 @@ +import { refine, string } from "superstruct"; + +const isCustomType = (value: string) => value.startsWith("custom:"); + +export const customType = () => + refine(string(), "custom element type", isCustomType); diff --git a/src/common/structs/is-entity-id.ts b/src/common/structs/is-entity-id.ts index 8d71f01694..05a7a8b439 100644 --- a/src/common/structs/is-entity-id.ts +++ b/src/common/structs/is-entity-id.ts @@ -1,11 +1,6 @@ import { refine, string } from "superstruct"; -const isEntityId = (value: string): boolean => { - if (!value.includes(".")) { - return false; - } - return true; -}; +const isEntityId = (value: string): boolean => value.includes("."); export const entityId = () => refine(string(), "entity ID (domain.entity)", isEntityId); diff --git a/src/common/structs/is-icon.ts b/src/common/structs/is-icon.ts index db97d69ec2..17ef291813 100644 --- a/src/common/structs/is-icon.ts +++ b/src/common/structs/is-icon.ts @@ -1,10 +1,5 @@ import { refine, string } from "superstruct"; -const isIcon = (value: string) => { - if (!value.includes(":")) { - return false; - } - return true; -}; +const isIcon = (value: string) => value.includes(":"); export const icon = () => refine(string(), "icon (mdi:icon-name)", isIcon); diff --git a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts index 9a38ec0820..d0bbbed691 100644 --- a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts @@ -15,7 +15,8 @@ import "../../components/hui-action-editor"; import "../../components/hui-entity-editor"; import "../../components/hui-theme-select-editor"; import { LovelaceCardEditor } from "../../types"; -import { actionConfigStruct, EditorTarget } from "../types"; +import { actionConfigStruct } from "../structs/action-struct"; +import { EditorTarget } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts index 5cac06cda6..8db7fa8840 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts @@ -5,15 +5,20 @@ import "@polymer/paper-listbox/paper-listbox"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { + any, array, assert, boolean, + literal, + number, object, optional, string, + type, union, } from "superstruct"; import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event"; +import { customType } from "../../../../common/structs/is-custom-type"; import { entityId } from "../../../../common/structs/is-entity-id"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import "../../../../components/entity/state-badge"; @@ -25,20 +30,127 @@ import type { HomeAssistant } from "../../../../types"; import type { EntitiesCardConfig } from "../../cards/types"; import "../../components/hui-theme-select-editor"; import type { LovelaceRowConfig } from "../../entity-rows/types"; -import { headerFooterConfigStructs } from "../../header-footer/types"; +import { headerFooterConfigStructs } from "../../header-footer/structs"; import type { LovelaceCardEditor } from "../../types"; import "../header-footer-editor/hui-header-footer-editor"; import "../hui-entities-card-row-editor"; import "../hui-sub-element-editor"; import { processEditorEntities } from "../process-editor-entities"; +import { actionConfigStruct } from "../structs/action-struct"; +import { entitiesConfigStruct } from "../structs/entities-struct"; import { EditorTarget, EditSubElementEvent, - entitiesConfigStruct, SubElementEditorConfig, } from "../types"; import { configElementStyle } from "./config-elements-style"; +const buttonEntitiesRowConfigStruct = object({ + type: literal("button"), + name: string(), + action_name: optional(string()), + tap_action: actionConfigStruct, + hold_action: optional(actionConfigStruct), + double_tap_action: optional(actionConfigStruct), +}); + +const castEntitiesRowConfigStruct = object({ + type: literal("cast"), + view: union([string(), number()]), + dashboard: optional(string()), + name: optional(string()), + icon: optional(string()), + hide_if_unavailable: optional(boolean()), +}); + +const callServiceEntitiesRowConfigStruct = object({ + type: literal("call-service"), + name: string(), + service: string(), + icon: optional(string()), + action_name: optional(string()), + service_data: optional(any()), +}); + +const conditionalEntitiesRowConfigStruct = object({ + type: literal("conditional"), + row: any(), + conditions: array( + object({ + entity: string(), + state: optional(string()), + state_not: optional(string()), + }) + ), +}); + +const dividerEntitiesRowConfigStruct = object({ + type: literal("divider"), + style: optional(any()), +}); + +const sectionEntitiesRowConfigStruct = object({ + type: literal("section"), + label: optional(string()), +}); + +const webLinkEntitiesRowConfigStruct = object({ + type: literal("weblink"), + url: string(), + name: optional(string()), + icon: optional(string()), +}); + +const buttonsEntitiesRowConfigStruct = object({ + type: literal("buttons"), + entities: array( + union([ + object({ + entity: string(), + icon: optional(string()), + image: optional(string()), + name: optional(string()), + }), + string(), + ]) + ), +}); + +const attributeEntitiesRowConfigStruct = object({ + type: literal("attribute"), + entity: string(), + attribute: string(), + prefix: optional(string()), + suffix: optional(string()), + name: optional(string()), +}); + +const textEntitiesRowConfigStruct = object({ + type: literal("text"), + name: string(), + text: string(), + icon: optional(string()), +}); + +const customRowConfigStruct = type({ + type: customType(), +}); + +const entitiesRowConfigStruct = union([ + entitiesConfigStruct, + buttonEntitiesRowConfigStruct, + castEntitiesRowConfigStruct, + conditionalEntitiesRowConfigStruct, + dividerEntitiesRowConfigStruct, + sectionEntitiesRowConfigStruct, + webLinkEntitiesRowConfigStruct, + buttonsEntitiesRowConfigStruct, + attributeEntitiesRowConfigStruct, + callServiceEntitiesRowConfigStruct, + textEntitiesRowConfigStruct, + customRowConfigStruct, +]); + const cardConfigStruct = object({ type: string(), title: optional(union([string(), boolean()])), @@ -47,7 +159,7 @@ const cardConfigStruct = object({ icon: optional(string()), show_header_toggle: optional(boolean()), state_color: optional(boolean()), - entities: array(entitiesConfigStruct), + entities: array(entitiesRowConfigStruct), header: optional(headerFooterConfigStructs), footer: optional(headerFooterConfigStructs), }); diff --git a/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts index 275f460f6b..34b0da3d0e 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entity-card-editor.ts @@ -11,7 +11,7 @@ import { EntityCardConfig } from "../../cards/types"; import "../../components/hui-action-editor"; import "../../components/hui-entity-editor"; import "../../components/hui-theme-select-editor"; -import { headerFooterConfigStructs } from "../../header-footer/types"; +import { headerFooterConfigStructs } from "../../header-footer/structs"; import { LovelaceCardEditor } from "../../types"; import { EditorTarget, EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; diff --git a/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts b/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts index 232112c6b4..203d6e9906 100644 --- a/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-generic-entity-row-editor.ts @@ -14,11 +14,8 @@ import "../../components/hui-action-editor"; import "../../components/hui-entity-editor"; import "../../components/hui-theme-select-editor"; import { LovelaceRowEditor } from "../../types"; -import { - EditorTarget, - entitiesConfigStruct, - EntitiesEditorEvent, -} from "../types"; +import { entitiesConfigStruct } from "../structs/entities-struct"; +import { EditorTarget, EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; const SecondaryInfoValues: { [key: string]: { domains?: string[] } } = { diff --git a/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts index 651a767c0a..7ea34e0445 100644 --- a/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-glance-card-editor.ts @@ -26,11 +26,8 @@ import "../../components/hui-entity-editor"; import "../../components/hui-theme-select-editor"; import { LovelaceCardEditor } from "../../types"; import { processEditorEntities } from "../process-editor-entities"; -import { - EditorTarget, - entitiesConfigStruct, - EntitiesEditorEvent, -} from "../types"; +import { entitiesConfigStruct } from "../structs/entities-struct"; +import { EditorTarget, EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/config-elements/hui-graph-footer-editor.ts b/src/panels/lovelace/editor/config-elements/hui-graph-footer-editor.ts index a63cac0d46..65b591c164 100644 --- a/src/panels/lovelace/editor/config-elements/hui-graph-footer-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-graph-footer-editor.ts @@ -8,10 +8,8 @@ import "../../../../components/entity/ha-entity-picker"; import "../../../../components/ha-formfield"; import "../../../../components/ha-switch"; import type { HomeAssistant } from "../../../../types"; -import { - GraphHeaderFooterConfig, - graphHeaderFooterConfigStruct, -} from "../../header-footer/types"; +import { graphHeaderFooterConfigStruct } from "../../header-footer/structs"; +import { GraphHeaderFooterConfig } from "../../header-footer/types"; import type { LovelaceCardEditor } from "../../types"; import type { EditorTarget, EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; diff --git a/src/panels/lovelace/editor/config-elements/hui-history-graph-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-history-graph-card-editor.ts index 407db8ca1a..6f07551a19 100644 --- a/src/panels/lovelace/editor/config-elements/hui-history-graph-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-history-graph-card-editor.ts @@ -1,34 +1,18 @@ import "@polymer/paper-input/paper-input"; import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; -import { - array, - assert, - number, - object, - optional, - string, - union, -} from "superstruct"; +import { array, assert, number, object, optional, string } from "superstruct"; import { fireEvent } from "../../../../common/dom/fire_event"; -import { entityId } from "../../../../common/structs/is-entity-id"; import { HomeAssistant } from "../../../../types"; import { HistoryGraphCardConfig } from "../../cards/types"; import "../../components/hui-entity-editor"; import { EntityConfig } from "../../entity-rows/types"; import { LovelaceCardEditor } from "../../types"; import { processEditorEntities } from "../process-editor-entities"; +import { entitiesConfigStruct } from "../structs/entities-struct"; import { EditorTarget, EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; -const entitiesConfigStruct = union([ - object({ - entity: entityId(), - name: optional(string()), - }), - entityId(), -]); - const cardConfigStruct = object({ type: string(), entities: array(entitiesConfigStruct), diff --git a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts index 867d939a1a..bb3d94a344 100644 --- a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts @@ -12,7 +12,8 @@ import "../../components/hui-action-editor"; import "../../components/hui-entity-editor"; import "../../components/hui-theme-select-editor"; import { LovelaceCardEditor } from "../../types"; -import { actionConfigStruct, EditorTarget } from "../types"; +import { actionConfigStruct } from "../structs/action-struct"; +import { EditorTarget } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts index f9484d1ed9..5a857ce8c3 100644 --- a/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-map-card-editor.ts @@ -22,11 +22,8 @@ import "../../components/hui-input-list-editor"; import { EntityConfig } from "../../entity-rows/types"; import { LovelaceCardEditor } from "../../types"; import { processEditorEntities } from "../process-editor-entities"; -import { - EditorTarget, - entitiesConfigStruct, - EntitiesEditorEvent, -} from "../types"; +import { entitiesConfigStruct } from "../structs/entities-struct"; +import { EditorTarget, EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts index 5ae59b0d26..b5df0f1802 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts @@ -9,7 +9,8 @@ import { PictureCardConfig } from "../../cards/types"; import "../../components/hui-action-editor"; import "../../components/hui-theme-select-editor"; import { LovelaceCardEditor } from "../../types"; -import { actionConfigStruct, EditorTarget } from "../types"; +import { actionConfigStruct } from "../structs/action-struct"; +import { EditorTarget } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts index a9a99edf4f..555eb35867 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-entity-card-editor.ts @@ -16,7 +16,8 @@ import "../../components/hui-action-editor"; import "../../components/hui-entity-editor"; import "../../components/hui-theme-select-editor"; import { LovelaceCardEditor } from "../../types"; -import { actionConfigStruct, EditorTarget } from "../types"; +import { actionConfigStruct } from "../structs/action-struct"; +import { EditorTarget } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts index a09f13cb68..20e062b514 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-glance-card-editor.ts @@ -16,11 +16,9 @@ import "../../components/hui-theme-select-editor"; import { EntityConfig } from "../../entity-rows/types"; import { LovelaceCardEditor } from "../../types"; import { processEditorEntities } from "../process-editor-entities"; -import { - actionConfigStruct, - EditorTarget, - entitiesConfigStruct, -} from "../types"; +import { actionConfigStruct } from "../structs/action-struct"; +import { entitiesConfigStruct } from "../structs/entities-struct"; +import { EditorTarget } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts index f5f3d18b58..0b8f9dc22a 100644 --- a/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-weather-forecast-card-editor.ts @@ -11,11 +11,8 @@ import { HomeAssistant } from "../../../../types"; import { WeatherForecastCardConfig } from "../../cards/types"; import "../../components/hui-theme-select-editor"; import { LovelaceCardEditor } from "../../types"; -import { - actionConfigStruct, - EditorTarget, - EntitiesEditorEvent, -} from "../types"; +import { actionConfigStruct } from "../structs/action-struct"; +import { EditorTarget, EntitiesEditorEvent } from "../types"; import { configElementStyle } from "./config-elements-style"; const cardConfigStruct = object({ diff --git a/src/panels/lovelace/editor/structs/action-struct.ts b/src/panels/lovelace/editor/structs/action-struct.ts new file mode 100644 index 0000000000..d5b35e161a --- /dev/null +++ b/src/panels/lovelace/editor/structs/action-struct.ts @@ -0,0 +1,67 @@ +import { + object, + string, + union, + boolean, + optional, + array, + literal, + enums, +} from "superstruct"; + +const actionConfigStructUser = object({ + user: string(), +}); + +const actionConfigStructConfirmation = union([ + boolean(), + object({ + text: optional(string()), + excemptions: optional(array(actionConfigStructUser)), + }), +]); + +const actionConfigStructUrl = object({ + action: literal("url"), + url_path: string(), + confirmation: optional(actionConfigStructConfirmation), +}); + +const actionConfigStructService = object({ + action: literal("call-service"), + service: string(), + service_data: optional(object()), + target: optional( + object({ + entity_id: optional(union([string(), array(string())])), + device_id: optional(union([string(), array(string())])), + area_id: optional(union([string(), array(string())])), + }) + ), + confirmation: optional(actionConfigStructConfirmation), +}); + +const actionConfigStructNavigate = object({ + action: literal("navigate"), + navigation_path: string(), + confirmation: optional(actionConfigStructConfirmation), +}); + +export const actionConfigStructType = object({ + action: enums([ + "none", + "toggle", + "more-info", + "call-service", + "url", + "navigate", + ]), + confirmation: optional(actionConfigStructConfirmation), +}); + +export const actionConfigStruct = union([ + actionConfigStructType, + actionConfigStructUrl, + actionConfigStructNavigate, + actionConfigStructService, +]); diff --git a/src/panels/lovelace/editor/structs/entities-struct.ts b/src/panels/lovelace/editor/structs/entities-struct.ts new file mode 100644 index 0000000000..fa170e3155 --- /dev/null +++ b/src/panels/lovelace/editor/structs/entities-struct.ts @@ -0,0 +1,18 @@ +import { union, object, string, optional, boolean } from "superstruct"; +import { actionConfigStruct } from "./action-struct"; + +export const entitiesConfigStruct = union([ + object({ + entity: string(), + name: optional(string()), + icon: optional(string()), + image: optional(string()), + secondary_info: optional(string()), + format: optional(string()), + state_color: optional(boolean()), + tap_action: optional(actionConfigStruct), + hold_action: optional(actionConfigStruct), + double_tap_action: optional(actionConfigStruct), + }), + string(), +]); diff --git a/src/panels/lovelace/editor/types.ts b/src/panels/lovelace/editor/types.ts index 762ed55d6e..73f2b3fe65 100644 --- a/src/panels/lovelace/editor/types.ts +++ b/src/panels/lovelace/editor/types.ts @@ -1,16 +1,3 @@ -import { - any, - array, - boolean, - dynamic, - enums, - literal, - number, - object, - optional, - string, - union, -} from "superstruct"; import { ActionConfig, LovelaceCardConfig, @@ -94,175 +81,3 @@ export interface SubElementEditorConfig { export interface EditSubElementEvent { subElementConfig: SubElementEditorConfig; } - -export const actionConfigStruct = dynamic((_value, ctx) => { - if (ctx.branch[0][ctx.path[0]]) { - return ( - actionConfigMap[ctx.branch[0][ctx.path[0]].action] || - actionConfigStructType - ); - } - - return actionConfigStructType; -}); - -const actionConfigStructUser = object({ - user: string(), -}); - -const actionConfigStructConfirmation = union([ - boolean(), - object({ - text: optional(string()), - excemptions: optional(array(actionConfigStructUser)), - }), -]); - -const actionConfigStructUrl = object({ - action: literal("url"), - url_path: string(), - confirmation: optional(actionConfigStructConfirmation), -}); - -const actionConfigStructService = object({ - action: literal("call-service"), - service: string(), - service_data: optional(object()), - target: optional( - object({ - entity_id: optional(union([string(), array(string())])), - device_id: optional(union([string(), array(string())])), - area_id: optional(union([string(), array(string())])), - }) - ), - confirmation: optional(actionConfigStructConfirmation), -}); - -const actionConfigStructNavigate = object({ - action: literal("navigate"), - navigation_path: string(), - confirmation: optional(actionConfigStructConfirmation), -}); - -const actionConfigMap = { - url: actionConfigStructUrl, - navigate: actionConfigStructNavigate, - "call-service": actionConfigStructService, -}; - -export const actionConfigStructType = object({ - action: enums([ - "none", - "toggle", - "more-info", - "call-service", - "url", - "navigate", - ]), - confirmation: optional(actionConfigStructConfirmation), -}); - -const buttonEntitiesRowConfigStruct = object({ - type: string(), - name: string(), - action_name: optional(string()), - tap_action: actionConfigStruct, - hold_action: optional(actionConfigStruct), - double_tap_action: optional(actionConfigStruct), -}); - -const castEntitiesRowConfigStruct = object({ - type: string(), - view: union([string(), number()]), - dashboard: optional(string()), - name: optional(string()), - icon: optional(string()), - hide_if_unavailable: optional(boolean()), -}); - -const callServiceEntitiesRowConfigStruct = object({ - type: string(), - name: string(), - service: string(), - icon: optional(string()), - action_name: optional(string()), - service_data: optional(any()), -}); - -const conditionalEntitiesRowConfigStruct = object({ - type: string(), - row: any(), - conditions: array( - object({ - entity: string(), - state: optional(string()), - state_not: optional(string()), - }) - ), -}); - -const dividerEntitiesRowConfigStruct = object({ - type: string(), - style: optional(any()), -}); - -const sectionEntitiesRowConfigStruct = object({ - type: string(), - label: optional(string()), -}); - -const webLinkEntitiesRowConfigStruct = object({ - type: string(), - url: string(), - name: optional(string()), - icon: optional(string()), -}); - -const buttonsEntitiesRowConfigStruct = object({ - type: string(), - entities: array( - union([ - object({ - entity: string(), - icon: optional(string()), - image: optional(string()), - name: optional(string()), - }), - string(), - ]) - ), -}); - -const attributeEntitiesRowConfigStruct = object({ - type: string(), - entity: string(), - attribute: string(), - prefix: optional(string()), - suffix: optional(string()), - name: optional(string()), -}); - -export const entitiesConfigStruct = union([ - object({ - entity: string(), - name: optional(string()), - icon: optional(string()), - image: optional(string()), - secondary_info: optional(string()), - format: optional(string()), - state_color: optional(boolean()), - tap_action: optional(actionConfigStruct), - hold_action: optional(actionConfigStruct), - double_tap_action: optional(actionConfigStruct), - }), - string(), - buttonEntitiesRowConfigStruct, - castEntitiesRowConfigStruct, - conditionalEntitiesRowConfigStruct, - dividerEntitiesRowConfigStruct, - sectionEntitiesRowConfigStruct, - webLinkEntitiesRowConfigStruct, - buttonsEntitiesRowConfigStruct, - attributeEntitiesRowConfigStruct, - callServiceEntitiesRowConfigStruct, -]); diff --git a/src/panels/lovelace/header-footer/structs.ts b/src/panels/lovelace/header-footer/structs.ts new file mode 100644 index 0000000000..2c275c63c9 --- /dev/null +++ b/src/panels/lovelace/header-footer/structs.ts @@ -0,0 +1,29 @@ +import { object, string, optional, array, number, union } from "superstruct"; +import { actionConfigStruct } from "../editor/structs/action-struct"; +import { entitiesConfigStruct } from "../editor/structs/entities-struct"; + +export const pictureHeaderFooterConfigStruct = object({ + type: string(), + image: string(), + tap_action: optional(actionConfigStruct), + hold_action: optional(actionConfigStruct), + double_tap_action: optional(actionConfigStruct), +}); + +export const buttonsHeaderFooterConfigStruct = object({ + type: string(), + entities: array(entitiesConfigStruct), +}); + +export const graphHeaderFooterConfigStruct = object({ + type: string(), + entity: string(), + detail: optional(number()), + hours_to_show: optional(number()), +}); + +export const headerFooterConfigStructs = union([ + pictureHeaderFooterConfigStruct, + buttonsHeaderFooterConfigStruct, + graphHeaderFooterConfigStruct, +]); diff --git a/src/panels/lovelace/header-footer/types.ts b/src/panels/lovelace/header-footer/types.ts index 00e058f759..ddbe7c79c8 100644 --- a/src/panels/lovelace/header-footer/types.ts +++ b/src/panels/lovelace/header-footer/types.ts @@ -1,6 +1,4 @@ -import { array, number, object, optional, string, union } from "superstruct"; import { ActionConfig } from "../../../data/lovelace"; -import { actionConfigStruct, entitiesConfigStruct } from "../editor/types"; import { EntityConfig } from "../entity-rows/types"; export interface LovelaceHeaderFooterConfig { @@ -27,29 +25,3 @@ export interface PictureHeaderFooterConfig extends LovelaceHeaderFooterConfig { hold_action?: ActionConfig; double_tap_action?: ActionConfig; } - -export const pictureHeaderFooterConfigStruct = object({ - type: string(), - image: string(), - tap_action: optional(actionConfigStruct), - hold_action: optional(actionConfigStruct), - double_tap_action: optional(actionConfigStruct), -}); - -export const buttonsHeaderFooterConfigStruct = object({ - type: string(), - entities: array(entitiesConfigStruct), -}); - -export const graphHeaderFooterConfigStruct = object({ - type: string(), - entity: string(), - detail: optional(number()), - hours_to_show: optional(number()), -}); - -export const headerFooterConfigStructs = union([ - pictureHeaderFooterConfigStruct, - buttonsHeaderFooterConfigStruct, - graphHeaderFooterConfigStruct, -]); From 2aa8f5b352a9f26203a564b5f23c6f9dec8af8ab Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 31 May 2021 05:11:53 +0200 Subject: [PATCH 11/13] Dev states: replace pattern in word by wildcard search (#9288) --- src/common/string/escape_regexp.ts | 2 + .../state/developer-tools-state.js | 94 +++++++++---------- 2 files changed, 47 insertions(+), 49 deletions(-) create mode 100644 src/common/string/escape_regexp.ts diff --git a/src/common/string/escape_regexp.ts b/src/common/string/escape_regexp.ts new file mode 100644 index 0000000000..2f218f1356 --- /dev/null +++ b/src/common/string/escape_regexp.ts @@ -0,0 +1,2 @@ +export const escapeRegExp = (text: string): string => + text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); diff --git a/src/panels/developer-tools/state/developer-tools-state.js b/src/panels/developer-tools/state/developer-tools-state.js index 3389d29ae6..e6b492aadf 100644 --- a/src/panels/developer-tools/state/developer-tools-state.js +++ b/src/panels/developer-tools/state/developer-tools-state.js @@ -11,8 +11,8 @@ import { html } from "@polymer/polymer/lib/utils/html-tag"; import { PolymerElement } from "@polymer/polymer/polymer-element"; import { dump, load } from "js-yaml"; import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time"; -import { isPatternInWord } from "../../../common/string/filter/filter"; import { computeRTL } from "../../../common/util/compute_rtl"; +import { escapeRegExp } from "../../../common/string/escape_regexp"; import { copyToClipboard } from "../../../common/util/copy-clipboard"; import "../../../components/entity/ha-entity-picker"; import "../../../components/ha-code-editor"; @@ -412,72 +412,68 @@ class HaPanelDevState extends EventsMixin(LocalizeMixin(PolymerElement)) { } computeEntities(hass, _entityFilter, _stateFilter, _attributeFilter) { - const _entityFilterLength = _entityFilter && _entityFilter.length; - const _entityFilterLow = _entityFilter && _entityFilter.toLowerCase(); + const entityFilterRegExp = + _entityFilter && + RegExp(escapeRegExp(_entityFilter).replace(/\\\*/g, ".*"), "i"); - return Object.keys(hass.states) - .map((key) => hass.states[key]) + const stateFilterRegExp = + _stateFilter && + RegExp(escapeRegExp(_stateFilter).replace(/\\\*/g, ".*"), "i"); + + let keyFilterRegExp; + let valueFilterRegExp; + let multiMode = false; + + if (_attributeFilter) { + const colonIndex = _attributeFilter.indexOf(":"); + multiMode = colonIndex !== -1; + + const keyFilter = multiMode + ? _attributeFilter.substring(0, colonIndex).trim() + : _attributeFilter; + const valueFilter = multiMode + ? _attributeFilter.substring(colonIndex + 1).trim() + : _attributeFilter; + + keyFilterRegExp = RegExp( + escapeRegExp(keyFilter).replace(/\\\*/g, ".*"), + "i" + ); + valueFilterRegExp = multiMode + ? RegExp(escapeRegExp(valueFilter).replace(/\\\*/g, ".*"), "i") + : keyFilterRegExp; + } + + return Object.values(hass.states) .filter((value) => { if ( - _entityFilter && - !isPatternInWord( - _entityFilterLow, - 0, - _entityFilterLength, - value.entity_id.toLowerCase(), - 0, - value.entity_id.length, - true - ) && + entityFilterRegExp && + !entityFilterRegExp.test(value.entity_id) && (value.attributes.friendly_name === undefined || - !isPatternInWord( - _entityFilterLow, - 0, - _entityFilterLength, - value.attributes.friendly_name.toLowerCase(), - 0, - value.attributes.friendly_name.length, - true - )) + !entityFilterRegExp.test(value.attributes.friendly_name)) ) { return false; } - if (!value.state.toLowerCase().includes(_stateFilter.toLowerCase())) { + if (stateFilterRegExp && !stateFilterRegExp.test(value.state)) { return false; } - if (_attributeFilter !== "") { - const attributeFilter = _attributeFilter.toLowerCase(); - const colonIndex = attributeFilter.indexOf(":"); - const multiMode = colonIndex !== -1; - - let keyFilter = attributeFilter; - let valueFilter = attributeFilter; - - if (multiMode) { - // we need to filter keys and values separately - keyFilter = attributeFilter.substring(0, colonIndex).trim(); - valueFilter = attributeFilter.substring(colonIndex + 1).trim(); - } - - const attributeKeys = Object.keys(value.attributes); - - for (let i = 0; i < attributeKeys.length; i++) { - const key = attributeKeys[i]; - - if (key.includes(keyFilter) && !multiMode) { + if (keyFilterRegExp && valueFilterRegExp) { + for (const [key, attributeValue] of Object.entries( + value.attributes + )) { + const match = keyFilterRegExp.test(key); + if (match && !multiMode) { return true; // in single mode we're already satisfied with this match } - if (!key.includes(keyFilter) && multiMode) { + if (!match && multiMode) { continue; } - const attributeValue = value.attributes[key]; - if ( attributeValue !== undefined && - JSON.stringify(attributeValue).toLowerCase().includes(valueFilter) + valueFilterRegExp.test(JSON.stringify(attributeValue)) ) { return true; } From 51a693badf7f66567f36f6c3dfd0c6f32b5dbc9b Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Mon, 31 May 2021 05:16:45 +0200 Subject: [PATCH 12/13] Convert `ha-store-auth-card` to Lit/TS/ha-card (#9300) --- package.json | 1 - src/dialogs/ha-store-auth-card.js | 74 ------------------------------ src/dialogs/ha-store-auth-card.ts | 75 +++++++++++++++++++++++++++++++ src/state/auth-mixin.ts | 2 +- yarn.lock | 12 +---- 5 files changed, 77 insertions(+), 87 deletions(-) delete mode 100644 src/dialogs/ha-store-auth-card.js create mode 100644 src/dialogs/ha-store-auth-card.ts diff --git a/package.json b/package.json index af32469d89..c316946391 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,6 @@ "@polymer/iron-label": "^3.0.1", "@polymer/iron-overlay-behavior": "^3.0.2", "@polymer/iron-resizable-behavior": "^3.0.1", - "@polymer/paper-card": "^3.0.1", "@polymer/paper-checkbox": "^3.1.0", "@polymer/paper-dialog": "^3.0.1", "@polymer/paper-dialog-behavior": "^3.0.1", diff --git a/src/dialogs/ha-store-auth-card.js b/src/dialogs/ha-store-auth-card.js deleted file mode 100644 index a3b39c1681..0000000000 --- a/src/dialogs/ha-store-auth-card.js +++ /dev/null @@ -1,74 +0,0 @@ -import "@polymer/paper-card/paper-card"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -/* eslint-plugin-disable lit */ -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import { enableWrite } from "../common/auth/token_storage"; -import LocalizeMixin from "../mixins/localize-mixin"; -import "../styles/polymer-ha-style"; - -class HaStoreAuth extends LocalizeMixin(PolymerElement) { - static get template() { - return html` - - -
[[localize('ui.auth_store.ask')]]
-
- [[localize('ui.auth_store.decline')]] - [[localize('ui.auth_store.confirm')]] -
-
- `; - } - - static get properties() { - return { - hass: Object, - }; - } - - ready() { - super.ready(); - this.classList.toggle("small", window.innerWidth < 600); - } - - _save() { - enableWrite(); - this._done(); - } - - _done() { - const card = this.shadowRoot.querySelector("paper-card"); - card.style.transition = "bottom .25s"; - card.style.bottom = `-${card.offsetHeight + 8}px`; - setTimeout(() => this.parentNode.removeChild(this), 300); - } -} - -customElements.define("ha-store-auth-card", HaStoreAuth); diff --git a/src/dialogs/ha-store-auth-card.ts b/src/dialogs/ha-store-auth-card.ts new file mode 100644 index 0000000000..b3229bfa73 --- /dev/null +++ b/src/dialogs/ha-store-auth-card.ts @@ -0,0 +1,75 @@ +import { LitElement, TemplateResult, html, css } from "lit"; +import { property } from "lit/decorators"; +import { enableWrite } from "../common/auth/token_storage"; +import { HomeAssistant } from "../types"; +import "../components/ha-card"; +import type { HaCard } from "../components/ha-card"; +import "@material/mwc-button/mwc-button"; + +class HaStoreAuth extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + protected render(): TemplateResult { + return html` + +
+ ${this.hass.localize("ui.auth_store.ask")} +
+
+ + ${this.hass.localize("ui.auth_store.decline")} + + + ${this.hass.localize("ui.auth_store.confirm")} + +
+
+ `; + } + + firstUpdated() { + this.classList.toggle("small", window.innerWidth < 600); + } + + private _save(): void { + enableWrite(); + this._dismiss(); + } + + private _dismiss(): void { + const card = this.shadowRoot!.querySelector("ha-card") as HaCard; + card.style.bottom = `-${card.offsetHeight + 8}px`; + setTimeout(() => this.parentNode!.removeChild(this), 300); + } + + static get styles() { + return css` + ha-card { + position: fixed; + padding: 8px 0; + bottom: 16px; + right: 16px; + transition: bottom 0.25s; + } + + .card-actions { + text-align: right; + border-top: 0; + } + + :host(.small) ha-card { + bottom: 0; + left: 0; + right: 0; + } + `; + } +} + +customElements.define("ha-store-auth-card", HaStoreAuth); + +declare global { + interface HTMLElementTagNameMap { + "ha-store-auth-card": HaStoreAuth; + } +} diff --git a/src/state/auth-mixin.ts b/src/state/auth-mixin.ts index 611a27f3b8..7800ce8433 100644 --- a/src/state/auth-mixin.ts +++ b/src/state/auth-mixin.ts @@ -32,8 +32,8 @@ export default >(superClass: T) => .then(() => import("../dialogs/ha-store-auth-card")) .then(() => { const el = document.createElement("ha-store-auth-card"); - this.shadowRoot!.appendChild(el); this.provideHass(el); + this.shadowRoot!.appendChild(el); }); } } diff --git a/yarn.lock b/yarn.lock index eccbc5fc48..5a9c6340ca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2104,7 +2104,7 @@ "@polymer/iron-meta" "^3.0.0-pre.26" "@polymer/polymer" "^3.0.0" -"@polymer/iron-image@^3.0.0-pre.26", "@polymer/iron-image@^3.0.1": +"@polymer/iron-image@^3.0.1": version "3.0.2" resolved "https://registry.yarnpkg.com/@polymer/iron-image/-/iron-image-3.0.2.tgz#425ee6269634e024dbea726a91a61724ae4402b6" integrity sha512-VyYtnewGozDb5sUeoLR1OvKzlt5WAL6b8Od7fPpio5oYL+9t061/nTV8+ZMrpMgF2WgB0zqM/3K53o3pbK5v8Q== @@ -2226,16 +2226,6 @@ "@polymer/paper-ripple" "^3.0.0-pre.26" "@polymer/polymer" "^3.0.0" -"@polymer/paper-card@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@polymer/paper-card/-/paper-card-3.0.1.tgz#fb5960b3e55fab56d20b7c1c3dee08f0d052ff2a" - integrity sha512-ZYzfA4kzP9niRO22wSOBL2RS+URZNUP5XmUCwN91fYPIGO0Qbimh7d1O2HpJD4cRCZhvGYn2CJMDMVmDm35vIg== - dependencies: - "@polymer/iron-flex-layout" "^3.0.0-pre.26" - "@polymer/iron-image" "^3.0.0-pre.26" - "@polymer/paper-styles" "^3.0.0-pre.26" - "@polymer/polymer" "^3.0.0" - "@polymer/paper-checkbox@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@polymer/paper-checkbox/-/paper-checkbox-3.1.0.tgz#66b903ae5814db237d027deb4a3f3430f48d905b" From db82a90414a1ef555d0d2a4bbff24e8f9d468caf Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 30 May 2021 20:17:02 -0700 Subject: [PATCH 13/13] Bumped version to 20210531.0 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 311519d4e2..acc46ddd38 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name="home-assistant-frontend", - version="20210528.0", + version="20210531.0", description="The Home Assistant frontend", url="https://github.com/home-assistant/home-assistant-polymer", author="The Home Assistant Authors",