Merge pull request #13302 from home-assistant/dev

Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
Zack Barett 2022-07-28 10:31:47 -05:00 committed by GitHub
commit 61b42249ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 138 additions and 66 deletions

View File

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

View File

@ -453,6 +453,7 @@ export class HaMap extends ReactiveElement {
} }
#map.dark { #map.dark {
background: #090909; background: #090909;
--map-filter: invert(0.9) hue-rotate(170deg) grayscale(0.7);
} }
.light { .light {
color: #000000; color: #000000;
@ -464,7 +465,7 @@ export class HaMap extends ReactiveElement {
filter: var(--map-filter); filter: var(--map-filter);
} }
.dark .leaflet-bar a { .dark .leaflet-bar a {
background: var(--card-background-color); background-color: var(--card-background-color, #1c1c1c);
color: #ffffff; color: #ffffff;
} }
.leaflet-marker-draggable { .leaflet-marker-draggable {

View File

@ -6,16 +6,17 @@ import { DataEntryFlowProgress, DataEntryFlowStep } from "./data_entry_flow";
import { domainToName } from "./integration"; import { domainToName } from "./integration";
export const DISCOVERY_SOURCES = [ export const DISCOVERY_SOURCES = [
"usb", "bluetooth",
"unignore",
"dhcp", "dhcp",
"homekit",
"ssdp",
"zeroconf",
"discovery", "discovery",
"hassio",
"homekit",
"integration_discovery", "integration_discovery",
"mqtt", "mqtt",
"hassio", "ssdp",
"unignore",
"usb",
"zeroconf",
]; ];
export const ATTENTION_SOURCES = ["reauth"]; export const ATTENTION_SOURCES = ["reauth"];

View File

@ -7,6 +7,7 @@ import type { DataEntryFlowStep } from "./data_entry_flow";
export interface RepairsIssue { export interface RepairsIssue {
domain: string; domain: string;
issue_domain?: string;
issue_id: string; issue_id: string;
active: boolean; active: boolean;
is_fixable: boolean; is_fixable: boolean;

View File

@ -21,6 +21,7 @@ import { LocalizeFunc } from "../../common/translations/localize";
import "../../components/ha-icon-next"; import "../../components/ha-icon-next";
import "../../components/search-input"; import "../../components/search-input";
import { domainToName } from "../../data/integration"; import { domainToName } from "../../data/integration";
import { haStyleScrollbar } from "../../resources/styles";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
import { brandsUrl } from "../../util/brands-url"; import { brandsUrl } from "../../util/brands-url";
import { documentationUrl } from "../../util/documentation-url"; import { documentationUrl } from "../../util/documentation-url";
@ -143,6 +144,7 @@ class StepFlowPickHandler extends LitElement {
width: `${this._width}px`, width: `${this._width}px`,
height: `${this._height}px`, height: `${this._height}px`,
})} })}
class="ha-scrollbar"
> >
${addDeviceRows.length ${addDeviceRows.length
? html` ? html`
@ -321,6 +323,7 @@ class StepFlowPickHandler extends LitElement {
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return [ return [
configFlowContentStyles, configFlowContentStyles,
haStyleScrollbar,
css` css`
img { img {
width: 40px; width: 40px;

View File

@ -1,15 +1,16 @@
import type { ActionDetail } from "@material/mwc-list"; import { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item";
import "@material/mwc-list/mwc-list-item";
import { mdiDotsVertical, mdiRefresh } from "@mdi/js"; import { mdiDotsVertical, mdiRefresh } from "@mdi/js";
import { HassEntities } from "home-assistant-js-websocket"; import { HassEntities } from "home-assistant-js-websocket";
import { css, html, LitElement, TemplateResult } from "lit"; import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import "../../../components/ha-bar"; import "../../../components/ha-bar";
import "../../../components/ha-button-menu"; import "../../../components/ha-button-menu";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-check-list-item";
import "../../../components/ha-metric"; import "../../../components/ha-metric";
import { extractApiErrorMessage } from "../../../data/hassio/common"; import { extractApiErrorMessage } from "../../../data/hassio/common";
import { import {
@ -72,20 +73,23 @@ class HaConfigSectionUpdates extends LitElement {
.path=${mdiRefresh} .path=${mdiRefresh}
@click=${this._checkUpdates} @click=${this._checkUpdates}
></ha-icon-button> ></ha-icon-button>
<ha-button-menu corner="BOTTOM_START" @action=${this._handleAction}> <ha-button-menu corner="BOTTOM_START" multi>
<ha-icon-button <ha-icon-button
slot="trigger" slot="trigger"
.label=${this.hass.localize("ui.common.menu")} .label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical} .path=${mdiDotsVertical}
></ha-icon-button> ></ha-icon-button>
<mwc-list-item id="skipped"> <ha-check-list-item
${this._showSkipped left
? this.hass.localize("ui.panel.config.updates.hide_skipped") @request-selected=${this._toggleSkipped}
: this.hass.localize("ui.panel.config.updates.show_skipped")} .selected=${this._showSkipped}
</mwc-list-item> >
${this.hass.localize("ui.panel.config.updates.show_skipped")}
</ha-check-list-item>
${this._supervisorInfo?.channel !== "dev" ${this._supervisorInfo?.channel !== "dev"
? html` ? html`
<mwc-list-item id="beta"> <li divider role="separator"></li>
<mwc-list-item @request-selected=${this._toggleBeta}>
${this._supervisorInfo?.channel === "stable" ${this._supervisorInfo?.channel === "stable"
? this.hass.localize("ui.panel.config.updates.join_beta") ? this.hass.localize("ui.panel.config.updates.join_beta")
: this.hass.localize( : this.hass.localize(
@ -122,18 +126,21 @@ class HaConfigSectionUpdates extends LitElement {
`; `;
} }
private _handleAction(ev: CustomEvent<ActionDetail>) { private _toggleSkipped(ev: CustomEvent<RequestSelectedDetail>): void {
switch (ev.detail.index) { if (ev.detail.source !== "property") {
case 0: return;
this._showSkipped = !this._showSkipped;
break;
case 1:
this._toggleBeta();
break;
} }
this._showSkipped = !this._showSkipped;
} }
private async _toggleBeta(): Promise<void> { private async _toggleBeta(
ev: CustomEvent<RequestSelectedDetail>
): Promise<void> {
if (!shouldHandleRequestSelectedEvent(ev)) {
return;
}
if (this._supervisorInfo!.channel === "stable") { if (this._supervisorInfo!.channel === "stable") {
const confirmed = await showConfirmationDialog(this, { const confirmed = await showConfirmationDialog(this, {
title: this.hass.localize("ui.dialogs.join_beta_channel.title"), title: this.hass.localize("ui.dialogs.join_beta_channel.title"),
@ -206,6 +213,9 @@ class HaConfigSectionUpdates extends LitElement {
.no-updates { .no-updates {
padding: 16px; padding: 16px;
} }
li[divider] {
border-bottom-color: var(--divider-color);
}
`; `;
} }

View File

@ -1,5 +1,5 @@
import "@material/mwc-button/mwc-button"; import "@material/mwc-button/mwc-button";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-card"; import "../../../components/ha-card";
@ -31,13 +31,14 @@ class DialogIntegrationStartup extends LitElement {
return html` return html`
<ha-dialog <ha-dialog
open open
@closed=${this.closeDialog}
scrimClickAction scrimClickAction
escapeKeyAction escapeKeyAction
hideActions
.heading=${createCloseHeading( .heading=${createCloseHeading(
this.hass, this.hass,
this.hass.localize("ui.panel.config.repairs.integration_startup_time") this.hass.localize("ui.panel.config.repairs.integration_startup_time")
)} )}
@closed=${this.closeDialog}
> >
<integrations-startup-time <integrations-startup-time
.hass=${this.hass} .hass=${this.hass}
@ -47,7 +48,14 @@ class DialogIntegrationStartup extends LitElement {
`; `;
} }
static styles: CSSResultGroup = haStyleDialog; static styles: CSSResultGroup = [
haStyleDialog,
css`
ha-dialog {
--dialog-content-padding: 0;
}
`,
];
} }
declare global { declare global {

View File

@ -48,29 +48,22 @@ class DialogRepairsIssue extends LitElement {
this.hass.localize( this.hass.localize(
`component.${this._issue.domain}.issues.${ `component.${this._issue.domain}.issues.${
this._issue.translation_key || this._issue.issue_id this._issue.translation_key || this._issue.issue_id
}.title` }.title`,
this._issue.translation_placeholders || {}
) || this.hass!.localize("ui.panel.config.repairs.dialog.title") ) || this.hass!.localize("ui.panel.config.repairs.dialog.title")
)} )}
> >
<div> <div>
<ha-alert ${this._issue.breaks_in_ha_version
.alertType=${this._issue.severity === "error" || ? html`
this._issue.severity === "critical" <ha-alert alert-type="error">
? "error" ${this.hass.localize(
: "warning"} "ui.panel.config.repairs.dialog.breaks_in_version",
.title=${this.hass.localize( { version: this._issue.breaks_in_ha_version }
`ui.panel.config.repairs.${this._issue.severity}` )}
)} </ha-alert>
>${this.hass.localize( `
"ui.panel.config.repairs.dialog.alert_not_fixable" : ""}
)}
${this._issue.breaks_in_ha_version
? this.hass.localize(
"ui.panel.config.repairs.dialog.breaks_in_version",
{ version: this._issue.breaks_in_ha_version }
)
: ""}
</ha-alert>
<ha-markdown <ha-markdown
allowsvg allowsvg
breaks breaks
@ -91,6 +84,19 @@ class DialogRepairsIssue extends LitElement {
> >
` `
: ""} : ""}
<div class="secondary">
<span class=${this._issue.severity}
>${this.hass.localize(
`ui.panel.config.repairs.${this._issue.severity}`
)}
</span>
-
${this._issue.created
? new Date(this._issue.created).toLocaleDateString(
this.hass.language
)
: ""}
</div>
</div> </div>
${this._issue.learn_more_url ${this._issue.learn_more_url
? html` ? html`
@ -137,6 +143,18 @@ class DialogRepairsIssue extends LitElement {
.dismissed { .dismissed {
font-style: italic; font-style: italic;
} }
.secondary {
margin-top: 8px;
text-align: right;
color: var(--secondary-text-color);
}
.error,
.critical {
color: var(--error-color);
}
.warning {
color: var(--warning-color);
}
`, `,
]; ];
} }

View File

@ -7,6 +7,7 @@ import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-check-list-item";
import { import {
RepairsIssue, RepairsIssue,
severitySort, severitySort,
@ -65,12 +66,20 @@ class HaConfigRepairsDashboard extends SubscribeMixin(LitElement) {
.header=${this.hass.localize("ui.panel.config.repairs.caption")} .header=${this.hass.localize("ui.panel.config.repairs.caption")}
> >
<div slot="toolbar-icon"> <div slot="toolbar-icon">
<ha-button-menu corner="BOTTOM_START"> <ha-button-menu corner="BOTTOM_START" multi>
<ha-icon-button <ha-icon-button
slot="trigger" slot="trigger"
.label=${this.hass.localize("ui.common.menu")} .label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical} .path=${mdiDotsVertical}
></ha-icon-button> ></ha-icon-button>
<ha-check-list-item
left
@request-selected=${this._toggleIgnored}
.selected=${this._showIgnored}
>
${this.hass.localize("ui.panel.config.repairs.show_ignored")}
</ha-check-list-item>
<li divider role="separator"></li>
${isComponentLoaded(this.hass, "system_health") || ${isComponentLoaded(this.hass, "system_health") ||
isComponentLoaded(this.hass, "hassio") isComponentLoaded(this.hass, "hassio")
? html` ? html`
@ -90,11 +99,6 @@ class HaConfigRepairsDashboard extends SubscribeMixin(LitElement) {
"ui.panel.config.repairs.integration_startup_time" "ui.panel.config.repairs.integration_startup_time"
)} )}
</mwc-list-item> </mwc-list-item>
<mwc-list-item @request-selected=${this._toggleIgnored}>
${this._showIgnored
? this.hass.localize("ui.panel.config.repairs.hide_ignored")
: this.hass.localize("ui.panel.config.repairs.show_ignored")}
</mwc-list-item>
</ha-button-menu> </ha-button-menu>
</div> </div>
<div class="content"> <div class="content">
@ -143,7 +147,7 @@ class HaConfigRepairsDashboard extends SubscribeMixin(LitElement) {
} }
private _toggleIgnored(ev: CustomEvent<RequestSelectedDetail>): void { private _toggleIgnored(ev: CustomEvent<RequestSelectedDetail>): void {
if (!shouldHandleRequestSelectedEvent(ev)) { if (ev.detail.source !== "property") {
return; return;
} }
@ -177,6 +181,9 @@ class HaConfigRepairsDashboard extends SubscribeMixin(LitElement) {
.no-repairs { .no-repairs {
padding: 16px; padding: 16px;
} }
li[divider] {
border-bottom-color: var(--divider-color);
}
`; `;
} }

View File

@ -2,6 +2,7 @@ import "@material/mwc-list/mwc-list";
import { css, html, LitElement, TemplateResult } from "lit"; import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { relativeTime } from "../../../common/datetime/relative_time"; import { relativeTime } from "../../../common/datetime/relative_time";
import { capitalizeFirstLetter } from "../../../common/string/capitalize-first-letter";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-list-item"; import "../../../components/ha-list-item";
@ -44,7 +45,7 @@ class HaConfigRepairs extends LitElement {
(issue) => html` (issue) => html`
<ha-list-item <ha-list-item
twoline twoline
graphic="avatar" graphic="medium"
.hasMeta=${!this.narrow} .hasMeta=${!this.narrow}
.issue=${issue} .issue=${issue}
class=${issue.ignored ? "ignored" : ""} class=${issue.ignored ? "ignored" : ""}
@ -53,7 +54,7 @@ class HaConfigRepairs extends LitElement {
<img <img
loading="lazy" loading="lazy"
src=${brandsUrl({ src=${brandsUrl({
domain: issue.domain, domain: issue.issue_domain || issue.domain,
type: "icon", type: "icon",
useFallback: true, useFallback: true,
darkOptimized: this.hass.themes?.darkMode, darkOptimized: this.hass.themes?.darkMode,
@ -66,12 +67,27 @@ class HaConfigRepairs extends LitElement {
>${this.hass.localize( >${this.hass.localize(
`component.${issue.domain}.issues.${ `component.${issue.domain}.issues.${
issue.translation_key || issue.issue_id issue.translation_key || issue.issue_id
}.title` }.title`,
issue.translation_placeholders || {}
)}</span )}</span
> >
<span slot="secondary" class="secondary"> <span slot="secondary" class="secondary">
${issue.severity === "critical" || issue.severity === "error"
? html`<span class="error"
>${this.hass.localize(
`ui.panel.config.repairs.${issue.severity}`
)}</span
>`
: ""}
${(issue.severity === "critical" ||
issue.severity === "error") &&
issue.created
? " - "
: ""}
${issue.created ${issue.created
? relativeTime(new Date(issue.created), this.hass.locale) ? capitalizeFirstLetter(
relativeTime(new Date(issue.created), this.hass.locale)
)
: ""} : ""}
${issue.ignored ${issue.ignored
? ` - ${this.hass.localize( ? ` - ${this.hass.localize(
@ -113,6 +129,9 @@ class HaConfigRepairs extends LitElement {
.ignored { .ignored {
opacity: var(--light-secondary-opacity); opacity: var(--light-secondary-opacity);
} }
ha-list-item {
--mdc-list-item-graphic-size: 40px;
}
button.show-more { button.show-more {
color: var(--primary-color); color: var(--primary-color);
text-align: left; text-align: left;
@ -133,6 +152,9 @@ class HaConfigRepairs extends LitElement {
cursor: pointer; cursor: pointer;
font-size: 16px; font-size: 16px;
} }
.error {
color: var(--error-color);
}
`; `;
} }

View File

@ -149,6 +149,10 @@ export const getMyRedirects = (hasSupervisor: boolean): Redirects => ({
logs: { logs: {
redirect: "/config/logs", redirect: "/config/logs",
}, },
repairs: {
component: "repairs",
redirect: "/config/repairs",
},
info: { info: {
redirect: "/config/info", redirect: "/config/info",
}, },

View File

@ -577,7 +577,7 @@
"title": "Media Management", "title": "Media Management",
"manage": "Manage", "manage": "Manage",
"no_items": "No media items found", "no_items": "No media items found",
"folders_not_supported": "Folders can not be managed via the UI.", "folders_not_supported": "Folders cannot be managed via the UI.",
"highlight_button": "Click here to upload your first media", "highlight_button": "Click here to upload your first media",
"upload_failed": "Upload failed: {reason}", "upload_failed": "Upload failed: {reason}",
"add_media": "Add Media", "add_media": "Add Media",
@ -1220,8 +1220,7 @@
"version_available": "Version {version_available} is available", "version_available": "Version {version_available} is available",
"more_updates": "Show all updates", "more_updates": "Show all updates",
"show": "show", "show": "show",
"show_skipped": "Show skipped", "show_skipped": "Show skipped updates",
"hide_skipped": "Hide skipped",
"join_beta": "[%key:supervisor::system::supervisor::join_beta_action%]", "join_beta": "[%key:supervisor::system::supervisor::join_beta_action%]",
"leave_beta": "[%key:supervisor::system::supervisor::leave_beta_action%]", "leave_beta": "[%key:supervisor::system::supervisor::leave_beta_action%]",
"skipped": "Skipped" "skipped": "Skipped"
@ -1232,8 +1231,7 @@
"title": "{count} {count, plural,\n one {repair}\n other {repairs}\n}", "title": "{count} {count, plural,\n one {repair}\n other {repairs}\n}",
"no_repairs": "There are currently no repairs available", "no_repairs": "There are currently no repairs available",
"more_repairs": "Show all repairs", "more_repairs": "Show all repairs",
"show_ignored": "Show ignored", "show_ignored": "Show ignored repairs",
"hide_ignored": "Hide ignored",
"critical": "Critical", "critical": "Critical",
"error": "Error", "error": "Error",
"warning": "Warning", "warning": "Warning",
@ -1246,8 +1244,7 @@
"learn": "Learn more", "learn": "Learn more",
"ignore": "Ignore", "ignore": "Ignore",
"unignore": "Unignore", "unignore": "Unignore",
"alert_not_fixable": "We can not repair this issue for you.", "breaks_in_version": "This stops working in version {version}. Please address before upgrading.",
"breaks_in_version": "This will break in version {version}. Please fix this issue before upgrading.",
"ignored_in_version_short": "Ignored in version {version}", "ignored_in_version_short": "Ignored in version {version}",
"ignored_in_version": "This issue was ignored in version {version}." "ignored_in_version": "This issue was ignored in version {version}."
} }