20241223.1 (#23402)

This commit is contained in:
Bram Kragten 2024-12-23 15:38:28 +01:00 committed by GitHub
commit e7d9032cc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 206 additions and 217 deletions

View File

@ -55,7 +55,7 @@ jobs:
script/release
- name: Upload release assets
uses: softprops/action-gh-release@v2.2.0
uses: softprops/action-gh-release@v2.1.0
with:
files: |
dist/*.whl
@ -107,7 +107,7 @@ jobs:
- name: Tar folder
run: tar -czf landing-page/home_assistant_frontend_landingpage-${{ github.event.release.tag_name }}.tar.gz -C landing-page/dist .
- name: Upload release asset
uses: softprops/action-gh-release@v2.2.0
uses: softprops/action-gh-release@v2.1.0
with:
files: landing-page/home_assistant_frontend_landingpage-${{ github.event.release.tag_name }}.tar.gz
@ -136,6 +136,6 @@ jobs:
- name: Tar folder
run: tar -czf hassio/home_assistant_frontend_supervisor-${{ github.event.release.tag_name }}.tar.gz -C hassio/build .
- name: Upload release asset
uses: softprops/action-gh-release@v2.2.0
uses: softprops/action-gh-release@v2.1.0
with:
files: hassio/home_assistant_frontend_supervisor-${{ github.event.release.tag_name }}.tar.gz

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
version = "20241223.0"
version = "20241223.1"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"

View File

@ -22,14 +22,6 @@ export class HaOutlinedField extends MdOutlinedField {
border-end-start-radius: var(--_container-shape-end-start);
border-end-end-radius: var(--_container-shape-end-end);
}
.with-start .start {
margin-inline-end: var(--ha-outlined-field-start-margin, 4px);
margin-inline-start: initial;
}
.with-end .end {
margin-inline-start: var(--ha-outlined-field-end-margin, 4px);
margin-inline-end: initial;
}
`,
];
}

View File

@ -28,8 +28,9 @@ export class HaOutlinedTextField extends MdOutlinedTextField {
--md-outlined-field-container-shape-end-end: 10px;
--md-outlined-field-container-shape-end-start: 10px;
--md-outlined-field-focus-outline-width: 1px;
--ha-outlined-field-start-margin: -4px;
--ha-outlined-field-end-margin: -4px;
--md-outlined-field-with-leading-content-leading-space: 8px;
--md-outlined-field-with-trailing-content-trailing-space: 8px;
--md-outlined-field-content-space: 8px;
--mdc-icon-size: var(--md-input-chip-icon-size, 18px);
}
.input {

View File

@ -871,7 +871,7 @@ class HaSidebar extends SubscribeMixin(LitElement) {
border-bottom: 1px solid var(--divider-color);
background-color: var(
--sidebar-menu-button-background-color,
var(--primary-background-color)
inherit
);
font-size: 20px;
align-items: center;

View File

@ -173,7 +173,7 @@ class DialogAreaDetail extends LitElement {
>
${entry
? this.hass.localize("ui.common.save")
: this.hass.localize("ui.common.add")}
: this.hass.localize("ui.common.create")}
</mwc-button>
</ha-dialog>
`;

View File

@ -237,7 +237,7 @@ class DialogFloorDetail extends LitElement {
>
${entry
? this.hass.localize("ui.common.save")
: this.hass.localize("ui.common.add")}
: this.hass.localize("ui.common.create")}
</mwc-button>
</ha-dialog>
`;

View File

@ -51,7 +51,7 @@ class HaBackupConfigAgents extends LitElement {
private _description(agentId: string) {
if (agentId === CLOUD_AGENT) {
return "It stores one backup. The oldest backups are deleted.";
return "Note: It stores only one backup, regardless of your settings.";
}
if (isNetworkMountAgent(agentId)) {
return "Network storage";

View File

@ -195,7 +195,7 @@ class HaBackupConfigData extends LitElement {
></ha-svg-icon>
<span slot="headline">Media</span>
<span slot="supporting-text">
For example, camera recordings.
This can include large filesize camera recordings.
</span>
<ha-switch
id="media"
@ -209,7 +209,7 @@ class HaBackupConfigData extends LitElement {
<ha-svg-icon slot="start" .path=${mdiFolder}></ha-svg-icon>
<span slot="headline">Share folder</span>
<span slot="supporting-text">
Folder that is often used for advanced or older
Folder that is often used by add-ons for advanced or older
configurations.
</span>
<ha-switch

View File

@ -75,6 +75,7 @@ class HaBackupSummaryCard extends LitElement {
row-gap: 8px;
align-items: center;
padding: 16px;
padding-bottom: 8px;
width: 100%;
box-sizing: border-box;
}
@ -145,10 +146,6 @@ class HaBackupSummaryCard extends LitElement {
}
@media all and (max-width: 550px) {
.summary {
flex-wrap: wrap;
padding: 8px;
}
.action {
width: 100%;
display: flex;

View File

@ -1,84 +0,0 @@
import { differenceInDays } from "date-fns";
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one";
import { formatShortDateTime } from "../../../../common/datetime/format_date_time";
import type { BackupContent } from "../../../../data/backup";
import type { ManagerStateEvent } from "../../../../data/backup_manager";
import type { HomeAssistant } from "../../../../types";
import "./ha-backup-summary-card";
@customElement("ha-backup-summary-status")
export class HaBackupSummaryProgress extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public manager!: ManagerStateEvent;
@property({ attribute: false }) public backups!: BackupContent[];
@property({ type: Boolean, attribute: "has-action" })
public hasAction = false;
private _lastBackup = memoizeOne((backups: BackupContent[]) => {
const sortedBackups = backups
// eslint-disable-next-line arrow-body-style
.filter((backup) => {
// TODO : only show backups with default flag
return backup.with_automatic_settings;
})
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
return sortedBackups[0] as BackupContent | undefined;
});
protected render() {
const lastBackup = this._lastBackup(this.backups);
if (!lastBackup) {
return html`
<ha-backup-summary-card
heading="No backup available"
description="You have not created any backups yet."
.hasAction=${this.hasAction}
status="warning"
>
<slot name="action" slot="action"></slot>
</ha-backup-summary-card>
`;
}
const lastBackupDate = new Date(lastBackup.date);
const numberOfDays = differenceInDays(new Date(), lastBackupDate);
// TODO : Improve time format
const description = `Last successful backup ${formatShortDateTime(lastBackupDate, this.hass.locale, this.hass.config)} and synced to ${lastBackup.agent_ids?.length} locations`;
if (numberOfDays > 8) {
return html`
<ha-backup-summary-card
heading=${`No backup for ${numberOfDays} days`}
description=${description}
.hasAction=${this.hasAction}
status="warning"
>
<slot name="action" slot="action"></slot>
</ha-backup-summary-card>
`;
}
return html`
<ha-backup-summary-card
heading=${`Backed up`}
description=${description}
.hasAction=${this.hasAction}
status="success"
>
<slot name="action" slot="action"></slot>
</ha-backup-summary-card>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-backup-summary-status": HaBackupSummaryProgress;
}
}

View File

@ -109,9 +109,13 @@ class HaBackupOverviewBackups extends LitElement {
display: flex;
justify-content: flex-end;
}
.card-header {
padding-bottom: 8px;
}
.card-content {
padding-left: 0;
padding-right: 0;
padding-bottom: 0;
}
`,
];

View File

@ -31,21 +31,20 @@ class HaBackupOverviewBackups extends LitElement {
<div class="icon">
<ha-svg-icon .path=${mdiInformationOutline}></ha-svg-icon>
</div>
Set up automatic backups
Set up backups
</div>
<div class="card-content">
<p>
Backups are essential to a reliable smart home. They protect your
setup against failures and allows you to quickly have a working
system again. It is recommended to create a daily backup and keep
backups of the last 3 days on two different locations. And one of
them is off-site.
Backups are essential for a reliable smart home. They help protect
the work you've put into setting up your smart home, and if the
worst happens, you can get back up and running quickly. It is
recommended that you create a backup every day. You should keep
three backups in at least two different locations, one of which
should be off-site.
</p>
</div>
<div class="card-actions">
<ha-button @click=${this._setup}>
Set up automatic backups
</ha-button>
<ha-button @click=${this._setup}>Set up backups</ha-button>
</div>
</ha-card>
`;

View File

@ -10,7 +10,11 @@ import "../../../../../components/ha-md-list";
import "../../../../../components/ha-md-list-item";
import "../../../../../components/ha-svg-icon";
import type { BackupConfig } from "../../../../../data/backup";
import { BackupScheduleState, isLocalAgent } from "../../../../../data/backup";
import {
BackupScheduleState,
computeBackupAgentName,
isLocalAgent,
} from "../../../../../data/backup";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant } from "../../../../../types";
@ -88,6 +92,14 @@ class HaBackupBackupsSummary extends LitElement {
);
if (offsiteLocations.length) {
if (offsiteLocations.length === 1) {
const name = computeBackupAgentName(
this.hass.localize,
offsiteLocations[0],
offsiteLocations
);
return `Upload to ${name}`;
}
return `Upload to ${offsiteLocations.length} off-site locations`;
}
if (hasLocal) {
@ -184,9 +196,13 @@ class HaBackupBackupsSummary extends LitElement {
display: flex;
justify-content: flex-end;
}
.card-header {
padding-bottom: 8px;
}
.card-content {
padding-left: 0;
padding-right: 0;
padding-bottom: 0;
}
`,
];

View File

@ -1,5 +1,5 @@
import { mdiBackupRestore, mdiCalendar } from "@mdi/js";
import { differenceInDays, setHours, setMinutes } from "date-fns";
import { addHours, differenceInDays, setHours, setMinutes } from "date-fns";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
@ -17,6 +17,8 @@ import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant } from "../../../../../types";
import "../ha-backup-summary-card";
const OVERDUE_MARGIN_HOURS = 3;
@customElement("ha-backup-overview-summary")
class HaBackupOverviewBackups extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@ -25,9 +27,14 @@ class HaBackupOverviewBackups extends LitElement {
@property({ attribute: false }) public config!: BackupConfig;
@property({ type: Boolean }) public fetching = false;
private _lastBackup = memoizeOne((backups: BackupContent[]) => {
const sortedBackups = backups
.filter((backup) => backup.with_automatic_settings)
.filter(
(backup) =>
backup.with_automatic_settings && !backup.failed_agent_ids?.length
)
.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
return sortedBackups[0] as BackupContent | undefined;
@ -60,6 +67,23 @@ class HaBackupOverviewBackups extends LitElement {
}
protected render() {
if (this.fetching) {
return html`
<ha-backup-summary-card heading="Loading backups" status="loading">
<ha-md-list>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiBackupRestore}></ha-svg-icon>
<span slot="headline" class="skeleton"></span>
</ha-md-list-item>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiCalendar}></ha-svg-icon>
<span slot="headline" class="skeleton"></span>
</ha-md-list-item>
</ha-md-list>
</ha-backup-summary-card>
`;
}
const lastBackup = this._lastBackup(this.backups);
if (!lastBackup) {
@ -75,10 +99,9 @@ class HaBackupOverviewBackups extends LitElement {
const lastBackupDate = new Date(lastBackup.date);
const numberOfDays = differenceInDays(new Date(), lastBackupDate);
const now = new Date();
const lastBackupDescription = `Last successful backup ${relativeTime(lastBackupDate, this.hass.locale, now, true)} and synced to ${lastBackup.agent_ids?.length} locations.`;
const lastBackupDescription = `Last successful backup ${relativeTime(lastBackupDate, this.hass.locale, now, true)} and stored to ${lastBackup.agent_ids?.length} locations.`;
const nextBackupDescription = this._nextBackupDescription(
this.config.schedule.state
);
@ -94,51 +117,62 @@ class HaBackupOverviewBackups extends LitElement {
heading=${`Last automatic backup failed`}
status="error"
>
<ul class="list">
<li class="item">
<ha-md-list>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiBackupRestore}></ha-svg-icon>
<span>${lastAttemptDescription}</span>
</li>
<li class="item">
<span slot="headline">${lastAttemptDescription}</span>
</ha-md-list-item>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiCalendar}></ha-svg-icon>
<span>${lastBackupDescription}</span>
</li>
</ul>
<span slot="headline">${lastBackupDescription}</span>
</ha-md-list-item>
</ha-md-list>
</ha-backup-summary-card>
`;
}
if (numberOfDays > 0) {
const numberOfDays = differenceInDays(
// Subtract a few hours to avoid showing as overdue if it's just a few hours (e.g. daylight saving)
addHours(now, -OVERDUE_MARGIN_HOURS),
lastBackupDate
);
const isOverdue =
(numberOfDays >= 1 &&
this.config.schedule.state === BackupScheduleState.DAILY) ||
numberOfDays >= 7;
if (isOverdue) {
return html`
<ha-backup-summary-card
heading=${`No backup for ${numberOfDays} days`}
status="warning"
>
<ul class="list">
<li class="item">
<ha-md-list>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiBackupRestore}></ha-svg-icon>
<span>${lastBackupDescription}</span>
</li>
<li class="item">
<span slot="headline">${lastBackupDescription}</span>
</ha-md-list-item>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiCalendar}></ha-svg-icon>
<span>${nextBackupDescription}</span>
</li>
</ul>
<span slot="headline">${nextBackupDescription}</span>
</ha-md-list-item>
</ha-md-list>
</ha-backup-summary-card>
`;
}
return html`
<ha-backup-summary-card heading=${`Backed up`} status="success">
<ul class="list">
<li class="item">
<ha-md-list>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiBackupRestore}></ha-svg-icon>
<span>${lastBackupDescription}</span>
</li>
<li class="item">
<span slot="headline">${lastBackupDescription}</span>
</ha-md-list-item>
<ha-md-list-item>
<ha-svg-icon slot="start" .path=${mdiCalendar}></ha-svg-icon>
<span>${nextBackupDescription}</span>
</li>
</ul>
<span slot="headline">${nextBackupDescription}</span>
</ha-md-list-item>
</ha-md-list>
</ha-backup-summary-card>
`;
}
@ -156,25 +190,6 @@ class HaBackupOverviewBackups extends LitElement {
p {
margin: 0;
}
.list {
display: flex;
flex-direction: column;
gap: 16px;
padding: 8px 24px 24px 24px;
margin: 0;
}
.item {
display: flex;
flex-direction: row;
gap: 16px;
align-items: center;
color: var(--secondary-text-color);
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: 0.25px;
}
ha-svg-icon {
flex: none;
}
@ -183,6 +198,42 @@ class HaBackupOverviewBackups extends LitElement {
justify-content: flex-end;
border-top: none;
}
ha-md-list {
background: none;
}
ha-md-list-item {
--md-list-item-top-space: 8px;
--md-list-item-bottom-space: 8px;
--md-list-item-one-line-container-height: 40x;
}
span.skeleton {
position: relative;
display: block;
width: 160px;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: loading;
animation-timing-function: linear;
animation-duration: 1.2s;
border-radius: 4px;
height: 20px;
background: linear-gradient(
to right,
rgb(247, 249, 250) 8%,
rgb(235, 238, 240) 18%,
rgb(247, 249, 250) 33%
)
0% 0% / 936px 104px;
}
@keyframes loading {
0% {
background-position: -468px 0;
}
100% {
background-position: 468px 0;
}
}
`,
];
}

View File

@ -287,13 +287,14 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
src="/static/images/voice-assistant/hi.png"
alt="Casita Home Assistant logo"
/>
<h1>Set up your automatic backups</h1>
<h1>Set up backups</h1>
<p class="secondary">
Backups are essential to a reliable smart home. They protect your
setup against failures and allows you to quickly have a working
system again. It is recommended to create a daily backup and keep
backups of the last 3 days on two different locations. And one of
them is off-site.
Backups are essential for a reliable smart home. They help protect
the work you've put into setting up your smart home, and if the
worst happens, you can get back up and running quickly. It is
recommended that you create a backup every day. You should keep
three backups in at least two different locations, one of which
should be off-site.
</p>
</div>
`;
@ -327,21 +328,23 @@ class DialogBackupOnboarding extends LitElement implements HassDialog {
case "setup":
return html`
<p>
It is recommended to create a daily backup and keep backups of the
last 3 days on two different locations. And one of them is off-site.
It is recommended that you create a backup every day. You should
keep three backups in at least two different locations, one of which
should be off-site. Once you make your selection, your first backup
will begin.
</p>
<ha-md-list class="full">
<ha-md-list-item type="button" @click=${this._done}>
<span slot="headline">Recommended settings</span>
<span slot="supporting-text">
Set the proven settings of daily backup.
Backup everything daily, keeping three days of backups
</span>
<ha-icon-next slot="end"> </ha-icon-next>
</ha-md-list-item>
<ha-md-list-item type="button" @click=${this._nextStep}>
<span slot="headline">Custom settings</span>
<span slot="supporting-text">
Select your own automation, data and locations
Select when, where, and what to backup
</span>
<ha-icon-next slot="end"> </ha-icon-next>
</ha-md-list-item>

View File

@ -152,7 +152,7 @@ class DialogChangeBackupEncryptionKey extends LitElement implements HassDialog {
<ha-md-list-item>
<span slot="headline">Download old emergency kit</span>
<span slot="supporting-text">
We recommend to save this encryption key somewhere secure.
We recommend saving this encryption key file somewhere secure.
</span>
<ha-button slot="end" @click=${this._downloadOld}>
<ha-svg-icon .path=${mdiDownload} slot="icon"></ha-svg-icon>
@ -164,9 +164,10 @@ class DialogChangeBackupEncryptionKey extends LitElement implements HassDialog {
case "new":
return html`
<p>
All next backups will use the new encryption key. We recommend to
save this key somewhere secure. As you can only restore your data
with the backup encryption key.
Keep this encryption key in a safe place, as you will need it to
access your backup, allowing it to be restored. Either record the
characters below or download them as an emergency kit file.
Encryption keeps your backups private and secure.
</p>
<div class="encryption-key">
<p>${this._newEncryptionKey}</p>
@ -179,7 +180,7 @@ class DialogChangeBackupEncryptionKey extends LitElement implements HassDialog {
<ha-md-list-item>
<span slot="headline">Download new emergency kit</span>
<span slot="supporting-text">
We recommend to save this encryption key somewhere secure.
We recommend saving this encryption key file somewhere secure.
</span>
<ha-button slot="end" @click=${this._downloadNew}>
<ha-svg-icon .path=${mdiDownload} slot="icon"></ha-svg-icon>

View File

@ -125,7 +125,8 @@ class HaConfigBackupDetails extends LitElement {
: !this._backup
? html`<ha-circular-progress active></ha-circular-progress>`
: html`
<ha-card header="Backup">
<ha-card>
<div class="card-header">Backup</div>
<div class="card-content">
<ha-md-list>
<ha-md-list-item>
@ -145,7 +146,8 @@ class HaConfigBackupDetails extends LitElement {
</ha-md-list>
</div>
</ha-card>
<ha-card header="Select what to restore">
<ha-card>
<div class="card-header">Select what to restore</div>
<div class="card-content">
<ha-backup-data-picker
.hass=${this.hass}
@ -166,7 +168,8 @@ class HaConfigBackupDetails extends LitElement {
</ha-button>
</div>
</ha-card>
<ha-card header="Locations">
<ha-card>
<div class="card-header">Locations</div>
<div class="card-content">
<ha-md-list>
${this._agents.map((agent) => {
@ -355,7 +358,7 @@ class HaConfigBackupDetails extends LitElement {
margin-bottom: 24px;
}
.card-content {
padding: 0 20px 8px 20px;
padding: 0 20px;
}
.card-actions {
display: flex;
@ -368,6 +371,7 @@ class HaConfigBackupDetails extends LitElement {
ha-md-list-item {
--md-list-item-leading-space: 0;
--md-list-item-trailing-space: 0;
--md-list-item-two-line-container-height: 64px;
}
ha-md-list-item img {
width: 48px;
@ -410,6 +414,9 @@ class HaConfigBackupDetails extends LitElement {
.dot.error {
background-color: var(--error-color);
}
.card-header {
padding-bottom: 8px;
}
`;
}

View File

@ -27,7 +27,6 @@ import "../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../resources/styles";
import type { HomeAssistant, Route } from "../../../types";
import "./components/ha-backup-summary-card";
import "./components/ha-backup-summary-status";
import "./components/overview/ha-backup-overview-backups";
import "./components/overview/ha-backup-overview-onboarding";
import "./components/overview/ha-backup-overview-progress";
@ -182,31 +181,23 @@ class HaConfigBackupOverview extends LitElement {
>
</ha-backup-overview-progress>
`
: this.fetching
: this._needsOnboarding
? html`
<ha-backup-summary-card
heading="Loading backups"
description="Your backup information is being retrieved."
status="loading"
<ha-backup-overview-onboarding
.hass=${this.hass}
@button-click=${this._handleOnboardingButtonClick}
>
</ha-backup-summary-card>
</ha-backup-overview-onboarding>
`
: this._needsOnboarding
? html`
<ha-backup-overview-onboarding
.hass=${this.hass}
@button-click=${this._handleOnboardingButtonClick}
>
</ha-backup-overview-onboarding>
`
: html`
<ha-backup-overview-summary
.hass=${this.hass}
.backups=${this.backups}
.config=${this.config}
>
</ha-backup-overview-summary>
`}
: html`
<ha-backup-overview-summary
.hass=${this.hass}
.backups=${this.backups}
.config=${this.config}
.fetching=${this.fetching}
>
</ha-backup-overview-summary>
`}
<ha-backup-overview-backups
.hass=${this.hass}

View File

@ -140,10 +140,10 @@ class HaConfigBackupSettings extends LitElement {
<div class="card-header">Encryption key</div>
<div class="card-content">
<p>
All your backups are encrypted to keep your data private and
secure. You need this key to restore a backup. It's important
that you don't lose this key, as no one else can restore your
data.
Keep this encryption key in a safe place, as you will need it to
access your backup, allowing it to be restored. Either record
the characters below or download them as an emergency kit file.
Encryption keeps your backups private and secure.
</p>
<ha-backup-config-encryption-key
.hass=${this.hass}
@ -257,6 +257,12 @@ class HaConfigBackupSettings extends LitElement {
.alert {
--mdc-theme-primary: var(--error-color);
}
.card-header {
padding-bottom: 8px;
}
.card-content {
padding-bottom: 0;
}
`;
}

View File

@ -436,9 +436,8 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
>
${this.narrow
? html`
<div slot="header">
<div slot="header" class="header">
<search-input-outlined
class="header"
.hass=${this.hass}
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
@ -457,7 +456,6 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
></ha-integration-overflow-menu>
<div class="search">
<search-input-outlined
class="header"
.hass=${this.hass}
.filter=${this._filter}
@value-changed=${this._handleSearchChange}
@ -982,6 +980,9 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
search-input-outlined {
flex: 1;
}
.header {
display: flex;
}
.search {
display: flex;
justify-content: space-between;

View File

@ -59,6 +59,7 @@ export class HuiViewBackgroundEditor extends LitElement {
translation_key:
"ui.panel.lovelace.editor.edit_view.background.size",
options: ["auto", "cover", "contain"],
mode: "dropdown",
},
},
},
@ -79,6 +80,7 @@ export class HuiViewBackgroundEditor extends LitElement {
"bottom center",
"bottom right",
],
mode: "dropdown",
},
},
},
@ -89,6 +91,7 @@ export class HuiViewBackgroundEditor extends LitElement {
translation_key:
"ui.panel.lovelace.editor.edit_view.background.repeat",
options: ["repeat", "no-repeat"],
mode: "dropdown",
},
},
},

View File

@ -348,6 +348,7 @@
"move": "Move",
"save": "Save",
"add": "Add",
"create": "Create",
"edit": "Edit",
"submit": "Submit",
"rename": "Rename",
@ -2159,7 +2160,7 @@
"edit_floor": "Edit floor",
"delete_floor": "Delete floor",
"confirm_delete": "Delete floor?",
"confirm_delete_text": "Removing the floor will unassign all areas from it."
"confirm_delete_text": "Deleting the floor will unassign all areas from it."
}
},
"editor": {
@ -4358,7 +4359,7 @@
"error_delete": "Error deleting device",
"picker": {
"search": "Search {number} devices",
"state": "State",
"state": "Status",
"bulk_actions": {
"move_area": "Move to area",
"no_area": "No area",