diff --git a/src/components/ha-dialog-header.ts b/src/components/ha-dialog-header.ts index 659a2124b1..995211c15b 100644 --- a/src/components/ha-dialog-header.ts +++ b/src/components/ha-dialog-header.ts @@ -10,8 +10,13 @@ export class HaDialogHeader extends LitElement {
-
- +
+
+ +
+
+ +
@@ -39,17 +44,24 @@ export class HaDialogHeader extends LitElement { padding: 4px; box-sizing: border-box; } - .header-title { + .header-content { flex: 1; - font-size: 22px; - line-height: 28px; - font-weight: 400; padding: 10px 4px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + .header-title { + font-size: 22px; + line-height: 28px; + font-weight: 400; + } + .header-subtitle { + font-size: 14px; + line-height: 20px; + color: var(--secondary-text-color); + } @media all and (min-width: 450px) and (min-height: 500px) { .header-bar { padding: 12px; diff --git a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts index 4ae9965e85..f35d8d88d6 100644 --- a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts @@ -31,6 +31,11 @@ export interface FlowConfig { deleteFlow(hass: HomeAssistant, flowId: string): Promise; + renderAbortHeader?( + hass: HomeAssistant, + step: DataEntryFlowStepAbort + ): TemplateResult | string; + renderAbortDescription( hass: HomeAssistant, step: DataEntryFlowStepAbort @@ -39,7 +44,7 @@ export interface FlowConfig { renderShowFormStepHeader( hass: HomeAssistant, step: DataEntryFlowStepForm - ): string; + ): string | TemplateResult; renderShowFormStepDescription( hass: HomeAssistant, @@ -95,14 +100,17 @@ export interface FlowConfig { renderShowFormProgressHeader( hass: HomeAssistant, step: DataEntryFlowStepProgress - ): string; + ): string | TemplateResult; renderShowFormProgressDescription( hass: HomeAssistant, step: DataEntryFlowStepProgress ): TemplateResult | ""; - renderMenuHeader(hass: HomeAssistant, step: DataEntryFlowStepMenu): string; + renderMenuHeader( + hass: HomeAssistant, + step: DataEntryFlowStepMenu + ): string | TemplateResult; renderMenuDescription( hass: HomeAssistant, diff --git a/src/dialogs/config-flow/step-flow-abort.ts b/src/dialogs/config-flow/step-flow-abort.ts index b91da83370..4ab121e8dc 100644 --- a/src/dialogs/config-flow/step-flow-abort.ts +++ b/src/dialogs/config-flow/step-flow-abort.ts @@ -31,7 +31,11 @@ class StepFlowAbort extends LitElement { return nothing; } return html` -

${this.hass.localize(`component.${this.domain}.title`)}

+

+ ${this.params.flowConfig.renderAbortHeader + ? this.params.flowConfig.renderAbortHeader(this.hass, this.step) + : this.hass.localize(`component.${this.domain}.title`)} +

${this.params.flowConfig.renderAbortDescription(this.hass, this.step)}
diff --git a/src/panels/config/repairs/dialog-repairs-issue-subtitle.ts b/src/panels/config/repairs/dialog-repairs-issue-subtitle.ts new file mode 100644 index 0000000000..3a09766df8 --- /dev/null +++ b/src/panels/config/repairs/dialog-repairs-issue-subtitle.ts @@ -0,0 +1,63 @@ +import { css, html, LitElement } from "lit"; +import { customElement, property } from "lit/decorators"; +import type { HomeAssistant } from "../../../types"; +import { domainToName } from "../../../data/integration"; +import type { RepairsIssue } from "../../../data/repairs"; + +@customElement("dialog-repairs-issue-subtitle") +class DialogRepairsIssueSubtitle extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ type: Object }) public issue!: RepairsIssue; + + protected firstUpdated() { + if (this.scrollWidth > this.offsetWidth) { + this.title = + (this.shadowRoot?.firstElementChild as HTMLElement)?.innerText || ""; + } + } + + protected render() { + const domainName = domainToName(this.hass.localize, this.issue.domain); + const reportedBy = domainName + ? this.hass.localize("ui.panel.config.repairs.reported_by", { + integration: domainName, + }) + : ""; + + const severity = this.hass.localize( + `ui.panel.config.repairs.${this.issue.severity}` + ); + + return html` + + ${severity} + ${reportedBy} + + `; + } + + static styles = css` + :host { + display: block; + font-size: 14px; + margin-bottom: 8px; + color: var(--secondary-text-color); + text-overflow: ellipsis; + overflow: hidden; + } + .error, + .critical { + color: var(--error-color); + } + .warning { + color: var(--warning-color); + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-repairs-issue-subtitle": DialogRepairsIssueSubtitle; + } +} diff --git a/src/panels/config/repairs/dialog-repairs-issue.ts b/src/panels/config/repairs/dialog-repairs-issue.ts index ece7a219f7..7d48662423 100644 --- a/src/panels/config/repairs/dialog-repairs-issue.ts +++ b/src/panels/config/repairs/dialog-repairs-issue.ts @@ -1,11 +1,14 @@ -import "@material/mwc-button/mwc-button"; +import { mdiClose } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators"; -import { formatDateNumeric } from "../../../common/datetime/format_date"; +import { customElement, property, state, query } from "lit/decorators"; import { fireEvent } from "../../../common/dom/fire_event"; import { isNavigationClick } from "../../../common/dom/is-navigation-click"; import "../../../components/ha-alert"; -import { createCloseHeading } from "../../../components/ha-dialog"; +import "../../../components/ha-md-dialog"; +import type { HaMdDialog } from "../../../components/ha-md-dialog"; +import "../../../components/ha-button"; +import "../../../components/ha-dialog-header"; +import "./dialog-repairs-issue-subtitle"; import "../../../components/ha-markdown"; import { ignoreRepairsIssue, RepairsIssue } from "../../../data/repairs"; import { haStyleDialog } from "../../../resources/styles"; @@ -20,12 +23,14 @@ class DialogRepairsIssue extends LitElement { @state() private _params?: RepairsIssueDialogParams; + @query("ha-md-dialog") private _dialog?: HaMdDialog; + public showDialog(params: RepairsIssueDialogParams): void { this._params = params; this._issue = this._params.issue; } - public closeDialog() { + private _dialogClosed() { if (this._params?.dialogClosedCallback) { this._params.dialogClosedCallback(); } @@ -35,6 +40,10 @@ class DialogRepairsIssue extends LitElement { fireEvent(this, "dialog-closed", { dialog: this.localName }); } + public closeDialog() { + this._dialog?.close(); + } + protected render() { if (!this._issue) { return nothing; @@ -43,23 +52,39 @@ class DialogRepairsIssue extends LitElement { const learnMoreUrlIsHomeAssistant = this._issue.learn_more_url?.startsWith("homeassistant://") || false; + const dialogTitle = + this.hass.localize( + `component.${this._issue.domain}.issues.${this._issue.translation_key || this._issue.issue_id}.title`, + this._issue.translation_placeholders || {} + ) || this.hass!.localize("ui.panel.config.repairs.dialog.title"); + return html` - -
+ + + ${dialogTitle} + + +
${this._issue.breaks_in_ha_version ? html` @@ -71,6 +96,7 @@ class DialogRepairsIssue extends LitElement { ` : ""} ` : ""} -
- ${this.hass.localize( - `ui.panel.config.repairs.${this._issue.severity}` - )} - - - - ${this._issue.created - ? formatDateNumeric( - new Date(this._issue.created), - this.hass.locale, - this.hass.config - ) - : ""} -
- ${this._issue.learn_more_url - ? html` - - - - ` - : ""} - - +
+ + ${this._issue!.ignored + ? this.hass!.localize("ui.panel.config.repairs.dialog.unignore") + : this.hass!.localize("ui.panel.config.repairs.dialog.ignore")} + + ${this._issue.learn_more_url + ? html` + + + ${this.hass!.localize( + "ui.panel.config.repairs.dialog.learn" + )} + + + ` + : ""} +
+ `; } @@ -154,28 +168,16 @@ class DialogRepairsIssue extends LitElement { static styles: CSSResultGroup = [ haStyleDialog, css` + .dialog-content { + padding-top: 0; + } ha-alert { margin-bottom: 16px; display: block; } - a { - text-decoration: none; - } .dismissed { 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); - } `, ]; } diff --git a/src/panels/config/repairs/ha-config-repairs.ts b/src/panels/config/repairs/ha-config-repairs.ts index 3446fb305b..50c4b9f2f4 100644 --- a/src/panels/config/repairs/ha-config-repairs.ts +++ b/src/panels/config/repairs/ha-config-repairs.ts @@ -1,12 +1,9 @@ -import "@material/mwc-list/mwc-list"; import { css, html, LitElement, nothing } from "lit"; import { customElement, property } from "lit/decorators"; import { relativeTime } from "../../../common/datetime/relative_time"; import { capitalizeFirstLetter } from "../../../common/string/capitalize-first-letter"; -import "../../../components/ha-alert"; -import "../../../components/ha-card"; -import "../../../components/ha-list-item"; -import "../../../components/ha-svg-icon"; +import "../../../components/ha-md-list"; +import "../../../components/ha-md-list-item"; import { domainToName } from "../../../data/integration"; import { fetchRepairsIssueData, @@ -48,19 +45,31 @@ class HaConfigRepairs extends LitElement { count: this.total || this.repairsIssues.length, })}
- - ${issues.map( - (issue) => html` - + ${issues.map((issue) => { + const domainName = domainToName(this.hass.localize, issue.domain); + + const createdBy = + issue.created && domainName + ? this.hass.localize("ui.panel.config.repairs.created_at_by", { + date: capitalizeFirstLetter( + relativeTime(new Date(issue.created), this.hass.locale) + ), + integration: domainName, + }) + : ""; + + return html` + ${domainToName(this.hass.localize, - ${this.hass.localize( - `component.${issue.domain}.issues.${ - issue.translation_key || issue.issue_id - }.title`, + + ${this.hass.localize( + `component.${issue.domain}.issues.${issue.translation_key || issue.issue_id}.title`, issue.translation_placeholders || {} ) || - `${issue.domain}: ${issue.translation_key || issue.issue_id}`} - + `${issue.domain}: ${issue.translation_key || issue.issue_id}`} + + ${issue.severity === "critical" || issue.severity === "error" ? html`${this.hass.localize( @@ -93,27 +99,25 @@ class HaConfigRepairs extends LitElement { ${(issue.severity === "critical" || issue.severity === "error") && issue.created - ? " - " - : ""} - ${issue.created - ? capitalizeFirstLetter( - relativeTime(new Date(issue.created), this.hass.locale) - ) + ? " ⸱ " : ""} + ${createdBy + ? html`${createdBy}` + : nothing} ${issue.ignored - ? ` - ${this.hass.localize( + ? ` ⸱ ${this.hass.localize( "ui.panel.config.repairs.dialog.ignored_in_version_short", { version: issue.dismissed_version } )}` : ""} ${!this.narrow - ? html`` + ? html`` : ""} - - ` - )} - + + `; + })} + `; } @@ -179,9 +183,6 @@ class HaConfigRepairs extends LitElement { .ignored { opacity: var(--light-secondary-opacity); } - ha-list-item { - --mdc-list-item-graphic-size: 40px; - } button.show-more { color: var(--primary-color); text-align: left; @@ -198,9 +199,12 @@ class HaConfigRepairs extends LitElement { outline: none; text-decoration: underline; } - ha-list-item { - cursor: pointer; - font-size: 16px; + ha-md-list-item img[slot="start"] { + width: 40px; + height: 40px; + } + ha-md-list-item span[slot="supporting-text"] { + white-space: nowrap; } .error { color: var(--error-color); diff --git a/src/panels/config/repairs/show-dialog-repair-flow.ts b/src/panels/config/repairs/show-dialog-repair-flow.ts index 88ef1e3734..890c51eeca 100644 --- a/src/panels/config/repairs/show-dialog-repair-flow.ts +++ b/src/panels/config/repairs/show-dialog-repair-flow.ts @@ -1,6 +1,7 @@ -import { html } from "lit"; +import { html, nothing } from "lit"; import { DataEntryFlowStep } from "../../../data/data_entry_flow"; import { domainToName } from "../../../data/integration"; +import "./dialog-repairs-issue-subtitle"; import { RepairsIssue, createRepairsFlow, @@ -66,6 +67,16 @@ export const showRepairsFlowDialog = ( handleFlowStep: handleRepairsFlowStep, deleteFlow: deleteRepairsFlow, + renderAbortHeader(hass) { + return html` + ${hass.localize("ui.dialogs.repair_flow.form.header")} + + `; + }, + renderAbortDescription(hass, step) { const description = hass.localize( `component.${issue.domain}.issues.${ @@ -87,14 +98,18 @@ export const showRepairsFlowDialog = ( }, renderShowFormStepHeader(hass, step) { - return ( - hass.localize( + return html` + ${hass.localize( `component.${issue.domain}.issues.${ issue.translation_key || issue.issue_id }.fix_flow.step.${step.step_id}.title`, mergePlaceholders(issue, step) - ) || hass.localize("ui.dialogs.repair_flow.form.header") - ); + ) || hass.localize("ui.dialogs.repair_flow.form.header")} + + `; }, renderShowFormStepDescription(hass, step) { @@ -113,7 +128,7 @@ export const showRepairsFlowDialog = ( .content=${description} > ` - : ""}`; + : nothing}`; }, renderShowFormStepFieldLabel(hass, step, field, options) { @@ -135,7 +150,7 @@ export const showRepairsFlowDialog = ( return html`${renderIssueDescription(hass, issue)} ${description ? html`` - : ""}`; + : nothing}`; }, renderShowFormStepFieldError(hass, step, error) { @@ -181,14 +196,18 @@ export const showRepairsFlowDialog = ( }, renderShowFormProgressHeader(hass, step) { - return ( - hass.localize( + return html` + ${hass.localize( `component.${issue.domain}.issues.step.${ issue.translation_key || issue.issue_id }.fix_flow.${step.step_id}.title`, mergePlaceholders(issue, step) - ) || hass.localize(`component.${issue.domain}.title`) - ); + ) || hass.localize(`component.${issue.domain}.title`)} + + `; }, renderShowFormProgressDescription(hass, step) { @@ -206,18 +225,22 @@ export const showRepairsFlowDialog = ( .content=${description} > ` - : ""}`; + : nothing}`; }, renderMenuHeader(hass, step) { - return ( - hass.localize( + return html` + ${hass.localize( `component.${issue.domain}.issues.${ issue.translation_key || issue.issue_id }.fix_flow.step.${step.step_id}.title`, mergePlaceholders(issue, step) - ) || hass.localize(`component.${issue.domain}.title`) - ); + ) || hass.localize(`component.${issue.domain}.title`)} + + `; }, renderMenuDescription(hass, step) { @@ -236,7 +259,7 @@ export const showRepairsFlowDialog = ( .content=${description} > ` - : ""}`; + : nothing}`; }, renderMenuOption(hass, step, option) { diff --git a/src/translations/en.json b/src/translations/en.json index 8d25102250..c6002da58b 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1972,6 +1972,8 @@ "system_information": "System information", "integration_startup_time": "Integration startup time", "copy": "Copy", + "reported_by": "Reported by {integration}", + "created_at_by": "{date} by {integration}", "dialog": { "title": "Repair", "fix": "Repair",