Update discovered/disabled/ignored integrations (#17107)

This commit is contained in:
Bram Kragten 2023-06-29 18:47:24 +02:00 committed by GitHub
parent a7100b9678
commit a09d71291b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 216 additions and 201 deletions

View File

@ -1,15 +1,10 @@
import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item";
import { mdiBookshelf, mdiCog, mdiDotsVertical, mdiOpenInNew } from "@mdi/js";
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 { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import {
mdiBookshelf,
mdiCog,
mdiDotsVertical,
mdiEyeOff,
mdiOpenInNew,
} from "@mdi/js";
import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import { import {
ATTENTION_SOURCES, ATTENTION_SOURCES,
DISCOVERY_SOURCES, DISCOVERY_SOURCES,
@ -17,13 +12,12 @@ import {
localizeConfigFlowTitle, localizeConfigFlowTitle,
} from "../../../data/config_flow"; } from "../../../data/config_flow";
import type { IntegrationManifest } from "../../../data/integration"; import type { IntegrationManifest } from "../../../data/integration";
import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow"; import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import { documentationUrl } from "../../../util/documentation-url";
import type { DataEntryFlowProgressExtended } from "./ha-config-integrations"; import type { DataEntryFlowProgressExtended } from "./ha-config-integrations";
import "./ha-integration-action-card"; import "./ha-integration-action-card";
import { documentationUrl } from "../../../util/documentation-url";
@customElement("ha-config-flow-card") @customElement("ha-config-flow-card")
export class HaConfigFlowCard extends LitElement { export class HaConfigFlowCard extends LitElement {
@ -38,16 +32,10 @@ export class HaConfigFlowCard extends LitElement {
return html` return html`
<ha-integration-action-card <ha-integration-action-card
class=${classMap({ class=${classMap({
discovered: !attention,
attention: attention, attention: attention,
})} })}
.hass=${this.hass} .hass=${this.hass}
.manifest=${this.manifest} .manifest=${this.manifest}
.banner=${this.hass.localize(
`ui.panel.config.integrations.${
attention ? "attention" : "discovered"
}`
)}
.domain=${this.flow.handler} .domain=${this.flow.handler}
.label=${this.flow.localized_title} .label=${this.flow.localized_title}
> >
@ -60,7 +48,17 @@ export class HaConfigFlowCard extends LitElement {
}` }`
)} )}
></mwc-button> ></mwc-button>
<ha-button-menu slot="header-button"> ${DISCOVERY_SOURCES.includes(this.flow.context.source) &&
this.flow.context.unique_id
? html`<mwc-button
@click=${this._ignoreFlow}
.label=${this.hass.localize(
`ui.panel.config.integrations.ignore.ignore`
)}
></mwc-button>`
: ""}
${this.flow.context.configuration_url || this.manifest
? html`<ha-button-menu slot="header-button">
<ha-icon-button <ha-icon-button
slot="trigger" slot="trigger"
.label=${this.hass.localize("ui.common.menu")} .label=${this.hass.localize("ui.common.menu")}
@ -84,7 +82,10 @@ export class HaConfigFlowCard extends LitElement {
"ui.panel.config.integrations.config_entry.open_configuration_url" "ui.panel.config.integrations.config_entry.open_configuration_url"
)} )}
<ha-svg-icon slot="graphic" .path=${mdiCog}></ha-svg-icon> <ha-svg-icon slot="graphic" .path=${mdiCog}></ha-svg-icon>
<ha-svg-icon slot="meta" .path=${mdiOpenInNew}></ha-svg-icon> <ha-svg-icon
slot="meta"
.path=${mdiOpenInNew}
></ha-svg-icon>
</mwc-list-item> </mwc-list-item>
</a>` </a>`
: ""} : ""}
@ -107,25 +108,15 @@ export class HaConfigFlowCard extends LitElement {
slot="graphic" slot="graphic"
.path=${mdiBookshelf} .path=${mdiBookshelf}
></ha-svg-icon> ></ha-svg-icon>
<ha-svg-icon slot="meta" .path=${mdiOpenInNew}></ha-svg-icon> <ha-svg-icon
slot="meta"
.path=${mdiOpenInNew}
></ha-svg-icon>
</mwc-list-item> </mwc-list-item>
</a>` </a>`
: ""} : ""}
${DISCOVERY_SOURCES.includes(this.flow.context.source) && </ha-button-menu>`
this.flow.context.unique_id
? html`
<mwc-list-item
graphic="icon"
@request-selected=${this._ignoreFlow}
>
${this.hass.localize(
"ui.panel.config.integrations.ignore.ignore"
)}
<ha-svg-icon slot="graphic" .path=${mdiEyeOff}></ha-svg-icon>
</mwc-list-item>
`
: ""} : ""}
</ha-button-menu>
</ha-integration-action-card> </ha-integration-action-card>
`; `;
} }
@ -174,14 +165,6 @@ export class HaConfigFlowCard extends LitElement {
} }
static styles = css` static styles = css`
.attention {
--state-color: var(--error-color);
--text-on-state-color: var(--text-primary-color);
}
.discovered {
--state-color: var(--primary-color);
--text-on-state-color: var(--text-primary-color);
}
a { a {
text-decoration: none; text-decoration: none;
color: var(--primary-color); color: var(--primary-color);

View File

@ -377,7 +377,12 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
</div> </div>
`} `}
${this._showIgnored ${this._showIgnored
? html`<div class="container"> ? html`<h1>
${this.hass.localize(
"ui.panel.config.integrations.ignore.ignored"
)}
</h1>
<div class="container">
${ignoredConfigEntries.map( ${ignoredConfigEntries.map(
(entry: ConfigEntryExtended) => html` (entry: ConfigEntryExtended) => html`
<ha-ignored-config-entry-card <ha-ignored-config-entry-card
@ -391,7 +396,10 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
</div>` </div>`
: ""} : ""}
${configEntriesInProgress.length ${configEntriesInProgress.length
? html`<div class="container"> ? html`<h1>
${this.hass.localize("ui.panel.config.integrations.discovered")}
</h1>
<div class="container">
${configEntriesInProgress.map( ${configEntriesInProgress.map(
(flow: DataEntryFlowProgressExtended) => html` (flow: DataEntryFlowProgressExtended) => html`
<ha-config-flow-card <ha-config-flow-card
@ -405,7 +413,10 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
</div>` </div>`
: ""} : ""}
${this._showDisabled ${this._showDisabled
? html`<div class="container"> ? html`<h1>
${this.hass.localize("ui.panel.config.integrations.disabled")}
</h1>
<div class="container">
${disabledConfigEntries.map( ${disabledConfigEntries.map(
(entry: ConfigEntryExtended) => html` (entry: ConfigEntryExtended) => html`
<ha-disabled-config-entry-card <ha-disabled-config-entry-card
@ -756,6 +767,8 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
.empty-message { .empty-message {
margin: auto; margin: auto;
text-align: center; text-align: center;
grid-column-start: 1;
grid-column-end: -1;
} }
.empty-message h1 { .empty-message h1 {
margin-bottom: 0; margin-bottom: 0;
@ -851,6 +864,9 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
.menu-badge-container { .menu-badge-container {
position: relative; position: relative;
} }
h1 {
margin: 8px 0 0 16px;
}
ha-button-menu { ha-button-menu {
color: var(--primary-text-color); color: var(--primary-text-color);
} }

View File

@ -1,9 +1,14 @@
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 type { IntegrationManifest } from "../../../data/integration"; import {
domainToName,
type IntegrationManifest,
} from "../../../data/integration";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "./ha-integration-header"; import "./ha-integration-header";
import "../../../components/ha-card"; import "../../../components/ha-card";
import { brandsUrl } from "../../../util/brands-url";
import { haStyle } from "../../../resources/styles";
@customElement("ha-integration-action-card") @customElement("ha-integration-action-card")
export class HaIntegrationActionCard extends LitElement { export class HaIntegrationActionCard extends LitElement {
@ -22,29 +27,65 @@ export class HaIntegrationActionCard extends LitElement {
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<ha-card outlined> <ha-card outlined>
<ha-integration-header <div class="card-content">
.hass=${this.hass} <img
.banner=${this.banner} alt=""
.domain=${this.domain} src=${brandsUrl({
.label=${this.label} domain: this.domain,
.localizedDomainName=${this.localizedDomainName} type: "icon",
.manifest=${this.manifest} darkOptimized: this.hass.themes?.darkMode,
> })}
<span slot="header-button"><slot name="header-button"></slot></span> referrerpolicy="no-referrer"
</ha-integration-header> @error=${this._onImageError}
@load=${this._onImageLoad}
/>
<h2>${this.label}</h2>
<h3>
${this.localizedDomainName ||
domainToName(this.hass.localize, this.domain, this.manifest)}
</h3>
</div>
<div class="filler"></div> <div class="filler"></div>
<div class="actions"><slot></slot></div> <div class="card-actions"><slot></slot></div>
<div class="header-button"><slot name="header-button"></slot></div>
</ha-card> </ha-card>
`; `;
} }
static styles = css` private _onImageLoad(ev) {
ev.target.style.visibility = "initial";
}
private _onImageError(ev) {
ev.target.style.visibility = "hidden";
}
static styles = [
haStyle,
css`
ha-card { ha-card {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
--ha-card-border-color: var(--state-color); }
--mdc-theme-primary: var(--state-color); img {
width: 40px;
height: 40px;
}
h2 {
font-size: 16px;
font-weight: 400;
margin-top: 8px;
margin-bottom: 0;
}
h3 {
font-size: 14px;
margin: 0;
}
.header-button {
position: absolute;
top: 8px;
right: 8px;
} }
.filler { .filler {
flex: 1; flex: 1;
@ -53,18 +94,27 @@ export class HaIntegrationActionCard extends LitElement {
--state-color: var(--error-color); --state-color: var(--error-color);
--text-on-state-color: var(--text-primary-color); --text-on-state-color: var(--text-primary-color);
} }
.discovered { .card-content {
--state-color: var(--primary-color);
--text-on-state-color: var(--text-primary-color);
}
.actions {
display: flex; display: flex;
justify-content: space-between; justify-content: center;
flex-direction: column;
align-items: center; align-items: center;
padding: 8px 6px 0;
height: 48px;
} }
`; .card-actions {
border-top: none;
padding-top: 0;
padding-bottom: 16px;
justify-content: center;
display: flex;
}
:host ::slotted(*) {
margin-right: 8px;
}
:host ::slotted(:last-child) {
margin-right: 0;
}
`,
];
} }
declare global { declare global {

View File

@ -10,10 +10,6 @@ import { brandsUrl } from "../../../util/brands-url";
export class HaIntegrationHeader extends LitElement { export class HaIntegrationHeader extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public banner?: string;
@property() public label?: string;
@property() public error?: string; @property() public error?: string;
@property() public warning?: string; @property() public warning?: string;
@ -25,25 +21,11 @@ export class HaIntegrationHeader extends LitElement {
@property({ attribute: false }) public manifest?: IntegrationManifest; @property({ attribute: false }) public manifest?: IntegrationManifest;
protected render(): TemplateResult { protected render(): TemplateResult {
let primary: string;
let secondary: string | undefined;
const domainName = const domainName =
this.localizedDomainName || this.localizedDomainName ||
domainToName(this.hass.localize, this.domain, this.manifest); domainToName(this.hass.localize, this.domain, this.manifest);
if (this.label) {
primary = this.label;
secondary =
primary.toLowerCase() === domainName.toLowerCase()
? undefined
: domainName;
} else {
primary = domainName;
}
return html` return html`
${!this.banner ? "" : html`<div class="banner">${this.banner}</div>`}
<div class="header"> <div class="header">
<img <img
alt="" alt=""
@ -62,7 +44,7 @@ export class HaIntegrationHeader extends LitElement {
role="heading" role="heading"
aria-level="1" aria-level="1"
> >
${primary} ${domainName}
</div> </div>
${this.error ${this.error
? html`<div class="error"> ? html`<div class="error">
@ -74,8 +56,6 @@ export class HaIntegrationHeader extends LitElement {
<ha-svg-icon .path=${mdiAlertOutline}></ha-svg-icon>${this <ha-svg-icon .path=${mdiAlertOutline}></ha-svg-icon>${this
.warning} .warning}
</div>` </div>`
: secondary
? html`<div class="secondary">${secondary}</div>`
: nothing} : nothing}
</div> </div>
<div class="header-button"> <div class="header-button">
@ -94,16 +74,6 @@ export class HaIntegrationHeader extends LitElement {
} }
static styles = css` static styles = css`
.banner {
background-color: var(--state-color);
color: var(--text-on-state-color);
text-align: center;
padding: 2px;
/* Padding is subtracted for nested elements with border radiuses */
border-top-left-radius: calc(var(--ha-card-border-radius, 12px) - 2px);
border-top-right-radius: calc(var(--ha-card-border-radius, 12px) - 2px);
}
.header { .header {
display: flex; display: flex;
position: relative; position: relative;
@ -126,8 +96,7 @@ export class HaIntegrationHeader extends LitElement {
} }
.primary, .primary,
.warning, .warning,
.error, .error {
.secondary {
word-wrap: break-word; word-wrap: break-word;
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
@ -152,10 +121,6 @@ export class HaIntegrationHeader extends LitElement {
-webkit-line-clamp: 1; -webkit-line-clamp: 1;
font-size: 0.9em; font-size: 0.9em;
} }
.secondary {
font-size: 14px;
color: var(--secondary-text-color);
}
.error ha-svg-icon { .error ha-svg-icon {
margin-right: 4px; margin-right: 4px;
color: var(--error-color); color: var(--error-color);

View File

@ -3301,6 +3301,7 @@
"description": "Manage integrations with services or devices", "description": "Manage integrations with services or devices",
"integration": "integration", "integration": "integration",
"discovered": "Discovered", "discovered": "Discovered",
"disabled": "Disabled",
"available_integrations": "Available integrations", "available_integrations": "Available integrations",
"new_flow": "Setup another instance of {integration}", "new_flow": "Setup another instance of {integration}",
"attention": "Attention required", "attention": "Attention required",