Add Ignore Action + dialog updates (#13254)

This commit is contained in:
Zack Barett 2022-07-25 04:36:00 -05:00 committed by GitHub
parent 63ea8e6568
commit b9ae0e72b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 159 additions and 59 deletions

View File

@ -27,14 +27,16 @@ export const fetchRepairsIssues = async (hass: HomeAssistant) =>
type: "repairs/list_issues", type: "repairs/list_issues",
}); });
export const dismissRepairsIssue = async ( export const ignoreRepairsIssue = async (
hass: HomeAssistant, hass: HomeAssistant,
issue: RepairsIssue issue: RepairsIssue,
ignore: boolean
) => ) =>
hass.callWS<string>({ hass.callWS<string>({
type: "repairs/dismiss_issue", type: "repairs/ignore_issue",
issue_id: issue.issue_id, issue_id: issue.issue_id,
domain: issue.domain, domain: issue.domain,
ignore,
}); });
export const createRepairsFlow = ( export const createRepairsFlow = (

View File

@ -4,7 +4,7 @@ import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { createCloseHeading } from "../../../components/ha-dialog"; import { createCloseHeading } from "../../../components/ha-dialog";
import "../../../components/ha-markdown"; import "../../../components/ha-markdown";
import type { RepairsIssue } from "../../../data/repairs"; import { ignoreRepairsIssue, RepairsIssue } from "../../../data/repairs";
import { haStyleDialog } from "../../../resources/styles"; import { haStyleDialog } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import type { RepairsIssueDialogParams } from "./show-repair-issue-dialog"; import type { RepairsIssueDialogParams } from "./show-repair-issue-dialog";
@ -23,6 +23,10 @@ class DialogRepairsIssue extends LitElement {
} }
public closeDialog() { public closeDialog() {
if (this._params?.dialogClosedCallback) {
this._params.dialogClosedCallback();
}
this._params = undefined; this._params = undefined;
this._issue = undefined; this._issue = undefined;
fireEvent(this, "dialog-closed", { dialog: this.localName }); fireEvent(this, "dialog-closed", { dialog: this.localName });
@ -50,6 +54,24 @@ class DialogRepairsIssue extends LitElement {
)} )}
> >
<div> <div>
<ha-alert
.alertType=${this._issue.severity === "error" ||
this._issue.severity === "critical"
? "error"
: "warning"}
.title=${this.hass.localize(
`ui.panel.config.repairs.${this._issue.severity}`
)}
>${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
@ -60,19 +82,14 @@ class DialogRepairsIssue extends LitElement {
this._issue.translation_placeholders this._issue.translation_placeholders
)} )}
></ha-markdown> ></ha-markdown>
${this._issue.breaks_in_ha_version
? html`
<br />This will no longer work as of the
${this._issue.breaks_in_ha_version} release of Home Assistant.
`
: ""}
<br />The issue is ${this._issue.severity} severity.<br />We can not
automatically repair this issue for you.
${this._issue.dismissed_version ${this._issue.dismissed_version
? html` ? html`
<br />This issue has been dismissed in version <br /><span class="dismissed">
${this._issue.dismissed_version}. ${this.hass.localize(
"ui.panel.config.repairs.dialog.dismissed_in_version",
{ version: this._issue.dismissed_version }
)}</span
>
` `
: ""} : ""}
</div> </div>
@ -84,20 +101,43 @@ class DialogRepairsIssue extends LitElement {
slot="primaryAction" slot="primaryAction"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
<mwc-button .label=${"Learn More"}></mwc-button> <mwc-button
.label=${this.hass!.localize(
"ui.panel.config.repairs.dialog.learn"
)}
></mwc-button>
</a> </a>
` `
: ""} : ""}
<mwc-button
slot="secondaryAction"
.label=${this._issue!.ignored
? this.hass!.localize("ui.panel.config.repairs.dialog.unignore")
: this.hass!.localize("ui.panel.config.repairs.dialog.ignore")}
@click=${this._ignoreIssue}
></mwc-button>
</ha-dialog> </ha-dialog>
`; `;
} }
private _ignoreIssue() {
ignoreRepairsIssue(this.hass, this._issue!, !this._issue!.ignored);
this.closeDialog();
}
static styles: CSSResultGroup = [ static styles: CSSResultGroup = [
haStyleDialog, haStyleDialog,
css` css`
ha-alert {
margin-bottom: 16px;
display: block;
}
a { a {
text-decoration: none; text-decoration: none;
} }
.dismissed {
font-style: italic;
}
`, `,
]; ];
} }

View File

@ -1,8 +1,14 @@
import type { ActionDetail } from "@material/mwc-list";
import { mdiDotsVertical } from "@mdi/js";
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import "../../../components/ha-card"; import "../../../components/ha-card";
import type { RepairsIssue } from "../../../data/repairs"; import {
import { fetchRepairsIssues } from "../../../data/repairs"; fetchRepairsIssues,
RepairsIssue,
severitySort,
} from "../../../data/repairs";
import "../../../layouts/hass-subpage"; import "../../../layouts/hass-subpage";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "./ha-config-repairs"; import "./ha-config-repairs";
@ -15,12 +21,25 @@ class HaConfigRepairsDashboard extends LitElement {
@state() private _repairsIssues: RepairsIssue[] = []; @state() private _repairsIssues: RepairsIssue[] = [];
@state() private _showIgnored = false;
private _getFilteredIssues = memoizeOne(
(showIgnored: boolean, repairsIssues: RepairsIssue[]) =>
showIgnored
? repairsIssues
: repairsIssues.filter((issue) => !issue.ignored)
);
protected firstUpdated(changedProps: PropertyValues): void { protected firstUpdated(changedProps: PropertyValues): void {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
this._fetchIssues(); this._fetchIssues();
} }
protected render(): TemplateResult { protected render(): TemplateResult {
const issues = this._getFilteredIssues(
this._showIgnored,
this._repairsIssues
);
return html` return html`
<hass-subpage <hass-subpage
back-path="/config/system" back-path="/config/system"
@ -28,6 +47,20 @@ class HaConfigRepairsDashboard extends LitElement {
.narrow=${this.narrow} .narrow=${this.narrow}
.header=${this.hass.localize("ui.panel.config.repairs.caption")} .header=${this.hass.localize("ui.panel.config.repairs.caption")}
> >
<div slot="toolbar-icon">
<ha-button-menu corner="BOTTOM_START" @action=${this._handleAction}>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<mwc-list-item id="skipped">
${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>
</div>
<div class="content"> <div class="content">
<ha-card outlined> <ha-card outlined>
<div class="card-content"> <div class="card-content">
@ -36,7 +69,7 @@ class HaConfigRepairsDashboard extends LitElement {
<ha-config-repairs <ha-config-repairs
.hass=${this.hass} .hass=${this.hass}
.narrow=${this.narrow} .narrow=${this.narrow}
.repairsIssues=${this._repairsIssues} .repairsIssues=${issues}
@update-issues=${this._fetchIssues} @update-issues=${this._fetchIssues}
></ha-config-repairs> ></ha-config-repairs>
` `
@ -55,7 +88,9 @@ class HaConfigRepairsDashboard extends LitElement {
} }
private async _fetchIssues(): Promise<void> { private async _fetchIssues(): Promise<void> {
this._repairsIssues = (await fetchRepairsIssues(this.hass)).issues; this._repairsIssues = (await fetchRepairsIssues(this.hass)).issues.sort(
(a, b) => severitySort[a.severity] - severitySort[b.severity]
);
const integrations: Set<string> = new Set(); const integrations: Set<string> = new Set();
for (const issue of this._repairsIssues) { for (const issue of this._repairsIssues) {
integrations.add(issue.domain); integrations.add(issue.domain);
@ -63,6 +98,14 @@ class HaConfigRepairsDashboard extends LitElement {
this.hass.loadBackendTranslation("issues", [...integrations]); this.hass.loadBackendTranslation("issues", [...integrations]);
} }
private _handleAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) {
case 0:
this._showIgnored = !this._showIgnored;
break;
}
}
static styles = css` static styles = css`
.content { .content {
padding: 28px 20px 0; padding: 28px 20px 0;

View File

@ -41,43 +41,41 @@ class HaConfigRepairs extends LitElement {
})} })}
</div> </div>
<mwc-list> <mwc-list>
${issues.map((issue) => ${issues.map(
issue.ignored (issue) => html`
? "" <ha-list-item
: html` twoline
<ha-list-item graphic="avatar"
twoline .hasMeta=${!this.narrow}
graphic="avatar" .issue=${issue}
.hasMeta=${!this.narrow} @click=${this._openShowMoreDialog}
.issue=${issue} >
@click=${this._openShowMoreDialog} <img
> loading="lazy"
<img src=${brandsUrl({
loading="lazy" domain: issue.domain,
src=${brandsUrl({ type: "icon",
domain: issue.domain, useFallback: true,
type: "icon", darkOptimized: this.hass.themes?.darkMode,
useFallback: true, })}
darkOptimized: this.hass.themes?.darkMode, .title=${domainToName(this.hass.localize, issue.domain)}
})} referrerpolicy="no-referrer"
.title=${domainToName(this.hass.localize, issue.domain)} slot="graphic"
referrerpolicy="no-referrer" />
slot="graphic" <span
/> >${this.hass.localize(
<span `component.${issue.domain}.issues.${
>${this.hass.localize( issue.translation_key || issue.issue_id
`component.${issue.domain}.issues.${ }.title`
issue.translation_key || issue.issue_id )}</span
}.title` >
)}</span <span slot="secondary" class="secondary">
> ${issue.created
<span slot="secondary" class="secondary"> ? relativeTime(new Date(issue.created), this.hass.locale)
${issue.created : ""}
? relativeTime(new Date(issue.created), this.hass.locale) </span>
: ""} </ha-list-item>
</span> `
</ha-list-item>
`
)} )}
</mwc-list> </mwc-list>
`; `;
@ -91,7 +89,13 @@ class HaConfigRepairs extends LitElement {
fireEvent(this, "update-issues"); fireEvent(this, "update-issues");
}); });
} else { } else {
showRepairsIssueDialog(this, { issue: (ev.currentTarget as any).issue }); showRepairsIssueDialog(this, {
issue,
dialogClosedCallback: () => {
// @ts-ignore
fireEvent(this, "update-issues");
},
});
} }
} }

View File

@ -3,6 +3,7 @@ import type { RepairsIssue } from "../../../data/repairs";
export interface RepairsIssueDialogParams { export interface RepairsIssueDialogParams {
issue: RepairsIssue; issue: RepairsIssue;
dialogClosedCallback: () => void;
} }
export const loadRepairsIssueDialog = () => import("./dialog-repairs-issue"); export const loadRepairsIssueDialog = () => import("./dialog-repairs-issue");

View File

@ -1232,10 +1232,20 @@
"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": "+{count} repairs", "more_repairs": "+{count} repairs",
"show_ignored": "Show ignored",
"hide_ignored": "Hide ignored",
"critical": "Critical",
"error": "Error",
"warning": "Warning",
"dialog": { "dialog": {
"title": "Repair", "title": "Repair",
"fix": "Repair", "fix": "Repair",
"learn": "Learn more" "learn": "Learn more",
"ignore": "Ignore",
"unignore": "Unignore",
"alert_not_fixable": "We can not repair this issue for you.",
"breaks_in_version": "This will break in version {version}. Please fix this issue before upgrading.",
"dismissed_in_version": "This issue was dismissed in version {version}."
} }
}, },
"areas": { "areas": {