mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-20 07:46:37 +00:00
Align layout of all cards (#8931)
* Align layout of all cards * Make ignore card have normal button
This commit is contained in:
parent
25b3bb1285
commit
179767e9f8
@ -44,9 +44,10 @@ const createConfigEntry = (
|
|||||||
|
|
||||||
const createManifest = (
|
const createManifest = (
|
||||||
isCustom: boolean,
|
isCustom: boolean,
|
||||||
isCloud: boolean
|
isCloud: boolean,
|
||||||
|
name = "ESPHome"
|
||||||
): IntegrationManifest => ({
|
): IntegrationManifest => ({
|
||||||
name: "ESPHome",
|
name,
|
||||||
domain: "esphome",
|
domain: "esphome",
|
||||||
is_built_in: !isCustom,
|
is_built_in: !isCustom,
|
||||||
config_flow: false,
|
config_flow: false,
|
||||||
@ -103,7 +104,7 @@ const configFlows: DataEntryFlowProgressExtended[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
step_id: "discovery_confirm",
|
step_id: "discovery_confirm",
|
||||||
localized_title: "Roku: Living room Roku",
|
localized_title: "Living room Roku",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
flow_id: "adbb401329d8439ebb78ef29837826a8",
|
flow_id: "adbb401329d8439ebb78ef29837826a8",
|
||||||
@ -234,7 +235,8 @@ export class DemoIntegrationCard extends LitElement {
|
|||||||
.flow=${flow}
|
.flow=${flow}
|
||||||
.manifest=${createManifest(
|
.manifest=${createManifest(
|
||||||
this.isCustomIntegration,
|
this.isCustomIntegration,
|
||||||
this.isCloud
|
this.isCloud,
|
||||||
|
flow.handler === "roku" ? "Roku" : "Philips Hue"
|
||||||
)}
|
)}
|
||||||
></ha-config-flow-card>
|
></ha-config-flow-card>
|
||||||
`
|
`
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
import { mdiPackageVariant, mdiCloud } from "@mdi/js";
|
|
||||||
import "@polymer/paper-tooltip/paper-tooltip";
|
|
||||||
import { css, html } from "lit-element";
|
|
||||||
import { IntegrationManifest } from "../../../data/integration";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
|
|
||||||
export const haConfigIntegrationsStyles = css`
|
|
||||||
.banner {
|
|
||||||
background-color: var(--state-color);
|
|
||||||
color: var(--text-on-state-color);
|
|
||||||
text-align: center;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
.icons {
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
right: 16px;
|
|
||||||
color: var(--text-on-state-color, var(--secondary-text-color));
|
|
||||||
background-color: var(--state-color, #e0e0e0);
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
border-bottom-right-radius: 4px;
|
|
||||||
padding: 1px 4px 2px;
|
|
||||||
}
|
|
||||||
.icons ha-svg-icon {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
paper-tooltip {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const haConfigIntegrationRenderIcons = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
manifest?: IntegrationManifest
|
|
||||||
) => {
|
|
||||||
const icons: [string, string][] = [];
|
|
||||||
|
|
||||||
if (manifest) {
|
|
||||||
if (!manifest.is_built_in) {
|
|
||||||
icons.push([
|
|
||||||
mdiPackageVariant,
|
|
||||||
hass.localize(
|
|
||||||
"ui.panel.config.integrations.config_entry.provided_by_custom_integration"
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manifest.iot_class && manifest.iot_class.startsWith("cloud_")) {
|
|
||||||
icons.push([
|
|
||||||
mdiCloud,
|
|
||||||
hass.localize(
|
|
||||||
"ui.panel.config.integrations.config_entry.depends_on_cloud"
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return icons.length === 0
|
|
||||||
? ""
|
|
||||||
: html`
|
|
||||||
<div class="icons">
|
|
||||||
${icons.map(
|
|
||||||
([icon, description]) => html`
|
|
||||||
<span>
|
|
||||||
<ha-svg-icon .path=${icon}></ha-svg-icon>
|
|
||||||
<paper-tooltip animation-delay="0"
|
|
||||||
>${description}</paper-tooltip
|
|
||||||
>
|
|
||||||
</span>
|
|
||||||
`
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
};
|
|
@ -31,6 +31,7 @@ export class HaIgnoredConfigEntryCard extends LitElement {
|
|||||||
"ui.panel.config.integrations.ignore.ignored"
|
"ui.panel.config.integrations.ignore.ignored"
|
||||||
)}
|
)}
|
||||||
.domain=${this.entry.domain}
|
.domain=${this.entry.domain}
|
||||||
|
.localizedDomainName=${this.entry.localized_domain_name}
|
||||||
.label=${this.entry.title === "Ignored"
|
.label=${this.entry.title === "Ignored"
|
||||||
? // In 2020.2 we added support for entry.title. All ignored entries before
|
? // In 2020.2 we added support for entry.title. All ignored entries before
|
||||||
// that have title "Ignored" so we fallback to localized domain name.
|
// that have title "Ignored" so we fallback to localized domain name.
|
||||||
@ -38,7 +39,6 @@ export class HaIgnoredConfigEntryCard extends LitElement {
|
|||||||
: this.entry.title}
|
: this.entry.title}
|
||||||
>
|
>
|
||||||
<mwc-button
|
<mwc-button
|
||||||
unelevated
|
|
||||||
@click=${this._removeIgnoredIntegration}
|
@click=${this._removeIgnoredIntegration}
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.integrations.ignore.stop_ignore"
|
"ui.panel.config.integrations.ignore.stop_ignore"
|
||||||
|
@ -1,18 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
|
TemplateResult,
|
||||||
|
html,
|
||||||
customElement,
|
customElement,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
CSSResult,
|
|
||||||
css,
|
css,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { TemplateResult, html } from "lit-html";
|
import type { IntegrationManifest } from "../../../data/integration";
|
||||||
import { IntegrationManifest } from "../../../data/integration";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { HomeAssistant } from "../../../types";
|
import "./ha-integration-header";
|
||||||
import { brandsUrl } from "../../../util/brands-url";
|
|
||||||
import {
|
|
||||||
haConfigIntegrationRenderIcons,
|
|
||||||
haConfigIntegrationsStyles,
|
|
||||||
} from "./ha-config-integrations-common";
|
|
||||||
|
|
||||||
@customElement("ha-integration-action-card")
|
@customElement("ha-integration-action-card")
|
||||||
export class HaIntegrationActionCard extends LitElement {
|
export class HaIntegrationActionCard extends LitElement {
|
||||||
@ -20,6 +16,8 @@ export class HaIntegrationActionCard extends LitElement {
|
|||||||
|
|
||||||
@property() public banner!: string;
|
@property() public banner!: string;
|
||||||
|
|
||||||
|
@property() public localizedDomainName?: string;
|
||||||
|
|
||||||
@property() public domain!: string;
|
@property() public domain!: string;
|
||||||
|
|
||||||
@property() public label!: string;
|
@property() public label!: string;
|
||||||
@ -29,82 +27,47 @@ export class HaIntegrationActionCard extends LitElement {
|
|||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
return html`
|
return html`
|
||||||
<ha-card outlined>
|
<ha-card outlined>
|
||||||
<div class="banner">
|
<ha-integration-header
|
||||||
${this.banner}
|
.hass=${this.hass}
|
||||||
</div>
|
.banner=${this.banner}
|
||||||
<div class="content">
|
.domain=${this.domain}
|
||||||
${haConfigIntegrationRenderIcons(this.hass, this.manifest)}
|
.label=${this.label}
|
||||||
<div class="image">
|
.localizedDomainName=${this.localizedDomainName}
|
||||||
<img
|
.manifest=${this.manifest}
|
||||||
src=${brandsUrl(this.domain, "logo")}
|
></ha-integration-header>
|
||||||
referrerpolicy="no-referrer"
|
<div class="filler"></div>
|
||||||
@error=${this._onImageError}
|
|
||||||
@load=${this._onImageLoad}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<h2>${this.label}</h2>
|
|
||||||
</div>
|
|
||||||
<div class="actions"><slot></slot></div>
|
<div class="actions"><slot></slot></div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onImageLoad(ev) {
|
static styles = css`
|
||||||
ev.target.style.visibility = "initial";
|
ha-card {
|
||||||
}
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
private _onImageError(ev) {
|
height: 100%;
|
||||||
ev.target.style.visibility = "hidden";
|
--ha-card-border-color: var(--state-color);
|
||||||
}
|
--mdc-theme-primary: var(--state-color);
|
||||||
|
}
|
||||||
static get styles(): CSSResult[] {
|
.filler {
|
||||||
return [
|
flex: 1;
|
||||||
haConfigIntegrationsStyles,
|
}
|
||||||
css`
|
.attention {
|
||||||
ha-card {
|
--state-color: var(--error-color);
|
||||||
display: flex;
|
--text-on-state-color: var(--text-primary-color);
|
||||||
flex-direction: column;
|
}
|
||||||
height: 100%;
|
.discovered {
|
||||||
--ha-card-border-color: var(--state-color);
|
--state-color: var(--primary-color);
|
||||||
--mdc-theme-primary: var(--state-color);
|
--text-on-state-color: var(--text-primary-color);
|
||||||
}
|
}
|
||||||
.content {
|
.actions {
|
||||||
position: relative;
|
display: flex;
|
||||||
flex: 1;
|
justify-content: space-between;
|
||||||
}
|
align-items: center;
|
||||||
.image {
|
padding: 8px 6px 0;
|
||||||
height: 60px;
|
height: 48px;
|
||||||
margin-top: 16px;
|
}
|
||||||
display: flex;
|
`;
|
||||||
align-items: center;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
max-width: 90%;
|
|
||||||
max-height: 100%;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
text-align: center;
|
|
||||||
margin: 16px 8px 0;
|
|
||||||
}
|
|
||||||
.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);
|
|
||||||
}
|
|
||||||
.actions {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 8px 6px 0;
|
|
||||||
height: 48px;
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -31,7 +31,7 @@ import {
|
|||||||
} from "../../../data/config_entries";
|
} from "../../../data/config_entries";
|
||||||
import type { DeviceRegistryEntry } from "../../../data/device_registry";
|
import type { DeviceRegistryEntry } from "../../../data/device_registry";
|
||||||
import type { EntityRegistryEntry } from "../../../data/entity_registry";
|
import type { EntityRegistryEntry } from "../../../data/entity_registry";
|
||||||
import { domainToName, IntegrationManifest } from "../../../data/integration";
|
import type { IntegrationManifest } from "../../../data/integration";
|
||||||
import { showConfigEntrySystemOptionsDialog } from "../../../dialogs/config-entry-system-options/show-dialog-config-entry-system-options";
|
import { showConfigEntrySystemOptionsDialog } from "../../../dialogs/config-entry-system-options/show-dialog-config-entry-system-options";
|
||||||
import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
|
import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
|
||||||
import {
|
import {
|
||||||
@ -40,13 +40,9 @@ import {
|
|||||||
showPromptDialog,
|
showPromptDialog,
|
||||||
} from "../../../dialogs/generic/show-dialog-box";
|
} from "../../../dialogs/generic/show-dialog-box";
|
||||||
import { haStyle } from "../../../resources/styles";
|
import { haStyle } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import { brandsUrl } from "../../../util/brands-url";
|
import type { ConfigEntryExtended } from "./ha-config-integrations";
|
||||||
import { ConfigEntryExtended } from "./ha-config-integrations";
|
import "./ha-integration-header";
|
||||||
import {
|
|
||||||
haConfigIntegrationRenderIcons,
|
|
||||||
haConfigIntegrationsStyles,
|
|
||||||
} from "./ha-config-integrations-common";
|
|
||||||
|
|
||||||
const ERROR_STATES: ConfigEntry["state"][] = [
|
const ERROR_STATES: ConfigEntry["state"][] = [
|
||||||
"migration_error",
|
"migration_error",
|
||||||
@ -92,18 +88,6 @@ export class HaIntegrationCard extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let primary: string;
|
|
||||||
let secondary: string | undefined;
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
primary = item.title || item.localized_domain_name || this.domain;
|
|
||||||
if (primary !== item.localized_domain_name) {
|
|
||||||
secondary = item.localized_domain_name;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
primary = domainToName(this.hass.localize, this.domain, this.manifest);
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasItem = item !== undefined;
|
const hasItem = item !== undefined;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
@ -120,38 +104,32 @@ export class HaIntegrationCard extends LitElement {
|
|||||||
})}"
|
})}"
|
||||||
.configEntry=${item}
|
.configEntry=${item}
|
||||||
>
|
>
|
||||||
${this.disabled
|
<ha-integration-header
|
||||||
? html`
|
.hass=${this.hass}
|
||||||
<div class="banner">
|
.banner=${this.disabled
|
||||||
${this.hass.localize(
|
? this.hass.localize(
|
||||||
"ui.panel.config.integrations.config_entry.disable.disabled"
|
"ui.panel.config.integrations.config_entry.disable.disabled"
|
||||||
)}
|
)
|
||||||
</div>
|
: undefined}
|
||||||
`
|
.domain=${this.domain}
|
||||||
: ""}
|
.label=${item
|
||||||
${this.items.length > 1
|
? item.title || item.localized_domain_name || this.domain
|
||||||
? html`
|
: undefined}
|
||||||
<div class="back-btn">
|
.localizedDomainName=${item ? item.localized_domain_name : undefined}
|
||||||
<ha-icon-button
|
.manifest=${this.manifest}
|
||||||
icon="hass:chevron-left"
|
>
|
||||||
@click=${this._back}
|
${this.items.length > 1
|
||||||
></ha-icon-button>
|
? html`
|
||||||
</div>
|
<div class="back-btn" slot="above-header">
|
||||||
`
|
<ha-icon-button
|
||||||
: ""}
|
icon="hass:chevron-left"
|
||||||
<div class="header">
|
@click=${this._back}
|
||||||
<img
|
></ha-icon-button>
|
||||||
src=${brandsUrl(this.domain, "icon")}
|
</div>
|
||||||
referrerpolicy="no-referrer"
|
`
|
||||||
@error=${this._onImageError}
|
: ""}
|
||||||
@load=${this._onImageLoad}
|
</ha-integration-header>
|
||||||
/>
|
|
||||||
<div class="info">
|
|
||||||
<div class="primary">${primary}</div>
|
|
||||||
${secondary ? html`<div class="secondary">${secondary}</div>` : ""}
|
|
||||||
</div>
|
|
||||||
${haConfigIntegrationRenderIcons(this.hass, this.manifest)}
|
|
||||||
</div>
|
|
||||||
${item
|
${item
|
||||||
? this._renderSingleEntry(item)
|
? this._renderSingleEntry(item)
|
||||||
: this._renderGroupedIntegration()}
|
: this._renderGroupedIntegration()}
|
||||||
@ -441,14 +419,6 @@ export class HaIntegrationCard extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onImageLoad(ev) {
|
|
||||||
ev.target.style.visibility = "initial";
|
|
||||||
}
|
|
||||||
|
|
||||||
private _onImageError(ev) {
|
|
||||||
ev.target.style.visibility = "hidden";
|
|
||||||
}
|
|
||||||
|
|
||||||
private _showOptions(ev) {
|
private _showOptions(ev) {
|
||||||
showOptionsFlowDialog(this, ev.target.closest("ha-card").configEntry);
|
showOptionsFlowDialog(this, ev.target.closest("ha-card").configEntry);
|
||||||
}
|
}
|
||||||
@ -605,7 +575,6 @@ export class HaIntegrationCard extends LitElement {
|
|||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return [
|
return [
|
||||||
haStyle,
|
haStyle,
|
||||||
haConfigIntegrationsStyles,
|
|
||||||
css`
|
css`
|
||||||
ha-card {
|
ha-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -627,7 +596,7 @@ export class HaIntegrationCard extends LitElement {
|
|||||||
--state-message-color: var(--primary-text-color);
|
--state-message-color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
:host(.highlight) ha-card {
|
:host(.highlight) ha-card {
|
||||||
--state-color: var(--accent-color);
|
--state-color: var(--primary-color);
|
||||||
--text-on-state-color: var(--text-primary-color);
|
--text-on-state-color: var(--text-primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,36 +614,6 @@ export class HaIntegrationCard extends LitElement {
|
|||||||
height: 0px;
|
height: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
align-items: center;
|
|
||||||
padding: 16px 8px 8px 16px;
|
|
||||||
}
|
|
||||||
.header img {
|
|
||||||
margin-right: 16px;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
.header .info div,
|
|
||||||
paper-item-body {
|
|
||||||
word-wrap: break-word;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
.primary {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: var(--primary-text-color);
|
|
||||||
}
|
|
||||||
.secondary {
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
@ -724,6 +663,14 @@ export class HaIntegrationCard extends LitElement {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-height: 35px;
|
min-height: 35px;
|
||||||
}
|
}
|
||||||
|
paper-item-body {
|
||||||
|
word-wrap: break-word;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
mwc-list-item ha-svg-icon {
|
mwc-list-item ha-svg-icon {
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
}
|
}
|
||||||
|
174
src/panels/config/integrations/ha-integration-header.ts
Normal file
174
src/panels/config/integrations/ha-integration-header.ts
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
import { mdiPackageVariant, mdiCloud } from "@mdi/js";
|
||||||
|
import "@polymer/paper-tooltip/paper-tooltip";
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
html,
|
||||||
|
customElement,
|
||||||
|
property,
|
||||||
|
LitElement,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { domainToName, IntegrationManifest } from "../../../data/integration";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { brandsUrl } from "../../../util/brands-url";
|
||||||
|
|
||||||
|
@customElement("ha-integration-header")
|
||||||
|
export class HaIntegrationHeader extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public banner!: string;
|
||||||
|
|
||||||
|
@property() public localizedDomainName?: string;
|
||||||
|
|
||||||
|
@property() public domain!: string;
|
||||||
|
|
||||||
|
@property() public label!: string;
|
||||||
|
|
||||||
|
@property() public manifest?: IntegrationManifest;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
let primary: string;
|
||||||
|
let secondary: string | undefined;
|
||||||
|
|
||||||
|
const domainName =
|
||||||
|
this.localizedDomainName ||
|
||||||
|
domainToName(this.hass.localize, this.domain, this.manifest);
|
||||||
|
|
||||||
|
if (this.label) {
|
||||||
|
primary = this.label;
|
||||||
|
secondary = primary === domainName ? undefined : domainName;
|
||||||
|
} else {
|
||||||
|
primary = domainName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const icons: [string, string][] = [];
|
||||||
|
|
||||||
|
if (this.manifest) {
|
||||||
|
if (!this.manifest.is_built_in) {
|
||||||
|
icons.push([
|
||||||
|
mdiPackageVariant,
|
||||||
|
this.hass.localize(
|
||||||
|
"ui.panel.config.integrations.config_entry.provided_by_custom_integration"
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.manifest.iot_class &&
|
||||||
|
this.manifest.iot_class.startsWith("cloud_")
|
||||||
|
) {
|
||||||
|
icons.push([
|
||||||
|
mdiCloud,
|
||||||
|
this.hass.localize(
|
||||||
|
"ui.panel.config.integrations.config_entry.depends_on_cloud"
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
${!this.banner
|
||||||
|
? ""
|
||||||
|
: html`<div class="banner">
|
||||||
|
${this.banner}
|
||||||
|
</div>`}
|
||||||
|
<slot name="above-header"></slot>
|
||||||
|
<div class="header">
|
||||||
|
<img
|
||||||
|
src=${brandsUrl(this.domain, "icon")}
|
||||||
|
referrerpolicy="no-referrer"
|
||||||
|
@error=${this._onImageError}
|
||||||
|
@load=${this._onImageLoad}
|
||||||
|
/>
|
||||||
|
<div class="info">
|
||||||
|
<div class="primary">${primary}</div>
|
||||||
|
${secondary ? html`<div class="secondary">${secondary}</div>` : ""}
|
||||||
|
</div>
|
||||||
|
${icons.length === 0
|
||||||
|
? ""
|
||||||
|
: html`
|
||||||
|
<div class="icons">
|
||||||
|
${icons.map(
|
||||||
|
([icon, description]) => html`
|
||||||
|
<span>
|
||||||
|
<ha-svg-icon .path=${icon}></ha-svg-icon>
|
||||||
|
<paper-tooltip animation-delay="0"
|
||||||
|
>${description}</paper-tooltip
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onImageLoad(ev) {
|
||||||
|
ev.target.style.visibility = "initial";
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onImageError(ev) {
|
||||||
|
ev.target.style.visibility = "hidden";
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
.banner {
|
||||||
|
background-color: var(--state-color);
|
||||||
|
color: var(--text-on-state-color);
|
||||||
|
text-align: center;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16px 8px 8px 16px;
|
||||||
|
}
|
||||||
|
.header img {
|
||||||
|
margin-right: 16px;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
.header .info div {
|
||||||
|
word-wrap: break-word;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.primary {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
.secondary {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
.icons {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 16px;
|
||||||
|
color: var(--text-on-state-color, var(--secondary-text-color));
|
||||||
|
background-color: var(--state-color, #e0e0e0);
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
padding: 1px 4px 2px;
|
||||||
|
}
|
||||||
|
.icons ha-svg-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
paper-tooltip {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-integration-header": HaIntegrationHeader;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user